Icons
Lucide, and only Lucide. Every icon inherits currentColor — an icon is never given a colour of its own, it takes the colour of the text it sits with.
--icon-size-sm--icon-size-md--icon-size-lgStroke is --icon-stroke: 1.75, not Lucide's default 2 — it sits better against DM Sans at small sizes. Lucide writes width and height inline, so the icon-sm / icon-md / icon-lg utilities exist to override it at class level and keep size a token.
Browse Lucide
Every glyph in the pinned lucide package (same major as lucide-react in apps). Search by name, select a tile for import paths and copy-ready snippets. Stroke in the grid matches the system: 1.75 on a 24×24 viewBox.
Loading icon catalog…
import { Megaphone } from 'lucide-react';
// size and stroke come from the class, never from props
<Megaphone className="icon-md" aria-hidden="true" />
// an icon-only control needs its own name
<button aria-label="Delete review"><Trash2 className="icon-md" aria-hidden /></button>Event meta — date and place
The shipping event header draws a filled calendar and a coloured pin next to the date and the address. Replace both with Lucide. The glyphs take currentColor from the text they sit with — never a fill of their own, never a second family.
| In the product | Lucide | Not |
|---|---|---|
| Date of one edition | calendar | A filled calendar, an emoji, or calendar-days (that one is a list of events, used in side nav) |
| Place / address | map-pin | A filled or red pin. Colour is never the only signal, and an icon is never given a colour of its own |
Size is icon-sm (16px) — these sit in a meta row, inline with text-sm. Both are aria-hidden: the date and the address are the accessible names.
import { Calendar, MapPin } from 'lucide-react';
<div className="flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-secondary">
<span className="inline-flex items-center gap-2">
<Calendar className="icon-sm" aria-hidden="true" />
<time dateTime="2026-12-13">13/12/2026</time>
</span>
<span className="inline-flex items-center gap-2">
<MapPin className="icon-sm" aria-hidden="true" />
1600 Pacific Highway, San Diego, CA, US
</span>
</div>Category icons — the closed gap
Names and definitions are taken from the shipping product, not invented here. Category icons are drawn in --color-primary, never in the tier colour: the icon says what, the bar says how good.
ScoreBar reserves an icon slot and the design system deliberately ships no icon set — the app passes its own. That left seven categories with no named icon anywhere. This is the mapping. Category icons are drawn in --color-primary, never in the tier colour: the icon says what, the bar says how good.
Rules
- An icon beside a label is
aria-hidden. The label is the accessible name. - An icon-only control carries its own
aria-label, and still meets the 44px target. - No filled icons, no duotone, no second family. If Lucide has no glyph for it, use a word.
- Never a decorative icon. If removing it loses nothing, remove it.
theme.css.