Skip to content

Icon

P-03 · Primitives · Primitives

All elements · Icon on the Primitives page

Last checked 2026-10-22 · Awaiting approval · Accessibility tests

Copies the bun run a11y:approve command for Icon.

Icon

P-03WCAG 2.2 AA · Passed #430

One SVG glyph from the sprite. Strictly non-interactive (pointer-events: none): wrap it in a Pressable or Button to make it clickable. Default 20px, 24px on mobile. Never size the inner glyph; size the wrapper.

Glyph families. Tabler (sprites/icons.svg) everywhere. Editor exception: the QEditor editors use Fluent UI System Icons, Regular style only (sprites/office-icons.svg), inside .qf-office and qf-office__* elements and in the office catalog sections. The two families never mix, and office symbols carry stroke="none" so this primitive's stroke never outlines them. Both rules are gated; see the README's "Icons" section.

Axis Values
data-size inherit · xs (14) · sm (16) · md (20) · lg (24) · xl (32)
data-color inherit · primary · info · muted · success · warning · error · purple · electric-blue · pink · yellow · brown · inverse
data-spin · data-pulse loading animations
Sizes
inherit →
Colors and motion

Guidance

When to use

  • Add a glyph beside a label in a button, menu item, list row or nav item.
  • Mark status next to text, such as a check for done or a triangle for a warning.
  • Show a loading glyph with data-spin inside a button or row while work runs.
  • Use Fluent Regular glyphs from sprites/office-icons.svg inside .qf-office editors, and Tabler everywhere else.

When to consider something else

  • When the glyph must be clicked, wrap it in a Pressable or Button; Icon itself has pointer-events: none. See Pressable.
  • When the glyph stands for a person, use Avatar. See Avatar.
  • When the user waits for a longer task with measurable progress, use Progress instead of a spinning icon. See Progress.
  • When content is loading in place, use Skeleton rather than a spinner over the region. See Skeleton.

Usability

Do
  • Pair icons with visible text wherever space allows; an icon-only control needs a Tooltip with its name.
  • Size the wrapper or use data-size; never size the inner glyph.
  • Use data-size="inherit" and data-color="inherit" to match the surrounding text.
  • Keep one glyph per meaning across the app.
Don’t
  • Don't mix Tabler and Fluent glyphs; Fluent stays inside the editor scope, Tabler stays outside it.
  • Don't rely on icon color alone to show status.
  • Don't leave data-pulse or data-spin running after the work is done.

Accessibility

Keyboard

No keyboard interaction of its own.

Roles and names

  • A decorative icon, or one next to text that says the same thing, carries aria-hidden="true", as every specimen does.
  • An icon that is the only content of a control is hidden, and the control carries the name with aria-label.
  • A meaningful standalone icon (a status glyph with no text) needs role="img" and an aria-label, or adjacent qf-sr-only text.

Focus

  • Icon is never focusable. Focus belongs to the Pressable or Button that wraps it.

Other requirements

  • Icon is non-interactive and has no keyboard behavior of its own.
  • Glyphs that convey information need 3:1 contrast against their background (1.4.11); check muted, yellow and accent colors in both themes.
  • Status must not depend on color alone (1.4.1).
  • data-spin and data-pulse are reduced to a single near-instant run under prefers-reduced-motion (2.3.3); a loading state still needs a text or live-region announcement (4.1.3).

Test your implementation too. This guidance covers the element as specified here. How a screen composes it (labels, order, announcements) still needs its own keyboard and screen reader check.

Accessibility tests

WCAG 2.2 AA · Passed

Passed the gate (run 358b316 on 2026-10-22): no finding in any theme. Awaiting a person’s approval of the checklist below.

Icon test checklist
Area Automated A person checks
General Passed Color is never the only cue, text alternatives say the same thing as the graphic, and the element reads the same in the light and the dark theme.
Zoom Passed At 200% zoom, at 320 CSS pixels wide and with the WCAG text-spacing overrides, nothing is lost, clipped or overlapping.
Keyboard Passed Every row of the Keyboard table works, focus is always visible and never trapped, and the tab order follows the reading order.
Screen reader Passed With NVDA or JAWS on Windows and VoiceOver on macOS, names, roles and states are announced as Roles and names says, and changes are announced once. (3 items)

Approving. When the checklist passes on the checked run, record it with bun run a11y:approve -- icon --by "Your name" and commit a11y/approvals.json with the rebuilt pages. All test status

Package

Consumers link one stylesheet, css/classic/index.css, which includes every element. The files below are where this element is defined.

Icon package
Source css/classic/primitives/layout.css
Specimens also use Box · Card · Chip · Table · Text · Toolbar
Sprites sprites/icons.svg · sprites/office-icons.svg
React Not yet available: the React binding has not started.

Latest updates

Icon latest updates
Date Version Breaking Description
2026-10-02 0.1 No Editor icon exception — Fluent Regular only, scoped to the editor
2026-10-02 0.1 No Office symbols reset stroke so .qf-icon no longer outlines them
2026-10-02 0.1 No Inline every icon sprite, not only icons.svg
2026-10-02 0.1 No Office icon list and a --check that fails on missing glyphs
2026-09-30 0.1 No Nav (both skins): D-9's icon is drawn without .qf-icon's stroke, so circle-plus-filled keeps its plus; the sprite stays as provided (QF-10570)
2026-09-30 0.1 No Revert "sprites: a -filled glyph sets stroke="none", so .qf-icon's inherited stroke no longer closes its cut-outs (QF-10570)"
2026-09-30 0.1 No A -filled glyph sets stroke="none", so .qf-icon's inherited stroke no longer closes its cut-outs (QF-10570)
2026-09-26 0.1 No Classic dark: surfaces, ink and borders from the info scale; nav icons at full strength (QF-10566)
2026-09-15 0.1 No Utility links: icons with tooltips when labels overflow, one-row masthead, ellipsis menu at 30rem
2026-09-15 0.1 No Skin toggle icons

All release notes