MaterialDesign-React

A React component that renders Material Design Icon path data as accessible, stylable SVG icons.

Library
npm
v1.6.1
150stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
36/100Needs Attention
Development Activity0
Maintenance0
Community64
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
61/100Good
Architecture65
Code Quality58
Innovation45
Learning Curve75

@mdi/react is the official React binding for the Material Design Icons project, exposing a single Icon component that turns an SVG path string (typically imported from the companion @mdi/js package) into a fully-formed <svg> element. Rather than shipping a giant icon font or a component per icon, the library takes a data-driven approach: consumers pass one of thousands of MDI path strings plus a small set of props, and the component handles sizing, coloring, rotation, flipping, and spin animation.

A second export, Stack, lets multiple Icon instances be layered into a single SVG canvas so composite badge-style icons (e.g. an icon with a small overlay glyph) can be built by nesting Icon children and letting Stack propagate shared size/color/rotation/spin values down to them. Accessibility is handled explicitly: when a title prop is supplied the rendered SVG gets role, aria-labelledby, and matching <title>/<desc> elements; without one it falls back to role="presentation" so decorative icons are correctly ignored by screen readers.

The package is intentionally minimal — its only runtime dependency is prop-types, React itself is a peer dependency, and the compiled output is a single small CommonJS bundle plus hand-written .d.ts type declarations, keeping it lightweight to add alongside any React icon workflow.

What You Get

  • An Icon component that renders any MDI path string as an accessible <svg>, with size, color, rotate, horizontal/vertical flip, and spin props handled entirely through generated inline styles and CSS keyframes
  • A Stack component that layers multiple Icon children into a single SVG viewport, propagating shared size/color/rotation/spin values down to each nested icon unless a child overrides them
  • Accessibility built in by default: supplying a title prop wires up role, aria-labelledby, and matching <title>/<desc> elements, while icons without a title are marked role="presentation"
  • TypeScript type declarations (Icon.d.ts, IconProps.d.ts, Stack.d.ts, StackProps.d.ts) shipped alongside PropTypes definitions, so both TS and plain-JS consumers get prop validation
  • A tiny runtime footprint — the only production dependency is prop-types, with React itself left as an external/peer dependency in the compiled bundle

Common Use Cases

  • Rendering any of the thousands of Material Design Icons in a React app without bundling an icon font or an entire SVG sprite sheet
  • Building icon buttons and inline icon+text UI, using the title prop to make icon-only buttons screen-reader accessible
  • Creating composite/badge icons (e.g. a base icon with a small overlay glyph in a corner) by nesting Icon elements inside a Stack
  • Adding lightweight loading/status indicators via the built-in spin prop instead of a separate spinner component
  • Applying consistent per-icon theming (size, color, rotation) across a design system by setting shared defaults once on a Stack wrapper

Under The Hood

Architecture The package exposes exactly two components from a single entry point (src/Icon.tsx, which re-exports Stack): Icon is a forwardRef function component that turns a raw SVG path string plus style-affecting props (size, color, rotate, horizontal/vertical flip, spin) into inline styles and a transform string applied to either the <path> directly or a wrapping <g> when the icon is rendered inside a Stack (tracked via the internal inStack prop); Stack composes multiple Icon children via React.Children.map and React.cloneElement, injecting shared size/color/rotation/spin values into each child unless the child already set its own. State is minimal — a module-level counter generates unique aria-labelledby/aria-describedby ids per rendered icon. The two-component surface, split prop-type definitions (IconProps.ts, StackProps.ts), and re-export pattern keep the architecture simple and easy to reason about, though the transform/style-building logic inside Icon itself is fairly dense for a single function.

Tech Stack Written in TypeScript (strict: true, targeting ES5) and compiled through Webpack 4 with ts-loader into a single CommonJS bundle (Icon.js) with a source map, keeping react and prop-types as externals so consumers supply their own React instance. The only runtime dependency is prop-types; React/React DOM appear solely as devDependencies for the test suite. Type declarations are produced by a separate tsc invocation (the build2 script) and shipped as hand-listed .d.ts files in package.json’s files array rather than through a bundler’s declaration-emit pipeline.

Code Quality Tests exist for both components (tests/Icon.spec.tsx, tests/Stack.spec.tsx) using Mocha, Chai assertions, and Enzyme with the React 16 adapter, run through ts-node under a dedicated CommonJS tsconfig; coverage is available via nyc. No CI workflow file is present in the repository, so it’s unclear whether these tests run automatically on push or PR. TypeScript strict mode plus noUnusedLocals/noUnusedParameters catch some classes of bugs at compile time, and PropTypes are declared redundantly alongside the TS types for plain-JS consumers. Linting is configured via tslint with tslint-config-airbnb and a Prettier rule — tslint itself has been deprecated in favor of ESLint for several years, indicating the tooling hasn’t been modernized.

API Design The public API is deliberately small: one required path prop plus a handful of optional, self-explanatory style props (size, color, rotate, horizontal, vertical, spin), all documented in a props table in the README with defaults and accepted types. Getting started requires no configuration beyond installing the package and its companion @mdi/js path-data package, and the Stack component reuses the exact same prop names as Icon so there’s nothing new to learn to layer icons. The main ergonomic wrinkle is implicit: supplying a description prop without a title throws at render time, which is documented behavior but only discoverable by reading the source or hitting the error.

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