Blog

Lucide vs Heroicons vs Radix Icons: Which to Pick in 2026

Head-to-head comparison of Lucide, Heroicons, Material Symbols, and Radix Icons for shadcn/ui projects — style, coverage, bundle size, and a clear verdict.

article··9 min read
Lucide vs Heroicons vs Radix Icons: Which to Pick in 2026

Read this first: shadcn/ui vs. shadcndesign.com (why it matters for icons)

There are two similarly named things in this ecosystem:

ui.shadcn.com: The official code project and CLI. When you run npx shadcn-ui@latest add button, it copies the React component source into your repository (no npm dependency). These components are pre-wired to Lucide by default via your components.json ("iconLibrary": "lucide").

shadcndesign.com: Our third-party, commercial Figma kit that mirrors the official shadcn/ui components for design work. It assumes Lucide in Figma for visual parity with the default code. Its "add custom icons" docs are about Figma workflows (publishing libraries, building components), not about changing your React imports or the shadcn/ui CLI.

Keep that split in mind: design-time (Figma) vs. runtime (React SVG components). Choosing an icon library affects code, while shadcndesign helps designers stay in sync with what developers see by default (Lucide). If you switch icon sets in code, coordinate your Figma assets (e.g., replace Lucide glyphs in the Figma library you use, whether it's shadcndesign or your own).

What this guide covers

  • How shadcn/ui wires icons by default
  • Where shadcndesign fits in the workflow
  • A comparison of Lucide (default), HeroIcons, Material Symbols, and Radix Icons
  • Practical integration workflows (from "do nothing" to full replacement)
  • Clear recommendations by project type

How shadcn/ui handles icons

shadcn/ui follows an "open code" model: the CLI copies component files into your repo. Those files import icons from lucide-react by default. The default is set in components.json (iconLibrary: "lucide"). If you keep Lucide, everything just works; both in code and, for design teams using shadcndesign, in Figma.

If you change icon libraries, you're changing imports inside your copied components (and you must keep doing that each time you add new shadcn/ui components). That's the primary friction point to plan for.

Where shadcndesign helps (and where it doesn't)

Helps: Gives designers a high-fidelity Figma kit aligned with shadcn/ui defaults (including Lucide look), so designs match code out of the box.

Doesn't: Change your React imports or the shadcn/ui CLI. If engineering adopts, say, HeroIcons in code, the design team should also update the Figma icon source (swap Lucide frames for HeroIcons or publish an internal icon library) to prevent drift. shadcndesign can still be your base kit; you'll just replace the icon assets it ships with.

Library 1: Lucide (default in shadcn/ui)

Style & scope: Clean, minimal, outline-only set (24×24, default 2px stroke). Large library (~1.6k+ icons).

DX: Import individual React components (tree-shakable). Props like size, color, and strokeWidth make it easy to tune weight and fit.

A11y: Guidance provided; developers control aria-hidden, labels, and context.

License: ISC (permissive).

Pros

  • Zero-friction with shadcn/ui components and shadcndesign Figma defaults.
  • Big set; rarely blocked by missing glyphs.
  • strokeWidth prop is great for matching visual weight.

Cons

  • Outline-only (no solid/filled variants).
  • Occasional name collisions in imports (Link, etc.).

Use when

  • You want the simplest path from design (shadcndesign Figma) to code (shadcn/ui defaults).
  • You value a large, consistent set and minimal maintenance.

Library 2: HeroIcons (Tailwind-native look)

Style & scope: Designed by Tailwind Labs. Offers Outline, Solid, plus Mini/Micro sizes. Smaller, curated set (~300 unique glyphs).

DX: Install @heroicons/react or add per-icon SVGs using the community shadcn registry.

A11y: Sensible default of aria-hidden="true" for decorative icons.

License: MIT.

Pros

  • Solid + Outline variants; ideal for toggle/active states.
  • Visual match with Tailwind/UI patterns; looks at home in shadcn/ui apps.
  • Good defaults for accessibility.

Cons

  • Smaller library; you may need custom icons for edge cases.
  • No strokeWidth prop (less granular weight control than Lucide).

Design note with shadcndesign

If your design team uses shadcndesign's Figma kit, replace Lucide frames with a HeroIcons library (publish your own Figma icon library or swap components) so design and code stay aligned.

Use when

  • You want a Tailwind-native look and two-state icon UX.
  • Marketing sites or product UIs where polished state transitions matter.

Library 3: Material Symbols (variable font power)

Style & scope: Massive set (2,500+). Unique variable font axes: FILL (outline↔filled), wght, GRAD, opsz.

DX: Best used as a font (span + CSS font-variation-settings). Inline SVG use is possible, but you lose the variable axes—that's most of the value.

A11y: Backed by thorough Material Design guidance.

License: Apache 2.0.

Pros

  • Unmatched programmatic control (weight, grade, optical size).
  • Huge coverage for enterprise apps.
  • Maintained by Google.

Cons

  • The ideal workflow is font-based, which doesn't align with shadcn/ui's inline-SVG component pattern.
  • Using static SVGs removes the variable-font advantages.

Design note with shadcndesign

If you adopt Material Symbols, your design team should maintain a Material Symbols Figma library and phase out Lucide frames in shadcndesign-based files. Expect a forked process.

Use when

  • Data-dense, enterprise UIs benefit from subtle icon emphasis/de-emphasis.
  • You're okay adopting a different technical path (font) for icons.

Library 4: Radix Icons (primitives-aligned, accessibility-first)

Style & scope: Purpose-built for dense UIs on a 15×15 grid (~330 icons).

DX: Import from @radix-ui/react-icons.

A11y: The standout: AccessibleIcon utility from Radix enforces proper labeling patterns.

License: MIT.

Pros

  • Best-in-class accessibility approach when paired with AccessibleIcon.
  • Philosophically aligned with Radix primitives used under the hood in many shadcn/ui components.
  • Crisp at small sizes; great for admin/productivity tools.

Cons

  • Smaller set; gaps likely in general-purpose apps.
  • 15×15 grid may require visual tweaks when mixed with 24×24 components.

Design note with shadcndesign

If you move to Radix Icons, provide designers a Radix-based Figma set (or swap icon instances) inside your shadcndesign file to keep parity.

Use when

  • Accessibility is a hard requirement (gov/finance/healthcare).
  • Your UI favors compact, data-dense layouts.

Integration workflows (from simplest to deliberate)

1) Do nothing (Lucide default)

What: Keep Lucide. Add shadcn components as usual.

Why: Zero friction; perfect parity with shadcndesign's default visuals.

Risk: None. You're opting into outline-only.

What: Install another library (e.g., @heroicons/react), remove Lucide, and edit every copied shadcn component to swap imports. Repeat whenever you add new components.

Why: Single dependency.

Risk: Ongoing maintenance burden; you've effectively forked the library.

3) Hybrid per-icon adds (quick, but inconsistent)

What: Keep Lucide default; add specific icons from another set via the shadcn community registry (per-icon SVG components).

Why: Solve gaps fast without new npm deps.

Risk: Style drift (mix of sets/sizes). Designers using shadcndesign may not see the mixed set unless you maintain a mirrored Figma icon library.

What: Pick one library (e.g., HeroIcons). Remove lucide-react. Add needed SVGs via the registry one by one. Whenever you add a shadcn component, swap its icon import to your local icon component.

Why: Consistency without forking an npm dependency.

Design pairing: In shadcndesign, replace Lucide icons with your chosen set (publish a Figma icon library for the team).

Risk: Manual, but controlled. The right kind of friction.

Quick comparison table

FeatureLucideHeroIconsMaterial SymbolsRadix Icons
StyleOutline-onlyOutline + Solid (+ Mini/Micro)Variable font (fill/weight/grade/opsz)Outline (15×15)
Size (approx.)1,600+~3002,500+~330
Best fitDefault parity with shadcn/ui & shadcndesignTailwind-native look with two-state UXEnterprise control & density (font workflow)A11y-critical, compact UIs
DX notesstrokeWidth prop; tree-shakableSmaller set; good a11y defaultsIdeal as a font, not inline SVGAccessibleIcon utility
LicenseISCMITApache 2.0MIT

Recommendations by scenario

General web app / startup MVP

Stick with Lucide. It's the default, it matches shadcndesign's icons in Figma, and it removes overhead.

Brand-forward site or product UI with rich states

Go HeroIcons. You get Solid + Outline for clear feedback. Pair it with a HeroIcons Figma library inside your shadcndesign file so design matches code.

Data-dense enterprise SaaS

If you'll leverage variable axes and can adopt the font workflow, Material Symbols is powerful. Keep in mind you'll need a coordinated Figma icon library (and likely won't use shadcndesign's default Lucide icons).

Accessibility-critical applications

Choose Radix Icons and enforce labeling with AccessibleIcon. Update your shadcndesign-based Figma library to match.

How to keep design and code in sync when not using Lucide

  1. Publish a Figma icon library for your chosen set (HeroIcons, Material, Radix).
  2. In your shadcndesign file, swap icon instances (or detach and replace) so the component gallery now previews your real icon set.
  3. Document icon usage (outline/solid patterns, sizing, color) so designers and developers use the same rules.
  4. In code, adopt Workflow #4 (single-source custom). Keep icons as owned source components, not hidden behind npm, to match the shadcn philosophy.

Bottom line

  • If you want speed and alignment with both shadcn/ui and shadcndesign, Lucide is the smoothest path.
  • If you want two-state UX and a Tailwind-native look, use HeroIcons and mirror it in Figma.
  • If you need fine-grained, programmatic control for complex dashboards and can accept a different font-based path, Material Symbols is unmatched.
  • If accessibility is the priority, Radix Icons plus AccessibleIcon is the cleanest, most explicit pattern.

Whatever you pick, treat icons as a single source of truth across design and code: choose one set, wire it into the shadcn components with intention, and keep your Figma library (whether shadcndesign or custom) in lockstep.

MW
Matt Wierzbicki

Founder @ shadcndesign.com

Level-up your workflow today

One-time payment
14 days refund policy