Skip to content
ArcadiaDesign

Registry

Every glyph is one outline.

Click an icon to copy its name. Names describe the job (new-chat, compact, plan), not the drawing, and the search knows the usual words for each: try delete, gear or undo.

TSX

Icons are always decorative (aria-hidden): the label belongs on the control. Colour is currentColor, set by the parent from the --icon-* ladder. A component that holds a label draws its icon beside it on its own (Button, MenuItem, ListRow, Chip, Badge, Tab, PickerTrigger, Input and the rest), so size="text" is for an icon you place in a line of text yourself. One exception: a glyph made only of dots (more) in an IconButton. Three 1.5px dots at a rank peak far under the label beside them (122 of 235 at the muted rank in light, under a row's secondary line), so the button draws them at --icon-1 whatever its tone. A solid ink already stands at full strength and keeps its colour (the inverse disc, plan on ghost).

Stroke and size

Standalone, an icon is an outline at a fixed 1.5px stroke, whatever its size. Beside text it takes the text's measure: as tall as its capitals, at the font's stem.

14px16px20px24px32pxpxpxpxpxpx
Standalone, 14 to 32px: the stroke under each column is read from the page. The scale is 14 to 24.

Beside text

The drawing and its stroke stand --icon-text-ink, 1.09 cap heights, stroked at --icon-stem, the stem of the label's weight, in --icon-text, a frame of whole pixels.

TextSampleFrameStroke
Label, 12 / 418Open folderpxpx
UI, 13 / 418Open folderpxpx
UI strong, 13 / 500Open folderpxpx
Prose, 15 / 418Open folderpxpx
Title, 15 / 500Open folderpxpx
XL, 17 / 418Open folderpxpx
Heading, 20 / 500Open folderpxpx
3XL, 24 / 500Open folderpxpx
Display, 30 / 460Open folderpxpx

A glyph beside text is as tall as the letters: its live area and its stroke stand 1.09 cap heights, the median of SF Symbols' small scale beside SF Pro, and the stroke is the font's stem. Icon sizes the 24 grid to that, 10.6px beside 13px regular text and 10.36 beside medium, and centres it in the frame: whole pixels, 11 beside 13px, its size taking the parity of the cap height's, so the drawing's middle sits within a quarter pixel of the cap middle. Frame and stroke above are read from the page, at each text role's size and weight. In a row the icon centres on the capitals rather than the line box (--icon-text-nudge: Chrome puts the baseline on a whole pixel, so the cap middle sits up to 0.7px off the line's middle, by an amount the token works out from the size and line height). The nudge is a layout offset that keeps the frame a whole number of pixels from the baseline, so icon and text snap to the pixel grid together. In running text the drawing sits on the baseline. A host keeps its slot's width (a menu's 16px icon column, a row's 20px leading slot) and centres the icon in it, so labels still line up.

Standalone, at 1.5px: icon buttons, icon-only segments, tiles and empty states, a sign-in screen's glyph, a heading's link anchor, a checkbox's check.

Beside text, at the stem: a button's icon, menu and row icons, chips, badges, tabs, pickers, an input's glyph, a toast's tone, a notice's caution, and a glyph inside a sentence. A medium label sets --icon-stem to --stem-medium.

All follow the font the icon sits in.

In a label's run

IconLabel holds a glyph and its one-line label in one font run, so the glyph sizes from that label's letters and stays on its capitals wherever the pair sits.

#300 Checking

A glyph in a wrapper of another font sizes to that font, and a flex or grid box centres it on the line box, which sits off the capitals. Style the IconLabel itself (its font, its chip), never a span inside it.

Stems

A font's vertical stroke as a share of its size, measured on the SF Pro outlines and linear in the weight; Geist Mono is within 2%.

TokenWeightAt 13pxStroke
418, regular textFolderpx
460, display and heroFolderpx
500, labels, buttons, titlesFolderpx
600, strong proseFolderpx

Each stem is written against its weight token, so a change of weight moves its stem.

Sizes

Four standalone sizes on the icon scale, and the text frame. An icon takes --icon-size from its parent unless it states a size.

SizeSampleTokenValue
Folderpx
--icon-size
Ref<"--icon-sm" | "--icon-md" | "--icon-lg" | "--icon-xl">
Width and height of a standalone icon whose size prop doesn't fix them. Inherited: a parent sets it for the icons it holds.
--icon-stem
Ref<"--stem-regular" | "--stem-display" | "--stem-medium" | "--stem-semibold">
The stroke of an icon beside text: the stem of its label's weight. Inherited; default the regular stem.
--icon-turn
"90deg" | "180deg" | "-90deg"
A turn of the drawing about its centre, on the fold's time (an open chevron-right: 90deg); inherited. A turned box around a text icon would swing its offset onto the capitals sideways. Default no turn.

Brand mark

ArcadiaMark is the Arcadia pine, two arms and a pine: a mark, not an icon, so it keeps its fill, as provider marks and agent avatars do.

The running indicator is the same three strokes, lit one at a time: see Pine sweep.
Keep half the mark's height clear on every side; beside a wordmark, that is the gap.
The smallest size is 12px wide, the pine sweep in a chat row. Below that the arms close up.
Night and day: the mark takes --brand-mark, an icon rank, so it sits back in the chrome.
--brand-size
Ref<IconSize>Default var(--icon-md)
Height; the width follows the mark.

Adding an icon

Every glyph is Arcadia's, drawn into the kit as data. The kit owns the names, so adding one is a kit change, never a product one.

TSX

Draw it on the 24 grid: live area 2 to 22, a 1.5 design stroke, round caps and joins, squircle corners on frames, and the off-slash rule (a full corner-to-corner slash the drawing meets on one side). Keep separate strokes, and the two sides of every counter, 5 units apart, centre to centre: the heaviest stroke an icon draws is a medium label's stem, 3.14 units, and 5 units leave 0.8px of paper there, so the glyph never reads as a blob. A mark read by its dots keeps them (a question mark, an exclamation, an ellipsis): each dot is a zero-length stroke, so its round cap draws it at the stroke's weight, and it stands 5 units clear of the rest (glyph-form). Paste the drawing as paths, circles and rounded rects with every paint attribute stripped: there is no filled or solid form, and Icon joins the elements into one path. It is hand-edited, with no generator or dependency; the kit's lint rasters every glyph and fails one whose parts merge or counters shut at that stroke and 0.75px more (glyph-clog). isIconName(value) narrows a string to IconName at runtime, for names that arrive as data. Add the new name's search words to the site's icon aliases so people can find it.

Provider marks

Model providers' marks are one filled path each in src/icons/provider-paths.ts, drawn inside the icon live area and shown in the icon ranks.

Use them through ProviderMark; beside text (its default text size) the mark's own drawing stands as tall as the letters, 1.09 cap heights as a line icon does (1.00 for a flat mark), at most 1.3 times 1.09 cap heights wide.

Icon

namerequired
IconName
size
"sm" | "md" | "lg" | "xl" | "text"Default "md"
sm 14, md 16, lg 20 or xl 24 at the 1.5px stroke. text: beside text, its drawing 1.09 cap heights at the font's stem (--icon-stem), on the capitals. Omit to take the parent's --icon-size.
rootStyle
RootStyle<IconKnobs>
Typed StyleX override: layout, --icon-size and --icon-stem.
className
string
The part name a parent gives the icon it renders (ui-menu-item-chevron), for its own rules.

Rest props go to SVG element props.

iconrequired
IconName | ReactNode
An icon name, an Icon, or a loader at size="text".
end
booleanDefault false
The glyph after the label.
rootStyle
RootStyle<IconLabelKnobs>
Typed StyleX override.
childrenrequired
ReactNode
The label; style the IconLabel, not a span inside it.

Rest props go to <span> props and render.

title
string
Accessible name. Without it the mark is decorative (aria-hidden).
size
"sm" | "md" | "lg"Default "md"
The mark's height on the icon scale: sm 12px, md 16px, lg 20px.
rootStyle
RootStyle<BrandMarkKnobs>
Typed StyleX override: layout and --brand-size.
className
string
The part name a parent gives the mark it renders, for its own rules.

Rest props go to SVG element props.