Brand

Iconography

One vocabulary: Lucide, stroke only, never filled. An icon here is friendly line work — light, open, and quick to read. Stroke 1.75px, inheriting currentColor, so every glyph picks up the color of its context without per-icon color work (ADR-0010). The set is shared with the proposed system; only the paint around it changes.

The vocabulary

Five constraints define the whole system. They are deliberately few — the discipline is what keeps a thousand-glyph library feeling like one friendly set.

library
Lucide — broad coverage, well-maintained, open-source. When Lucide lacks a glyph, a custom one is authored in the same style via the ADR-0010 RFC path, never redrawn ad hoc.
style
Stroke only — never filled. The open line work stays light and approachable; filled icons would weigh the surface down.
stroke width
Default 1.75px. The one exception: 12px icons inside badges bump to 1.85 for crispness at that size.
color
Icons inherit currentColor — the context cascades its color through (gold for primary and active, plain ink elsewhere). No per-icon color overrides.
grid
A 24×24 viewBox, square endcaps unless rounded fits the glyph better. Custom additions keep the same geometry.

Specimens

A working sample of the glyphs the product reaches for most — navigation, record actions, people, time. Each renders exactly as the system ships it: stroke 1.75, currentColor, on the native 24px grid. Hover one — the official brand says hello with a little lift.

search
funnel
plus
x
check
chevron-down
chevron-right
arrow-left
external-link
copy
download
upload
trash-2
pencil
eye
file-text
calendar
clock
user
users
bell
shield-check

Inlined as JSX with stroke=currentColor — toggle the appearance and the brand; the set re-inks itself with zero per-icon work.

Severity glyphs

Severity is never color alone (ADR-0017). Under red-green color-blindness, the caution and critical hues collapse into similar olives — so every severity carries a disambiguating glyph and names itself in text. These are the shipped defaults, rendered by the same severity-icon module Toast, Banner and Badge consume.

NeutralA plain note — no judgment attached.
InfoSomething worth knowing; nothing required.
AffirmDone, passed, confirmed.
CautionNeeds attention; recoverable.
CriticalFailed, blocked, or irreversible.
ADR-0017 specoctagon-alert — the specified critical glyph.

A named gap: ADR-0017 specifies octagon-alert — the universal stop-sign silhouette — for critical, but the shipped Beta messengers currently render circle-x. The divergence is shown here, not hidden; reconciliation is pending.

The brand mark

The engraved dial glyph belongs to the proposed system — under the official brand it does not exist. The face of this brand is the gold ring mark: a solid fill, not a stroke, and it stays brand artwork. It lives in brand slots and lockups, never in the icon set, and it is never stroke-converted or recolored.

halo ring
The official mark — solid gold, brand artwork, not a UI icon.

Vendor marks

The second ADR-0010 exception, amended in: where a vendor requires its own mark — the Google "G" on a sign-in button is the live case — it renders per that vendor's guidelines. Full color, correct geometry, never recolored, never reduced to a stroke glyph. This applies only where the vendor mandates the mark (chiefly SSO buttons); it is not a license for multicolor icons.

Google "G"
A vendor asset in its required four colors — the one place currentColor does not apply.

Sizing

There is no dedicated icon-size token ramp yet — a named gap, shared with the proposed system. Icons size from their context: the native grid, the chrome that holds them, or the badge they sit in. The working sizes are these.

24px — native grid
The authored size. Doc specimens and standalone glyphs render here.
18px — chrome
Ambient buttons and app-bar affordances; the icon shrinks, the stroke holds at 1.75.
12px — badge
The smallest legal size, and the one stroke exception: stroke 1.85 for crispness (ADR-0010).

Don't

  • No emoji, ever. Emoji break the voice register, render differently per platform, and have no accessibility contract (ADR-0009). Lucide fills the role emoji might otherwise take.
  • No filled icons. The open line work is the shared vocabulary across both brands; mixing in filled glyphs fractures it.
  • Never recolor a vendor mark. The Google "G" keeps its four colors; a monochrome or gold "G" violates the vendor's guidelines and ADR-0010 both.
  • Never carry severity by color alone. Pair the tone with its glyph and name it in text (ADR-0017) — the glyph survives greyscale; the hue does not.
  • Brand artwork is not an icon. The ring mark, lockups and patterns stay in brand slots — under this brand no mark crosses into the icon set at all.

Accessibility

  • Decorative icons disappear. An icon next to its label is decoration — aria-hidden="true" so screen readers hear the words once.
  • Icon-only controls carry a name. A glyph with no visible text needs aria-label; the icon itself announces nothing.
  • Meaning gets words. If a glyph carries information (a severity, a state), the information also appears as text — the icon is the fast cue, the text confirms.
  • Contrast rides currentColor. Because icons inherit the text color of their context, an icon passes contrast wherever its text does — one check, not two.

Usage

A glyph beside its labeltsx
import { Download, FileText } from 'lucide-react'

// Decorative beside its label — hidden from the accessibility tree:
<Button variant="ghost" tone="secondary">
  <FileText strokeWidth={1.75} aria-hidden="true" />
  Risk report
</Button>

// Icon-only — the control carries the name instead:
<Button variant="ghost" tone="secondary" aria-label="Download report">
  <Download strokeWidth={1.75} aria-hidden="true" />
</Button>
A severity, paired per ADR-0017tsx
import { defaultSeverityIcon, type SeverityTone } from '@halo-compliance/ui'

// The shared severity register — glyph + tone + the word, never color alone:
const tone: SeverityTone = 'caution'

<span className="finding-status">
  {defaultSeverityIcon(tone)}
  Caution: this control needs attention
</span>
  • /badge — the 12px icon context, and the stroke-1.85 exception.
  • /button — icon-only buttons and the accessible-name requirement.
  • /toast — the severity messengers consuming these glyphs.
  • /colors — the solid, friendly colors the icons inherit through currentColor.