Phosphor Icons Webcomponents

Framework-agnostic custom elements for over 9,000 Phosphor icons, styled entirely through HTML attributes.

Library
npm
v2.1.5
28stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
27/100Needs Attention
Development Activity0
Maintenance20
Community16
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture68
Code Quality45
Innovation80
Learning Curve65

@phosphor-icons/webcomponents packages the entire Phosphor icon set as native Custom Elements built with Lit, so any icon renders as a plain <ph-icon-name> tag in any HTML document or framework that supports the Custom Elements v1 spec. Each generated component ships all six Phosphor weights - thin, light, regular, bold, fill, and duotone - precompiled into itself, and exposes size, weight, color, and mirrored as reactive attributes so styling never needs JavaScript beyond adding the <script type=“module”> tag or running an npm install.

The package itself contains almost no hand-written runtime code: a small assemble.ts codegen script pulls SVG source data from the @phosphor-icons/core git submodule and mechanically emits one LitElement subclass per icon plus a matching TypeScript export, so the whole component index regenerates automatically whenever the core icon set changes. That trade-off makes updates trivial but leaves the shipped package without any tests of its own beyond the codegen’s icon-verification pass.

What You Get

  • 9,000+ generated icon elements - one Lit-based custom element per Phosphor icon, importable individually or as the full bundle.
  • Six icon weights per icon - thin, light, regular, bold, fill, and duotone SVGs precompiled into each component’s static weight map.
  • Attribute-driven styling - size, weight, color, and mirrored props reflect directly to HTML attributes, so no JS API is needed to restyle an icon.
  • Dual ESM/CJS builds with full TypeScript typings - published via package.json’s exports map for both import and require() entry points.

Common Use Cases

  • Framework-agnostic design systems - teams shipping icons to multiple frontend stacks (or none) via a single Custom Elements dependency instead of per-framework icon packages.
  • CDN-loaded marketing/landing pages - dropping a single <script type=“module”> tag onto a static site to get thousands of icons with zero bundler setup.
  • Astro, Svelte, or vanilla JS apps - projects outside the React/Vue ecosystem that still want Phosphor’s icon set without a framework-specific wrapper library.
  • Dynamic weight/color theming - UIs that toggle icon state (e.g. filled vs. outline) purely by swapping the weight attribute at runtime.

Under The Hood

Architecture The package is a thin, codegen-driven fan-out with no runtime logic layer of its own. scripts/assemble.ts updates the @phosphor-icons/core git submodule, reads its SVG asset map via helpers re-exported from scripts/index.ts, and for each icon mechanically writes one LitElement subclass into src/icons/PhName.ts plus a matching re-export line into src/index.ts and a demo entry into a generated index.html. Every generated component (e.g. PhHorse) extends LitElement, holds a static Map from IconWeight to precompiled Lit svg templates for all six weights, and exposes size/weight/color/mirrored as reflected reactive properties around a single <svg> host styled with display:contents. All of the project’s “logic” therefore lives in the build-time generator rather than in the shipped runtime, which is shallow but internally consistent.

Tech Stack TypeScript targets ES2017/ESNext, built and served in development via Vite 5.2, with tsc used only for emitDeclarationOnly type generation. The sole runtime dependency is lit ^3, used for its reactive custom-element base class and html/svg/css tagged templates. tsx runs the assemble.ts codegen script, chalk provides its console output, and Prettier enforces formatting; pnpm manages the workspace (pnpm-lock.yaml). The canonical icon SVGs live in a linked @phosphor-icons/core git submodule rather than being duplicated in this repo. The build ships dual ESM (dist/index.mjs) and CJS (dist/index.cjs) entry points plus .d.ts typings through package.json’s exports map, and works with any Custom Elements v1-compatible environment.

Code Quality No test files or test runner are configured anywhere in the repository, and no CI workflow was found under .github/ - only an issue template and a funding file. Error handling is limited to try/catch blocks around the codegen script’s file-system writes and its git submodule update step; the shipped icon components themselves contain no conditional logic to fail. TypeScript is configured with strict mode plus noUnusedLocals, noUnusedParameters, noImplicitReturns, and noFallthroughCasesInSwitch, and Prettier keeps formatting consistent, but there is no automated verification (linting, tests, or CI) enforcing any of it on every change.

API Design The developer-facing surface is deliberately minimal: consumers either add one CDN <script type=“module”> tag or npm-install the package, then import whichever icon paths they need (or the whole index) and use plain kebab-case ph-name custom elements in markup. Styling is entirely attribute-based (size, color, weight, mirrored) with no imperative API, matching the ergonomics of a native HTML element rather than a component library’s props/JSX surface. Naming is fully consistent and predictable (Ph-prefixed PascalCase exports, ph- prefixed tag names), and the README documents the full attribute surface in a few short lines, keeping the learning curve very low for anyone already comfortable with HTML.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search