Button
Buttons start an action: send a form, open a sheet, follow a step. One filled button per view carries the main action; ghost and text buttons carry the rest, and a red one marks the action that can’t be undone.
- CSS
css/components/button.css
01 — Variants
Primary, ghost and text
Primary is filled, for the main action. Ghost has a hairline edge, for the others. Text looks like a link, for low-key actions such as Cancel.
Destructive
Filled red, so it can’t be overlooked. Use it for the one action that deletes something or can’t be undone, usually in a confirm step with a plain way out beside it.
Remove prod-east?
Its saved context is deleted from this app. The cluster itself isn’t touched.
Icon button
A square button with a hairline icon. It must have an aria-label.
Toggle
A button that stays pressed, such as Follow and Following. It swaps its label and keeps aria-pressed in step.
As a link
Use an <a> when the button goes somewhere, and a <button> when it does something on the page.
02 — States
Hover, pressed, busy and disabled
Press and hold to see the pressed state. aria-busy="true" shows a hairline spinner; the form sets it while sending. Disabled buttons dim and their edge turns dashed.
03 — Usage
Use it for
- One primary button per view, for the action most people want.
- Verbs that say what happens: Post, Save changes, Delete photo.
- Text buttons for Cancel, Clear and other ways out.
Avoid
- Two primary buttons side by side. Make one ghost.
- The destructive button for anything that can be undone, or more than once in a view.
- Buttons for navigation between pages. Use a link.
- Icon buttons without a label, or icons nobody will recognize.
04 — Accessibility
Notes
- Buttons are 40px tall with a mouse and grow to 44px on touch screens.
- Every icon button needs an
aria-label; the SVG inside getsaria-hidden="true". - Toggles use
aria-pressed, so screen readers say “pressed” or “not pressed”. - Prefer the
disabledattribute for actions that can’t happen yet, and say why nearby.