Icon
Universal vector icon renderer with strict size tokens (xs to 3xl), numeric pixel scaling, semantic color tokens, and open SVG component wrapping.
// Plain markup
import { Icon } from "@shavin/ui";Interactive Playground
xl2px stroke
<Icon name="clock" size="xl" color="accent" strokeWidth={2} />Icon Name
Size Token
Color
Stroke Width
2pxSize Token Scale
xs (12px)
sm (16px)
md (20px)
lg (24px)
xl (32px)
2xl (40px)
import { Icon } from "@shavin/ui";
<Icon name="Sparkles" size="xs" color="accent" />
<Icon name="Sparkles" size="sm" color="accent" />
<Icon name="Sparkles" size="md" color="accent" />
<Icon name="Sparkles" size="lg" color="accent" />
<Icon name="Sparkles" size="xl" color="accent" />
<Icon name="Sparkles" size="2xl" color="accent" />Semantic Color Tokens
default
subtle
accent
contrast
success
warning
danger
import { Icon } from "@shavin/ui";
<Icon name="Shield" color="default" />
<Icon name="Shield" color="subtle" />
<Icon name="Shield" color="accent" />
<Icon name="Shield" color="contrast" />
<Icon name="Shield" color="success" />
<Icon name="Shield" color="warning" />
<Icon name="Shield" color="danger" />Direct Component Passing vs Name String
name="Zap"
icon={Heart}
import { Icon } from "@shavin/ui";
import { Zap, Heart } from "lucide-react";
// 1. By string name (dynamic lookups in builder & schema)
<Icon name="Zap" size="lg" color="warning" />
// 2. Direct component import (tree-shakeable in app code)
<Icon icon={Heart} size="lg" color="danger" />Custom & Native SVG Support
While @shavin/ui includes the full Lucide catalog by default, the <Icon /> primitive is completely open and accepts any custom vector graphic, inline SVG, or 3rd-party icon component (such as Radix Icons, Phosphor, FontAwesome, or custom company brandmarks).
1. Direct Custom Component Passing
Pass your custom React SVG component directly into the icon prop. It automatically inherits all size tokens, semantic colors, and accessibility attributes:
import { Icon } from "@shavin/ui";
import { MyCustomBrandmark } from "./MyCustomBrandmark";
export function Header() {
return (
<Icon
icon={MyCustomBrandmark}
size="xl"
color="accent"
aria-label="Company Brandmark"
/>
);
}2. Inline SVG Node Wrapping
You can also pass raw JSX SVG elements directly. <Icon /> wraps them cleanly with token classes and dimensional bounding:
import { Icon } from "@shavin/ui";
<Icon size="2xl" color="contrast">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2L2 22h20L12 2z" />
</svg>
</Icon>Props
| Prop | Type | Default |
|---|---|---|
| name | string | — |
| icon | LucideIcon | React.ElementType | React.ReactNode | — |
| size | IconSizeToken | number | string | "md" |
| color | IconColorToken | (string & {}) | "default" |
| strokeWidth | number | — |
| absoluteStrokeWidth | boolean | — |
| customSize | number | string | — |
| title | string | — |
| className | string | — |