Material Symbols React
Use Google's Material Symbols in React — every style, weight and fill, fully tree-shakeable, zero runtime dependencies.
- Installation
- Usage
- Tree-shaking & bundle size
- Finding icons (for agents & tooling)
- ESM only
- Migrating from v1
- How it works
- License
Installation
npm install @nine-thirty-five/material-symbols-react
# or: yarn add … / pnpm add …Requires React 18 or 19 (peer dependency).
Usage
Material Symbols come in three styles (outlined, rounded, sharp), seven weights
(100–700), and two fills (outlined / filled). Each combination is its own import path, so
your bundler only ships the exact icons you use.
Importing
// Default weight (400)
import { Search } from '@nine-thirty-five/material-symbols-react/outlined';
import { Home } from '@nine-thirty-five/material-symbols-react/outlined/filled';
// Specific weight
import { Star } from '@nine-thirty-five/material-symbols-react/rounded/300';
import { Favorite } from '@nine-thirty-five/material-symbols-react/rounded/700/filled';
// Sharp style
import { Delete } from '@nine-thirty-five/material-symbols-react/sharp/500';function Toolbar() {
return (
<>
<Search />
<Star size={32} />
<Favorite color="crimson" />
</>
);
}Weights
Import paths follow the pattern …/{style}[/{weight}][/filled]:
| Path | Style | Weight | Fill |
|---|---|---|---|
…/outlined |
outlined | 400 | 0 |
…/outlined/filled |
outlined | 400 | 1 |
…/outlined/300 |
outlined | 300 | 0 |
…/rounded/700/filled |
rounded | 700 | 1 |
…/sharp/100 |
sharp | 100 | 0 |
Styles: outlined, rounded, sharp. Weights: 100, 200, 300, 400, 500, 600,
700 (the bare path defaults to 400). Append /filled for the filled variant.
Props
Every icon accepts all SVG props (SVGProps<SVGSVGElement>), plus a convenience size prop:
<Search size={32} /> {/* sets width and height */}
<Search /> {/* defaults to 1em — scales with font-size */}
<Search color="red" /> {/* icons use fill="currentColor" */}
<Search className="icon" />
<Search style={{ verticalAlign: 'middle' }} />
<Search onClick={…} aria-label="Search" />size—number | string. Sets bothwidthandheight. Defaults to"1em", so icons scale with the surroundingfont-size. Passwidth/heightexplicitly to override.- Color — icons render with
fill="currentColor", so they inheritcolorfrom CSS.
Tree-shaking & bundle size
Each icon is a one-line module (base("<path>")) over a single shared component, marked
/*#__PURE__*/ in a "sideEffects": false package. Importing one icon at one weight ships only
that path — not the rest of the set, and not other weights. Works with Vite, Next.js, webpack,
esbuild, Parcel, and Rollup.
Finding icons (for agents & tooling)
Every install ships a searchable catalog at …/manifest.json
(node_modules/@nine-thirty-five/material-symbols-react/dist/manifest.json). Each
entry has the icon name, its exported component, categories, and rich tags
(synonyms) — so a tool or coding agent can resolve a natural-language request to a
component offline, no API calls:
{
"importPattern": "import { <component> } from '@nine-thirty-five/material-symbols-react/<style>[/<weight>][/filled]'",
"styles": ["outlined", "rounded", "sharp"],
"weights": [100, 200, 300, 400, 500, 600, 700],
"defaultWeight": 400,
"icons": [
{
"name": "add",
"component": "Add",
"categories": ["…"],
"tags": ["add", "create", "new", "plus", "+"],
},
],
}For example, to satisfy "add a create icon to the button": match create against
tags, pick Add, and import it:
import { Add } from '@nine-thirty-five/material-symbols-react/outlined';
<button>
<Add /> Create
</button>;The catalog is also importable directly:
import manifest from '@nine-thirty-five/material-symbols-react/manifest.json' with { type: 'json' };ESM only
This package ships ES Modules only. It works in all modern bundlers and ESM Node. If you need
to consume it from a CommonJS module under node16/nodenext resolution, use a dynamic
import().
Migrating from v1
v2 adds the weight axis and a few ergonomic changes:
- Existing imports keep working.
…/outlinedand…/outlined/filledstill resolve to weight 400, exactly as before. - Default size changed from
24to1em. Icons now scale withfont-size. To restore the old fixed size, passsize={24}(or setwidth/height). - New
sizeprop and new weight entrypoints (/100–/700). - 14 icon names corrected (a v1 bug dropped a bare
0), e.g.SpeedFivex → SpeedZeroFivex. - ESM-only (v1 was effectively ESM too; the broken CJS
mainfield has been removed).
Automatic upgrade (codemod)
Run the bundled codemod to apply the size and rename changes for you:
npx jscodeshift -t node_modules/@nine-thirty-five/material-symbols-react/codemods/v1-to-v2.cjs \
--parser tsx src/It adds size={24} to icons that relied on the old default and renames the 14 corrected
components. Pass --size=skip to adopt the new 1em default instead.
How it works
Icons are generated from Google's official artifacts — the icon list from the
Material Symbols metadata API and the SVGs from the
fonts.gstatic.com CDN. The generator extracts each path, optimizes it with SVGO, and emits the
dist tree directly. No web scraping, no headless browser. See CONTRIBUTING.md.
License
Material design icons are created by Google.
We have made these icons available for you to incorporate into your products under the Apache License Version 2.0. Feel free to remix and re-share these icons and documentation in your products. We'd love attribution in your app's about screen, but it's not required.