Icon box

A small box that contains an icon, svg, or image. Used for small tokens, media, etc.

Examples

Basic usage

<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 d="M10.3 21a1.94 1.94 0 0 0 3.4 0" />
            </svg>
        </div>

Size

<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" />
                </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" />
                </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" />
                </svg>
            </div>
        </div>

Color

<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 d="M10.3 21a1.94 1.94 0 0 0 3.4 0" />
                </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" />
                    <path d="M12 16v-4" />
                    <path d="M12 8h.01" />
                </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" />
                    <polyline points="22 4 12 14.01 9 11.01" />
                </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 d="M12 9v4" />
                    <path d="M12 17h.01" />
                </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" />
                    <path d="m15 9-6 6" />
                    <path d="m9 9 6 6" />
                </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"
                    />
                </svg>
            </div>
        </div>

Feature row with .media

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" />
                    </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" />
                        <polyline points="22 4 12 14.01 9 11.01" />
                    </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"
                        />
                    </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>

Source comments

Icons -- the bare glyph atom and the colored container

.icon (P3 atom) styles the consumer's own svg geometry and nothing
else: token sizing and flex-shrink: 0. It never touches fill,
stroke, or stroke-width, which is what makes it work with icons
from any source -- Lucide, Heroicons, tabler, a sprite, a
hand-drawn svg all keep their own paint (P8: content glyphs live
in consumer markup). The default size consumes the root
--default-icon-size token, so inline icons scale with surrounding text;
the is-* variants shadow the token locally with fixed sizes for
standalone glyphs. Inline alignment is part of the component: the
glyph sinks slightly below the text baseline (-0.125em) so it
reads as part of the line, the way an icon font would.

.icon-box is the container, not the glyph: a fixed-size square
for feature grids, media objects, and notification feeds. Pair
them when you want a tinted square -- .icon sizes the glyph,
.icon-box the box.

Markup:
  <svg class="icon is-sm" aria-hidden="true">...</svg>
  <div class="icon-box is-primary">
      <svg class="icon" aria-hidden="true">...</svg>
  </div>

Reference

Source: src/css/icon.css

Applies to

.icon-box

Classes

ClassKindDescription
.is-smvariantSmaller box at 2rem
.is-lgvariantLarger box at 3rem
.is-primaryvariantPrimary color variant
.is-successvariantSuccess color variant
.is-warningvariantWarning color variant
.is-dangervariantDanger color variant
.is-accentvariantAccent color variant

Tokens

TokenDefaultDescription
--icon-box-size2.5remWidth and height of the box
--icon-box-bgvar(--color-surface-raised)Background color of the box
--icon-box-colorvar(--color-text)Icon color inside the box
--icon-box-radiusvar(--radius-md)Border radius of the box