Icon button
The icon-only control. React <IconButton> (packages/ui/src/components/IconButton.tsx) emits .acrm-icobtn (apps/web/src/ds.css): transparent at rest, --hover-surface on hover, square at --control-h.
variant="framed" (.acrm-icobtn.framed) is the bordered one: 32px wide on the same height, 1px var(--border-strong), --surface-100, --shadow-xs, an --ico-sm glyph in --ink-700, hover --surface-75. It replaced the hand-drawn .pr-iconbtn / .rr-iconbtn on 11 September 2026 (BTN-A3), which were deleted in the same change.
variant="secondary" (.acrm-icobtn.secondary, beta — candidate approved by the AD on 18 October 2026, ACRM-542) is for rows of tools that need structure without the weight of framed: a 1px var(--line-200) hairline, no shadow, transparent at rest, --line-100 on hover, --selected + --accent-ink when pressed or open. It has ONE universal size (owner 19 October 2026, "everything should be one size"): --control-h square (30×30) with an --ico-sm glyph; size and iconSize do not apply to it. Used in the compose footer (attach, template, signature, AI, reminder), the rich-text format toolbar, and the message tool rows (message page tools, message card actions, message dock footer, draft panel header). Window headers (assistant panel, assistant surface, record drawer) stay quiet (AD 27 September 2026). Text next to a secondary row (e.g. the "2/14" counter) takes .acrm-icobtn-text (padding-inline: var(--sp-4)), always wider than the gap between buttons; each carries an application Tooltip with the shortcut instead of a native title.
href (AD 27 Sep 2026, acrm !3997) renders the same look as an <a> instead of a <button> — real link semantics for a download or an external address, same pattern as <Button href>.
When to use
- Actions in a Section top bar, record header or drawer chrome: close, back, previous/next record, more.
- Framed: the action row of a record rail (person, company, deal), row kebabs on cards, actions in a section block header.
- Row-level actions where a text label would add noise: edit, remove, open.
- Any place the icon alone is unambiguous and the action is secondary.
href: a download or an external/file address (e.g. an attachment) that should behave like a real link — middle-click, "save link as", a screen reader announcing a link.
When not to use
- The main action of a screen — use Button
primarywith a label. - An action whose icon is not self-explanatory — use Button with a label and an icon.
- Hand-drawn framed buttons (
.pr-iconbtn,.rr-iconbtn) — removed 11 September 2026; usevariant="framed", which the validator ruleiconbtn-framed-rawnow enforces. - In-app navigation —
hrefis for external URLs, downloads and deep links only; the router owns navigation inside the app. - A kebab (
dots-vertical) that opens a menu with a single item — replace it with the direct action instead (AD 26 Sep 2026, "kebab with one action", acrm !3997).
Anatomy
- Square container
--control-h×--control-h(30px),size="sm"= 24px × 24px. Framed is 32 × 30 and has one size only —sizedoes not apply to it. - Framed keeps its rest look when pressed, when its menu is open and when disabled: the hand-drawn rules it ports had no such states, and inventing them would have changed 31 places. Focus comes from the foundation ring.
- No border, no background at rest, radius
--radius-sm. - Icon
<Icon name>from the Tabler set,1emby default,iconSizeoverrides in px. - Colour
--fg-secondaryat rest,--fgon hover; hover background--hover-surface. type="button"by default so it never submits a surrounding form.- Required accessible name via
aria-label(andtitlefor the tooltip). pressed?: boolean(acrm !3936) drawsaria-pressedand the--active-surfacelook, kept on hover — for toggles (format, panel, template/AI in mail compose), not for a menu trigger's open state.href(with optionaltarget,rel,download) swaps the<button>for an<a class="acrm-icobtn …">with the identical look;target="_blank"merges inrel="noopener noreferrer";disabledrenders<a aria-disabled="true">withouthref, since a link cannot be disabled by attribute;refforwards onto the<a>too, so it can still anchor a Popover.
Best practices
Do
- Give every icon button an
aria-labelthat names the action: "Close", "Next record". - Group related icon buttons with a
SectionTopBarDividerbetween groups (navigation | more). - Use
size="sm"inside dense rows and chips where 30px would break the row height. - Keep the same icon for the same action across screens (pencil = edit, x = close, dots-vertical = more).
Don't
- Icon button without
aria-labelortitle— the button has no text, so it has no name. - More than 3–4 icon buttons in a row without grouping — the bar becomes a strip of glyphs.
- Icon button for a destructive action without confirmation — a trash icon deletes on one click.
- Custom size or colour via inline style — use
sizeandiconSizeonly.
Content
aria-labelandtitle: sentence case, verb phrase, no period ("Previous record").- The tooltip (
title) andaria-labelshould carry the same wording.
Related
- Button — labelled actions; the primary action of a section;
hreffollows the same pattern. - Section top bar — the row that hosts icon buttons for navigation and more.
- Kbd hint — not rendered inside Icon button; document shortcuts in the tooltip text instead.
- Attachment — uses
IconButton size="sm" hreffor its download action.
Source: docs/button/icon-button.usage.md · GitLab