Icon

A Phosphor icon looked up by its export name.

<Icon name="HeartbeatIcon" className="size-6" />

Everything else goes to the underlying Phosphor component, so weight, size and color work as they do there.

Names from data

Design
Development
Overdue
Unknown
<Icon name={category.icon} className="size-5" />

An unknown name falls back to TagIcon rather than throwing, so a renamed or mistyped icon in the database never takes the page down. In development it also logs a warning naming the missing icon.

Icons are aria-hidden unless you pass an alt or an aria-label.

The full list of valid names is exported for building a picker or validating input, along with the union type behind it:

import { type PhosphorIconName, phosphorIconNames } from "@voila.dev/ui/icon";

For letting a user choose one, @voila.dev/ui has an IconPicker built on top of this.

API

PropTypeDefault
namePhosphorIconName | (string & {})requiredThe Phosphor export name, e.g. "HeartIcon". Typed as the union of valid names but accepts any string, so a name read out of a database still compiles; an unknown one renders TagIcon instead of crashing.
altstring
colorstring
mirroredboolean
sizestring | number
weightIconWeight

Plus the DOM props of the element it renders. Source: icon/components/icon.tsx.

name is the only prop this component adds. The rest are Phosphor's own, which is why they carry no description here: size and color accept any CSS length and colour but are better left to className so a rebrand reaches them, weight picks the stroke style (thin through fill, regular by default), mirrored flips the glyph for right-to-left layouts, and alt is what turns a decorative icon into a labelled one.