IconButton
A square icon-only button. Always pass a label — it becomes the accessible name and the native tooltip, since there is no visible text to fall back on.
Variants
ghost is the default and transparent. outline is a raised fill (no
border — the name is kept for API compatibility, not for what it looks
like), for an icon button sitting alone rather than in a toolbar. accent
is a soft accent tint, for a toggled or active state — the segmented-tabs
pattern this system does not otherwise reach for.
A square icon-only button is still a <button>, but there is no attribute
that tells it apart from a plain Button
sitting alone — variant/size mean different things for each — so
.icon-button is the one class this component needs.
Markup
<button class="icon-button" aria-label="Delete">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13" /></svg>
</button>
<button class="icon-button" data-variant="outline" aria-label="Settings">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3" /><path d="M12 2.5v3M12 18.5v3M3.6 7.2l2.6 1.5M17.8 15.3l2.6 1.5M3.6 16.8l2.6-1.5M17.8 8.7l2.6-1.5" /></svg>
</button>
<button class="icon-button" data-variant="accent" aria-label="Filter (active)">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 5h16l-6 8v5l-4 2v-7z" /></svg>
</button>
Sizes
The box is square and fluid, and it is not a number of its own: it is two rungs of the space scale around one line of the type a Button of the same size would set. So the three sizes come out at 25px, 35–38px, and 39–43px — level with their Button counterparts at any window width, and still level if the scale is ever retuned.
Markup
<button class="icon-button" data-variant="outline" data-size="sm" aria-label="Back"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6" /></svg></button>
<button class="icon-button" data-variant="outline" aria-label="Back"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6" /></svg></button>
<button class="icon-button" data-variant="outline" data-size="lg" aria-label="Back"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6" /></svg></button>
Paired with Tooltip
An icon-only control almost always wants a Tooltip too — the aria-label covers accessibility, the tooltip covers a sighted mouse user glancing for a hint.
Markup
<span>
<button class="icon-button" aria-label="Delete" aria-describedby="icon-btn-tip">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13" /></svg>
</button>
<span role="tooltip" id="icon-btn-tip">Delete</span>
</span>
API
| Element / attribute | Values | Notes |
|---|---|---|
button.icon-button | Required base — the one class in this component, since nothing distinguishes it from Button structurally. | |
aria-label | string | Required — becomes the accessible name and the native tooltip. |
data-size | sm | lg | Square, matching the Button of the same size: 25px small, 39–43px large. Omit for the default, 35–38px. |
data-variant | outline | accent | Omit for the default, transparent ghost look. |