Icon
One icon from a typed registry, so the icon family can be swapped in one file.
On this page
- GitHub
import { Icon } from "@/components/Icon";
import { Stack } from "@/components/Stack";
export function IconExample() {
return (
<Stack as="ul" direction="horizontal" gap="md">
<li>
<Icon name="mail" /> Email
</li>
<li>
<Icon name="github" /> GitHub
</li>
<li>
<Icon name="linkedin" /> LinkedIn
</li>
</Stack>
);
}Examples
Registry
sunmoonexternal-linkarrow-leftarrow-rightarrow-upchevron-downcheckcopylinkedingithubmailwarningsearchclosepalettedownloaduploadresettrashmenupauseplay
Sizes
inherit (1em)sm (1rem)md (1.25rem)lg (1.5rem)
Weights
lightregularboldfillduotone
Inherits text size
Heading-size text, heading-size icon
Small text, small icon
Takes text color
Decorative, inline in running text
Deployed through GitHub Actions.
Props
Any native prop not listed here goes to the root element unchanged.
SVG attributes (fill, stroke, viewBox, width, height, transform) and children also reach the <svg> as escape hatches: fill replaces currentColor; viewBox and children depend on the icon family's 256-unit grid; width and height are overridden by the size classes, so size an icon with the size prop or a class. Children must not be focusable or include <title> or <desc>: the name comes only from label.
| Prop | Type | Default | Description |
|---|---|---|---|
name | "sun" | "moon" | "external-link" | "arrow-left" | "arrow-right" | "arrow-up" | "chevron-down" | "check" | "copy" | "linkedin" | "github" | "mail" | "warning" | "search" | "close" | "palette" | "download" | "upload" | "reset" | "trash" | "menu" | "pause" | "play" | — | A registry name. Anything else is a type error. |
label | string | — | Accessible name. Without one the icon is decorative and hidden. |
size | "inherit" | "sm" | "md" | "lg" | "inherit" | inherit follows the text size (1em); the others use size.icon.*. |
weight | "light" | "regular" | "bold" | "fill" | "duotone" | "regular" | Normalized weight, mapped onto the icon family's own weights. |
Component tokens
None. Size comes from the size prop (size.icon.*), color from currentColor, and the default weight is a registry constant.
Accessibility
- Decorative by default: aria-hidden and not focusable.
- Never focusable, and named only by label: aria-labelledby and tabIndex are blocked.
- With label: role="img", named by the label.
- Colored by currentColor unless fill is passed, so it matches its text's contrast. A custom fill on a labelled icon must meet 3:1 against its background.
- Where a visible caption names an icon, the icon stays decorative so the name isn't announced twice.