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

2px

Size Token Scale

xs (12px)
sm (16px)
md (20px)
lg (24px)
xl (32px)
2xl (40px)
Component Source
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
Component Source
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}
Component Source
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

PropTypeDefaultDescription
namestring—Name of the icon in Lucide / Shavin icon set (e.g. "Sparkles", "Search", "arrow-right").
iconLucideIcon | React.ElementType | React.ReactNode—Direct icon component or custom React node to render.
sizeIconSizeToken | number | string"md"Size token (xs, sm, md, lg, xl, 2xl, 3xl) or custom numeric pixel value (16-256) or CSS size string.
colorIconColorToken | (string & {})"inherit"Semantic color token or custom hex/CSS color string. Defaults to "inherit" (currentColor), so an icon always takes the colour of its parent (buttons, tabs, chips, filled accent surfaces).
strokeWidthnumber2)Stroke width for vector lines (from 0.5 to 3.0 in 0.25 steps, default 2).
absoluteStrokeWidthboolean—Whether stroke width remains absolute regardless of scaling.
customSizenumber | string—Custom pixel or CSS size override if not using size prop.
titlestring—Optional title for accessibility hover tooltip.
classNamestring——
Configure Theme
Theme
Accent Color
Custom
Gray Family
Appearance
Radius
Scaling
Panel Style
Heading Font
Body Font