Everything about icons in shadcn/ui: where Lucide fits in, how to swap in another icon library, sizing and color tweaks, and keeping Figma in sync with code.
Ever shipped a page and realize every icon looks a little different? One is heavier, one sits a pixel off, and another won't match dark mode. This guide keeps it simple. We'll look at the default Lucide icons you get in the shadcndesign.com Figma kit, how those map to shadcn/ui, and how to add other icon sets using their official npm packages. We'll also cover the basics: installing via npm (not third-party registries), changing size, stroke, and color, and dropping icons into buttons and input groups without breaking layout or accessibility.
Default choice: shadcn/ui ships with Lucide. The shadcndesign.com Figma kit uses Lucide too, so design and code match.
Other options: If you want a different style (solid variants, different weights, specialty sets), choose a reputable library and install it from its official npm package (for example, lucide-react, @heroicons/react, @radix-ui/react-icons, @tabler/icons-react, phosphor-react). Import only the icons you use so bundles stay small.
Customization: Adjust size, stroke width, and color through simple props and your Tailwind tokens.
Placement: Use icons before or after text in a button, or as prefix/suffix inside an input group. Keep spacing, contrast, and focus states consistent.
Lucide is a clean, outline-style set that covers most common needs. In shadcn/ui, Lucide is the default because it is:
Because the shadcndesign.com kit uses Lucide in Figma, what designers see in the file is what developers render in code. That keeps handoff calm: the same names, the same look, and fewer surprises.
Good use cases: navigation, toolbars, lists, menus, settings, empty states, and small inline cues inside forms.
Watch out for: Lucide is outline-only. If your brand often flips between outline and solid states for selected vs unselected, you may want a set that has both styles for the same glyph.
If you're choosing a set for a new project, use three simple checks:
Tip for mixed surfaces: If you must split styles, keep product UI on one set and marketing on another. Do not mix on the same surface.
Below are quick install notes for common choices. Always import only the icons you actually use.
Install: npm i lucide-react
Import pattern: import { Camera } from "lucide-react"
Good to know: Outline-only; supports size, color (inherits currentColor), and strokeWidth.
Install: npm i @heroicons/react
Import pattern:
import { CameraIcon } from "@heroicons/react/24/outline"import { CameraIcon as CameraSolid } from "@heroicons/react/24/solid"Good to know: Great for toggling states (outline ↔ solid) with a matched style.
Install: npm i @radix-ui/react-icons
Import pattern: import { Cross1Icon } from "@radix-ui/react-icons"
Optional a11y helper: npm i @radix-ui/react-accessible-icon
Good to know: Crisp in dense apps; pair with AccessibleIcon for easy labeling.
Install: npm i @tabler/icons-react
Import pattern: import { IconCamera } from "@tabler/icons-react"
Good to know: Consistent outlines and broad coverage.
Install: npm i phosphor-react
Import pattern: import { Camera } from "phosphor-react"
Good to know: Switch weights (thin → bold) and fills for expressive states.
Team hygiene: Keep a short doc that lists the approved library, icon sizes per control, stroke rules, and where icon files live in the repo. Import icons individually so builds stay lean.
Stick to a small scale that matches your type and spacing, for example: 14, 16, 18, 20, 24.
Buttons and inputs should have a default icon size per size variant.
currentColor from text. Theme with tokens like text-muted-foreground, text-primary, or text-destructive.Accessibility reminder: Color is not the only cue. Pair with labels or state changes.
One spacing token between icon and text. Same rule across sizes.
Add a tooltip and an accessible label.
Because shadcndesign.com uses Lucide and shadcn/ui defaults to Lucide, the Figma-to-code path is smooth:
If you want a different set in Figma while still using shadcn/ui, there are two easy paths. Both keep your design workflow clean and organized.
Now your icons live alongside the kit with clear naming and component structure.
Requires Figma Pro/Org
Why do this:
Prefer staying within your chosen library. If you truly need a single glyph from another set, install that library via npm, import just the one icon, and document the exception. If one-offs become common, switch the whole surface (e.g., an entire feature area) to a single alternative set and mirror that choice in Figma using one of the methods above.
Icons should be quiet helpers, not the star. With shadcn/ui and the shadcndesign.com Figma kit, the default path is simple: stick with Lucide, keep sizes and tokens tight, and place icons where they add clarity. If you need something different, integrate your set into Figma using manual components or a Team Library, and add the library to code from its official npm package. Pick once, document it, and keep the look steady. That is how you ship calm, professional UI without wrestling with icons every sprint.
Founder @ shadcndesign.com

A practical guide to theming shadcn/ui with CSS variables: OKLCH tokens, dark mode, custom brand palettes, and applying a full theme in minutes.

How shadcn/ui charts actually work: what ChartContainer does, how ChartConfig drives colors, and what breaks when you move from Recharts 2 to Recharts 3.

How shadcn/ui registries actually work: registry.json, URL resolution, styles, and namespaces — explained by a team that runs a production registry.