Button
Runs an action or submits a form. Primary is ink, not violet: the accent is kept for focus, links and the lamp.
Examples
Variants
One primary per view. Accent at most once per page. Ghost for toolbars and table rows.
Light
Dark
<Button>Add server</Button>
<Button variant="accent">Connect agent</Button>
<Button variant="secondary">Test connection</Button>
<Button variant="ghost">Cancel</Button>
<Button variant="danger">Delete server</Button>
<Button variant="danger-ghost">Remove</Button>Sizes and icons
<Button size="sm" variant="secondary" icon="refresh">Refresh</Button>
<Button size="md" icon="plus">Add server</Button>
<Button size="lg" variant="secondary" iconEnd="external-link">Open docs</Button>
<IconButton icon="settings" label="Settings" />Usage
import { Button, IconButton } from '@switchboard/ui'
<form method="post" action={routes.servers.create.href()}>
…
<Button type="submit" icon="plus">Add server</Button>
</form>Props
Every component also takes mix, for css() and mixins applied after its own style.
Button
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | 'primary' | 'accent' | 'secondary' | 'ghost' | 'danger' | 'danger-ghost' | 'primary' | Visual weight. Primary is ink. |
| size | 'sm' | 'md' | 'lg' | 'md' | Height 28, 32 or 36px. |
| icon | IconName | – | Leading icon. Replaced by a spinner while loading. |
| iconEnd | IconName | – | Trailing icon. |
| iconOnly | boolean | – | Square button showing only the icon. Needs aria-label; prefer IconButton. |
| loading | boolean | – | Spinner, aria-busy, clicks blocked, width kept. |
| block | boolean | – | Stretch to the container width. |
| href | string | – | Renders an <a> styled as a button. |
| disabled | boolean | – | On a link, drops the href and sets aria-disabled. |
| mix | Mix | – | Extra css() or mixins, applied after the button style. |
Also accepts every <button> attribute, or every <a> attribute when href is set.
IconButton
| Prop | Type | Default | Description |
|---|---|---|---|
| icon* | IconName | – | The icon. |
| label* | string | – | Accessible name and tooltip text. |
| variant | ButtonVariant | 'ghost' | Same variants as Button. |
| tooltip | 'top' | 'bottom' | 'left' | 'right' | false | 'top' | Tooltip placement, or false for none. |
Accessibility
- Renders a native <button type="button"> (or <a> with href), so Enter and Space work without JavaScript.
- Icon-only buttons need a name: IconButton sets aria-label from `label` and shows it as a tooltip.
- Loading sets aria-busy and keeps focus on the button; the spinner has no separate label.
- Focus ring is the shared 2px accent ring with a page-coloured gap.
Guidance
Do
- Name the action with a verb and its object: "Add server", "Delete skill".
- Use one primary button per view; make the rest secondary or ghost.
Don’t
- Use the accent variant as a general brand colour.
- Put "Submit", "OK" or a trailing arrow on a button.