Icon box
Icon container
Intent
Icon-box is a fixed-size colored square that centers an SVG
or glyph. Use it where you want an icon to read as a chip
rather than an inline mark -- feature grids, media rows with a
heading and blurb, notification feed glyphs, stat-tile heads.
For plain inline icons inside a button or navigation link, you
don't need this component; the root
--icon-size token already sizes SVGs inside
button and
sidebar-nav via their own
rules.
The glyph inside an icon-box inherits
currentColor, which tracks the component's
--icon-box-color token. Monochrome SVGs with
stroke="currentColor" or
fill="currentColor" automatically pick up the
variant color; SVGs with hard-coded colors ignore it.
Basic usage
A <div class="icon-box"> wrapping an SVG.
The default tone uses the neutral surface and text tokens --
reach for a color variant when the icon itself should carry
meaning.
<div class="icon-box">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"></path>
<path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"></path>
</svg>
</div>Variants
Size
Sizes step through the density grammar: .is-sm
for dense rows and compact feature lists; the default for
typical feature grids; .is-lg for hero marks or
standalone callouts. The SVG inside doesn't auto-scale --
match the glyph's explicit width and height to the variant,
or size it in relative units (em, %)
if you want one markup shape to work across sizes.
<div class="cluster">
<div class="icon-box is-sm">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
</svg>
</div>
<div class="icon-box">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
</svg>
</div>
<div class="icon-box is-lg">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
</svg>
</div>
</div>Color
Status tones remap the scoped tokens to the matching semantic color family -- a subtle tinted background paired with the darker primary/success/warning/danger/accent color for the glyph. The default (no modifier) uses neutral surface tokens and reads as chrome rather than status.
<div class="cluster">
<div class="icon-box">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"></path>
<path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"></path>
</svg>
</div>
<div class="icon-box is-primary">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4"></path>
<path d="M12 8h.01"></path>
</svg>
</div>
<div class="icon-box is-success">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
</div>
<div class="icon-box is-warning">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3z"></path>
<path d="M12 9v4"></path>
<path d="M12 17h.01"></path>
</svg>
</div>
<div class="icon-box is-danger">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="10"></circle>
<path d="m15 9-6 6"></path>
<path d="m9 9 6 6"></path>
</svg>
</div>
<div class="icon-box is-accent">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
</svg>
</div>
</div>Composed patterns
Feature row with .media
The canonical use. Pair .icon-box with the
.media
composition primitive: put .media-figure on the
icon-box so the row layout treats it as the figure slot, and
drop heading + body in .media-body. Each class
does one job -- icon-box themes the chip,
.media handles the figure-plus-body row.
Fast builds
esbuild-based pipeline produces the full CSS and docs site in under a second on typical hardware.
Semantic HTML first
Components style real elements -- no div-tag soup, no wrapper fences around native widgets.
Tokens all the way down
Every scoped component token resolves through the semantic layer, so a palette change flows through the entire library.
<div class="stack">
<div class="media">
<div class="icon-box is-primary media-figure">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
</svg>
</div>
<div class="media-body">
<h4>Fast builds</h4>
<p>esbuild-based pipeline produces the full CSS and docs site in under a second on typical hardware.</p>
</div>
</div>
<div class="media">
<div class="icon-box is-success media-figure">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
</div>
<div class="media-body">
<h4>Semantic HTML first</h4>
<p>Components style real elements -- no div-tag soup, no wrapper fences around native widgets.</p>
</div>
</div>
<div class="media">
<div class="icon-box is-accent media-figure">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
</svg>
</div>
<div class="media-body">
<h4>Tokens all the way down</h4>
<p>Every scoped component token resolves through the semantic layer, so a palette change flows through the entire library.</p>
</div>
</div>
</div>Class reference
.icon-box-- the atom. Typically applied to a<div>wrapping an SVG..is-sm,.is-lg-- size variants..is-primary,.is-success,.is-warning,.is-danger,.is-accent-- color variants. Default (no modifier) uses neutral surface tokens.
Customization
--icon-box-radius defaults to
--radius-md; override with
--radius-pill for a circular chip.
Full token list and defaults:
src/css/icon.css.
Accessibility
-
Decorative glyph, hide it. When an
icon-box sits next to text that already conveys the
meaning (the feature-row pattern above: the heading and
blurb say everything), mark the SVG
aria-hidden="true"so screen readers don't announce a redundant "image". -
Meaningful glyph, name it. When the
icon-box stands alone or carries information not present
in adjacent text, give the SVG
role="img"and an inner<title>element, or put anaria-labelon the<svg>. The title / label is what assistive tech announces. -
Icon-box isn't focusable. It's a
<div>-- not a button, not a link. If you want a whole-row or whole-tile click target, wrap the row in an<a>or put an<a>on the heading (as card's.is-interactivepattern does). Don't addtabindex,role="button", or a click handler to the icon-box itself.
CSS Reference: Icon Box
Colored box that centers an SVG or glyph
Source: src/css/icon.css
Tokens
| Token | Default | Description |
|---|---|---|
--icon-box-size | 2.5rem | Width and height of the box |
--icon-box-bg | var(--color-surface-raised) | Background color of the box |
--icon-box-color | var(--color-text) | Icon color inside the box |
--icon-box-radius | var(--radius-md) | Border radius of the box |
Classes
| Class | Description |
|---|---|
.icon-box | component root |
.is-sm | Smaller box at 2rem |
.is-lg | Larger box at 3rem |
.is-primary | Primary color variant |
.is-success | Success color variant |
.is-warning | Warning color variant |
.is-danger | Danger color variant |
.is-accent | Accent color variant |