Icon Button
FreeA compact button displaying only an icon, with no visible text label. Comes in 4 types (Primary, Secondary, Tertiary, Danger), 3 sizes (SM, MD, LG), and 6 states (Default, Hover, Pressed, Focus, Disabled, Loading). Used for actions like close, menu toggle, settings, or copy — where the icon is universally understood. Always requires an accessible label via aria-label.
72 variants
Variants
| Variant | Description | When to use |
|---|---|---|
| Primary | Solid brand-colour fill icon button for high-emphasis actions. | Use for key actions in toolbars or headers where space is limited. |
| Secondary | Subtle background icon button for medium-emphasis actions. | Use for secondary toolbar actions or inline controls. |
| Tertiary | Ghost icon button with no background at rest — appears on hover. | Use for low-emphasis inline actions like edit or delete in lists. |
| Danger | Red-toned icon button for destructive actions. | Use for delete or remove actions in compact contexts. |
Usage Guidelines
Always provide aria-label describing the action — e.g., aria-label="Close dialog".
Use an Icon Button when a text label would be clearer for the action.
Use universally recognised icons (✕ for close, ☰ for menu, ⚙ for settings).
Omit the aria-label — screen readers will announce nothing useful.
Maintain 44×44px minimum touch target even if the visible icon is smaller.
Use decorative-only icons for interactive buttons.
Code
<button class="lex-icon-button lex-icon-button--secondary" aria-label="Close dialog">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</button>.lex-icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: var(--lex-icon-btn-size, 40px);
height: var(--lex-icon-btn-size, 40px);
border-radius: var(--lex-icon-btn-radius, var(--lex-radius-md));
border: none;
cursor: pointer;
transition: background 150ms ease;
color: var(--lex-icon-btn-color);
}
.lex-icon-button--secondary {
background: var(--lex-icon-btn-bg);
}
.lex-icon-button--secondary:hover {
background: var(--lex-icon-btn-bg-hover);
}// Using Lexicon CSS classes with React
export function CloseButton({ onClose }: { onClose: () => void }) {
return (
<button
className="lex-icon-button lex-icon-button--secondary"
aria-label="Close dialog"
onClick={onClose}
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none"
stroke="currentColor" strokeWidth="2" strokeLinecap="round">
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</button>
);
}Design Tokens
| Token | Value (dark) | Value (light) | CSS property |
|---|---|---|---|
| --lex-icon-btn-size | — | — | size |
| --lex-icon-btn-radius | — | — | radius |
| --lex-icon-btn-bg | — | — | bg |
| --lex-icon-btn-icon-size | — | — | size |
Accessibility
- aria-label is required since there is no visible text content.
- Ensure 44×44px minimum touch target on mobile, even when icon is smaller.
- Use role="button" if not using a native <button> element.
- Focus ring must be visible — use the same focus/ring token as Button.