Button
The complete action surface: nine variants, five sizes, and a loading state that preserves the control’s measured width.
Live preview
Source
The exact file rendered in the preview above.
components/demos/button.tsx
components/ui/button.tsx
components/ui/spinner.tsx
lib/variants.ts
Demo source — adapt to your project. Foundry is not published as a package.
Usage
Reach for Button whenever an interaction changes state. When the interaction navigates instead, use ButtonLink — it renders a real anchor with identical styling, which keeps middle-click, "open in new tab" and crawling intact.
- One primary button per view. If two actions compete, one of them is secondary.
- Loading replaces the label with a spinner but keeps the label in the DOM, so the button never resizes mid-click.
- Icon-only buttons must pass `aria-label`; the icon itself is always `aria-hidden`.
- Destructive actions should be paired with ConfirmDialog rather than relying on the red fill alone.
Variants and states
Every entry below is a genuine difference in behaviour or layout, and every one of them is visible in the preview above.
- Primary — the single most important action in a view
- Secondary — an equally valid alternative on an inverted fill
- Outline — the neutral default for toolbars and dialogs
- Ghost — for dense rows where a border would add noise
- Soft — tinted, for repeated non-primary actions
- Link — inline navigation that must read as prose
- Destructive, Success, Warning — reserved for outcomes
Accessibility
- Focus
- Focus is drawn by the global `:focus-visible` rule, so it is identical on every control in the library and never appears for pointer users.
- Busy state
- `aria-busy` is set while loading, and a visually hidden label announces what is happening.
- Disabled
- Disabled buttons are removed from the tab order. If the reason matters, explain it in adjacent text rather than a tooltip on an unfocusable control.
- Touch target
- The default and large sizes exceed the 44px minimum at Default and Relaxed density; Compact is intended for pointer-first admin surfaces.
Foundry implements published ARIA patterns and is tested against them. No WCAG certification is claimed — see the accessibility documentation for what is and is not covered.
Related
All componentsDropdown menu
The ARIA menu-button pattern with grouped items, roving focus, shortcuts and destructive styling.
intermediateFeatured6 variantsConfirmation
A destructive-action guard with a static backdrop, a pending state and a confirm button that is never focused first.
starter4 variantsSpinner
A pure-CSS indeterminate indicator that inherits currentColor and costs nothing to render.
starter3 variantsLogin
Email and password with a form-level rejection that does not reveal which half was wrong.
starterFeatured6 variants