Docs · Motion, icons and 3D
Hugeicons
The icon set, the Icon wrapper and how to find icons.
Every icon comes from Hugeicons: the free set has over 4,000 stroke icons. They're drawn with currentColor, so they take the text color around them.
Install
Two packages: the React renderer and the icon data.
pnpm add @hugeicons/react @hugeicons/core-free-iconsThe icon package exports every icon from one file. Tell Next.js to load only the ones you import:
next.config.ts
experimental: { optimizePackageImports: ["@hugeicons/core-free-icons"],},The Icon wrapper
Components never use HugeiconsIcon directly. They use Icon, which fixes the stroke width and sizes:
src/components/ui/icon.tsx
import { HugeiconsIcon, type IconSvgElement } from "@hugeicons/react"; const SIZES = { xs: 14, sm: 16, md: 20, lg: 24, xl: 32 } as const; export type IconSize = keyof typeof SIZES; export type IconProps = { icon: IconSvgElement; /** sm 16 · md 20 (default) · lg 24, per design.md §7 */ size?: IconSize | number; /** Set for meaningful icons. Omit for decorative icons next to visible text. */ label?: string; className?: string; strokeWidth?: number;}; /** * Hugeicons wrapper. Icons draw with currentColor, so set color on the parent * (e.g. `text-fg-muted`) instead of on the icon. */export function Icon({ icon, size = "md", label, className, strokeWidth = 1.5,}: IconProps) { const px = typeof size === "number" ? size : SIZES[size]; return ( <HugeiconsIcon icon={icon} size={px} strokeWidth={strokeWidth} color="currentColor" className={className ? `shrink-0 ${className}` : "shrink-0"} aria-hidden={label ? undefined : true} aria-label={label} role={label ? "img" : undefined} /> );} export type { IconSvgElement };| Size | Pixels | Use for |
|---|---|---|
xs | 14 | Badges, inline hints |
sm | 16 | Buttons, menus, dense UI |
md | 20 | Default |
lg | 24 | Headers, empty states |
xl | 32 | Illustrative spots |
Use an icon
Icons in practice
import { Home01Icon, Notification02Icon } from "@hugeicons/core-free-icons";import { Icon } from "@/components/ui/icon"; // Decorative, next to visible text: no label<span className="flex items-center gap-2 text-fg-secondary"> <Icon icon={Home01Icon} size="sm" /> Home</span> // The only content of a button: give it a name<button aria-label="Notifications"> <Icon icon={Notification02Icon} /></button>- Set color on the parent (
text-primary), not on the icon. - Icon-only buttons need an
aria-label, or passlabeltoIcon. - Never use an icon as the only sign of a status; add text.
Find icons
Search at hugeicons.com and filter to the free stroke style. The import name is the icon's name in PascalCase with Icon on the end, for example Wallet01Icon. Your editor's autocomplete on @hugeicons/core-free-icons works too.