Default
Show the codeHide the code
Default, code
<IconButton icon={Settings} label="Settings" />An icon-only action with a required name, shown as a tooltip on hover and keyboard focus.
These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.
Default, code
<IconButton icon={Settings} label="Settings" />Variants, code
<div className="flex flex-wrap items-center gap-gap-md">
<IconButton icon={Search} label="Search" variant="default" />
<IconButton icon={Pencil} label="Edit" variant="secondary" />
<IconButton icon={Bell} label="Notifications" variant="outline" />
<IconButton icon={Settings} label="Settings" variant="ghost" />
<IconButton icon={Trash2} label="Delete" variant="destructive" />
</div>Sizes, code
<div className="flex flex-wrap items-center gap-gap-md">
<IconButton icon={Settings} label="Settings, small" size="sm" variant="outline" />
<IconButton icon={Settings} label="Settings, default" variant="outline" />
<IconButton icon={Settings} label="Settings, large" size="lg" variant="outline" />
<IconButton icon={Settings} label="Settings, touch" size="touch" variant="outline" />
</div>Inline, code
<div className="flex items-center gap-gap-lg p-inset-md">
<IconButton icon={X} label="Clear, inline" size="inline" />
<IconButton icon={X} label="Clear, inline outline" size="inline" variant="outline" />
<IconButton icon={X} label="Clear, inline round" size="inline" shape="round" variant="secondary" />
</div>Surfaces, code
<div className="flex flex-wrap items-center gap-gap-lg">
<div className="flex items-center gap-gap-md rounded-surface bg-surface p-inset-lg">
<IconButton icon={Pause} label="Pause" surface="media" shape="round" />
<IconButton icon={Heart} label="Like" surface="media" />
<IconButton icon={Camera} label="Switch camera" surface="media" size="touch" shape="round" />
<IconButton icon={Share} label="Share, disabled" surface="media" isDisabled />
</div>
<div className="flex items-center gap-gap-md rounded-surface bg-action-primary p-inset-lg">
<IconButton icon={X} label="Close banner" surface="brand" />
<IconButton icon={Share} label="Share offer" surface="brand" shape="round" />
</div>
</div>Shapes, code
<div className="flex flex-wrap items-center gap-gap-md">
<IconButton icon={ArrowLeft} label="Back" variant="outline" />
<IconButton icon={ArrowLeft} label="Back, round" variant="outline" shape="round" />
<IconButton icon={X} label="Close, round ghost" shape="round" />
<IconButton icon={X} label="Close, round touch" variant="secondary" shape="round" size="touch" />
</div>Tooltip open, code
<div className="flex items-center gap-gap-md pt-16">
<IconButton icon={Settings} label="Settings" variant="outline" defaultTooltipOpen />
</div>Disabled, code
<IconButton icon={Settings} label="Settings" isDisabled variant="outline" />The 21 design tokens IconButton reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.
| Token | Value now | CSS variable |
|---|---|---|
| button.height.lg | … | --sd-button-height-lg |
| button.height.sm | … | --sd-button-height-sm |
| color.action.primary | … | --sd-color-action-primary |
| color.action.primary-hover | … | --sd-color-action-primary-hover |
| color.action.primary-pressed | … | --sd-color-action-primary-pressed |
| color.bg.on-media | … | --sd-color-bg-on-media |
| color.bg.on-media-hover | … | --sd-color-bg-on-media-hover |
| color.border.control | … | --sd-color-border-control |
| color.text.on-media | … | --sd-color-text-on-media |
| color.text.on-primary | … | --sd-color-text-on-primary |
| elevation.2 | … | --sd-elevation-2 |
| icon-button.icon | … | --sd-icon-button-icon |
| icon-button.size | … | --sd-icon-button-size |
| layer.tooltip | … | --sd-layer-tooltip |
| radius.full | … | --sd-radius-full |
| size.icon.sm | … | --sd-size-icon-sm |
| space.8 | … | --sd-space-8 |
| target.min | … | --sd-target-min |
| tooltip.bg | … | --sd-tooltip-bg |
| tooltip.fg | … | --sd-tooltip-fg |
| tooltip.radius | … | --sd-tooltip-radius |
The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).
Install
npm i @superduperui/react @superduperui/tokensImport
import { IconButton } from "@superduperui/react"IconButton also takes the props of the React Aria component it’s built on.
| Prop | Type | What it does |
|---|---|---|
iconrequired | LucideIcon | The Lucide icon. |
labelrequired | string | Required accessible name: becomes aria-label and the tooltip text. An unnamed icon button does not compile. |
variant | Exclude<ButtonVariant, 'link'>Default 'ghost' | |
size | ButtonSize | 'touch' | 'inline'Default 'default' | sm 36px visual (44px hit area), default 44 x 44, lg 52 x 52, touch 48 x 48 with a 24px icon (the mobile preset; never under target.min), inline a 32px box with a 16px icon whose 44px target reaches outside it (a clear button inside a field, so the row keeps its own height; keep 44px clear around it). |
surface | 'media' | 'brand' | For a button on something other than the screen background. media: the on-media backing with a white glyph, for photos, video, maps and camera views (proven against a white image underneath). brand: the brand fill with the on-primary glyph, for a button on a brand-coloured surface. Either one replaces the variant's colours. In Figma this is the MediaButton set. |
shape | 'square' | 'round'Default 'square' | square (default) uses the control radius; round is a circle (radius full), for header and overlay buttons. The size, and so the 44px target, is the same. |
showTooltip | booleanDefault true | Show the label as a tooltip on hover and keyboard focus (1.4.13: hoverable, dismissable with Esc). Default true. |
tooltipPlacement | 'top' | 'bottom' | 'start' | 'end'Default 'top' | |
defaultTooltipOpen | boolean | Start with the tooltip open (docs, previews and the accessibility suite's open-tooltip story). |
Screen readers announce "Settings, button" (the tooltip repeats the label as a description).
WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6, 2.3.3.
Compact density meets AA (2.5.8, 24px targets), not AAA.
| axe-core (WCAG A, AA, AAA and best practice) | 180 runs across every story, theme, density and width: 0 violations |
|---|---|
| Rendered text contrast | 30 text runs: 0 below 7:1, lowest 16.71:1 |
| Target size | 96 targets: 0 under 44px in Comfortable |
| Focus appearance (2.4.13) | 108 focus stops in 3 browser engines: all pass |
| Keyboard script | Chromium 2 of 2, Firefox 2 of 2, WebKit 2 of 2 |
Manual passes with VoiceOver and NVDA haven’t been done yet.
Each step is scripted and run in Chromium, Firefox and WebKit.
| Key | What happens |
|---|---|
| Tab | Tab reaches the button; its name is the label and the tooltip opens on focus |
| Escape | Esc dismisses the tooltip without moving focus (1.4.13) |
The Figma component is IconButton, with Variant (Default, Secondary, Outline, Ghost, Destructive); Size (Small, Default, Large, Touch, Inline); State (Default, Hover, Pressed, Focus, Disabled); Shape (Square, Round). The Figma library isn’t published yet.
Figma to code: Variant → variant (Default = "default", Secondary = "secondary", Outline = "outline", Ghost = "ghost", Destructive = "destructive"); Size → size (Small = "sm", Default = "default", Large = "lg", Touch = "touch", Inline = "inline"); State (Default, Hover, Pressed, Focus, Disabled = isDisabled); Label → label; Icon → icon; Shape → shape (Square = "square", Round = "round").