Icon
One wrapper for the library's glyphs: size, tone and accessibility settled in one place, plus the named set it draws with.
@luc/uiExamples
Five sizes
A size is a role, not a pixel count: `xs` is inline in text, `xl` is a mark. The wrapper owns the scale, so an icon matches the text beside it without the caller guessing a number.
<Icon name="star" size="xs" />
<Icon name="star" size="sm" />
<Icon name="star" size="md" />
<Icon name="star" size="lg" />
<Icon name="star" size="xl" />Tones, and a name when the icon is the content
Tone is semantic and resolves to a `--fg-*` token, so it follows the theme. The last one carries a `label`, which makes it an image with a name instead of decoration.
<Icon name="check" tone="positive" size="lg" />
<Icon name="alert" tone="warning" size="lg" />
<Icon name="error" tone="negative" size="lg" />
<Icon name="info" tone="info" size="lg" />
<Icon name="sparkle" tone="accent" size="lg" />
<Icon name="lock" tone="primary" size="lg" label="Encrypted at rest" />Any glyph, and one that is still working
`name` addresses the curated set the library draws with; `icon` takes any Remix Icon component. `spin` is for work in flight, and it stops under reduced motion.
<Icon icon={RiStarLine} size="lg" tone="warning" />
<Icon icon={RiShareLine} size="lg" tone="muted" />
<Icon icon={RiRefreshLine} size="lg" tone="accent" spin />The set, searchable
Names and keywords in both languages, because the person looking for an icon may type either one.
39 of 39 icons
addalertarrow-downarrow-leftarrow-rightarrow-upbellcalendarchartcheckclosecodecopydeletedownloaddragerrorexternaleyeeye-offfilterfullscreeninfolinklockmoonmorepauseplayrefreshsearchsettingssparklestarsuntabletimeuploaduser
import { Icon, searchIcons } from "@luc/ui";
const names = searchIcons(query); // name and keyword, both languages
names.map((name) => <Icon key={name} name={name} />);Usage
import { Icon } from "@luc/ui";<Icon name="search" size="lg" tone="muted" />Package setup — peer requirements, the stylesheet and the provider — is on installation.
API
Read from the published TypeScript API, so a prop that is not listed here does not exist and a default that is listed is the one the compiler sees.
| Export | Kind | Signature |
|---|---|---|
Icon | 6 documented props | ({ className, icon, name, size, tone, label, spin, ...props }: IconProps) => import("@types/react").JSX.Element |
iconFor | export | (name: string) => IconGlyph | undefined |
iconNames | export | readonly string[] |
iconSet | export | readonly IconEntry[] |
searchIcons | export | (query: string) => readonly string[] |
Icon props
Type: IconProps
Values the compiler reads from the declaration.
| Prop | Type | Default | Notes |
|---|---|---|---|
icon? | RemixiconComponentType | undefined | — | The glyph: pass the imported component, `icon={RiPlayLine}`. Or address it by name from the curated set, `name="play"`. One of the two is required. |
label? | string | undefined | — | The icon's own name, for a glyph that carries meaning by itself. |
name? | string | undefined | — | A name from `iconSet`, for callers that cannot import a component. |
size? | IconSize | undefined | — | |
spin? | boolean | undefined | — | Rotate continuously — a refresh in flight, a job still running. |
tone? | IconTone | undefined | — | Defaults to `inherit`, so an icon inside a Button takes the button's tone. |
Guidelines
Do
- Address a glyph by name (`name="play"`) where a component cannot be imported — a stored value, a config field, a search box — and pass `icon={RiPlayLine}` where it can.
- Size and tone the wrapper rather than the glyph: `size` is the library's scale and `tone` resolves to a `--fg-*` token.
- Give an icon a `label` only where it carries the meaning by itself, and leave it unlabelled beside a word.
Don't
- Render a bare `@remixicon/react` component next to a LUC icon: the raw glyph knows nothing about the size scale or the tone tokens.
- Label a decorative glyph: it would be announced twice, once for the icon and once for the word beside it.
- Expect `name` to resolve a glyph outside the set — it throws at render rather than drawing nothing.
Accessibility
The wrapper owns the accessibility decision: with a `label` it is an image with that name, and without one it is `aria-hidden`, so a glyph beside a word is never announced twice. `spin` animates under the reduced-motion rule.
Family
Actions
Things a person presses, and the chrome that gathers them.
8 documented entries in this family. Open the family index
Related