MaterialDesign-React
A React component that renders Material Design Icon path data as accessible, stylable SVG icons.
Repository Health
Technical Analysis
@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
Iconcomponent that renders any MDI path string as an accessible<svg>, withsize,color,rotate,horizontal/verticalflip, andspinprops handled entirely through generated inline styles and CSS keyframes - A
Stackcomponent that layers multipleIconchildren 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
titleprop wires uprole,aria-labelledby, and matching<title>/<desc>elements, while icons without a title are markedrole="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
titleprop 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
Iconelements inside aStack - Adding lightweight loading/status indicators via the built-in
spinprop 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
Stackwrapper
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.
Used by 2 apps in this directory
Notesnook
Note Taking · File Storage · Security
End-to-end encrypted, open-source note-taking where your data stays yours — even from the server.
Owlistic
Note Taking · Productivity
Self-hosted, open-source real-time note-taking and task management with WYSIWYG editing, live sync, and role-based access control.