Component
Button
Triggers an action. Six variants, three sizes.
Plain-text source, for agents and clipboard use: /components/source/button.txt
When to use it
Use a button for an action the user takes on this page — submitting, confirming, opening a dialog. Exactly one primary button per view or section; everything else is secondary, outline or ghost.
Examples
Variants
Primary carries the one action that matters. CTA yellow is reserved for a single conversion moment and never appears twice on a screen.
<button class="flux-button">Save changes</button>
<button class="flux-button flux-button--secondary">Cancel</button>
<button class="flux-button flux-button--outline">Export</button>
<button class="flux-button flux-button--ghost">Dismiss</button>
<button class="flux-button flux-button--danger">Delete booking</button>
<button class="flux-button flux-button--cta">Talk to us</button>Sizes
Small for toolbars and table rows, medium everywhere else, large only for a standalone page action.
<button class="flux-button flux-button--sm">Small</button>
<button class="flux-button">Medium</button>
<button class="flux-button flux-button--lg">Large</button>Disabled
Keep the button in the DOM and disabled rather than removing it, so the layout does not shift and the reason can be explained nearby.
<button class="flux-button" disabled>Save changes</button>
<button class="flux-button flux-button--secondary" disabled>Cancel</button>Opens a menu
A button that opens a menu or panel ends in a chevron, so it reads as a dropdown rather than an action. The chevron flips while aria-expanded is true. Requires flux-components.js for menu placement and keys.
<button class="flux-button flux-button--secondary" type="button" popovertarget="export-menu" aria-haspopup="menu" aria-expanded="false">Export<svg class="flux-button__chevron" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /></svg></button>
<div class="flux-menu" id="export-menu" popover role="menu" aria-label="Export format">
<button class="flux-menu__item" type="button" role="menuitem">CSV</button>
<button class="flux-menu__item" type="button" role="menuitem">Excel</button>
<button class="flux-menu__item" type="button" role="menuitem">PDF manifest</button>
</div>Anatomy
| Part | Description |
|---|---|
| Container | Fixed height from the size token, 4px radius, no shadow. |
| Label | Lexend Bold. Sentence case. A verb, and specific — "Save changes", not "Submit". |
| Icon (optional) | Leading or trailing, 16px, inheriting text colour via currentColor. |
API
| Name | Kind | Description |
|---|---|---|
flux-button | class | Base class. Primary teal fill by default. |
flux-button--secondary | class | Neutral fill on layer-03. For the lesser of two actions. |
flux-button--outline | class | Teal border and text, transparent fill. |
flux-button--ghost | class | Teal text only. For tertiary actions in dense chrome. |
flux-button--danger | class | Destructive actions. Pair with a confirmation. |
flux-button--cta | class | Bumble-Me Yellow. One per view, conversion only. |
flux-button--sm | --lg | class | Size modifiers. Medium is the default and needs no class. |
flux-button__chevron | class | Trailing line chevron on a button that opens a menu or panel. Pair the button with aria-haspopup and aria-expanded; the chevron flips while expanded. Never on a button that acts immediately. |
disabled | attribute | Native disabled. Do not simulate it with pointer-events. |
States
| State | Treatment |
|---|---|
| Default | surface-brand fill, text-on-color label. |
| Hover | surface-brand-hover. No lift, no shadow, no scale. |
| Active | surface-brand-active. |
| Focus | 2px focus-ring outline at 2px offset. Teal in every theme. |
| Disabled | 50% opacity, not-allowed cursor. Colour is unchanged. |
Keyboard
| Keys | Action |
|---|---|
Tab | Moves focus to the button. |
Space, Enter | Activates the button. |
Accessibility
- A button with only an icon needs an accessible name — use aria-label, never a title attribute alone.
- Focus is a 2px teal outline offset by 2px, meeting WCAG 1.4.11 at 5.8:1 on white.
- Disabled buttons are removed from the tab order by the native attribute; if the reason is not obvious, state it in adjacent text rather than a tooltip.
Tokens
The tier-3 and tier-2 tokens this component binds to. Change the token, not the component.
- --flux-button-radius
- --flux-button-height-sm | -md | -lg
- --flux-button-padding-x-sm | -md | -lg
- --flux-button-font-size-sm | -md | -lg
- --flux-surface-brand
- --flux-surface-brand-hover
- --flux-text-on-color
Do and don’t
Do
- Use one primary button per view. If two actions look equally important, one of them is not.
- Write labels as specific verbs: "Create departure", "Send evidence pack".
- Put the primary action last in a footer row, after Cancel.
Don’t
- Do not use gradient fills, glow shadows, or a scale transform on hover.
- Do not use CTA yellow for anything but a single conversion action.
- Do not invent variants. Six exist; a seventh is a design decision, not a class name.