Button
Five variants, four sizes, five states. All styles reference design tokens from shared/tokens.css. Toggle the theme to see dark mode instantly.
When to use
- Use for actions that trigger an immediate response — submit, save, delete, confirm
- Use Primary for the single most important action in a view
- Use Danger for destructive or irreversible actions like delete or remove
- Use Ghost or Tertiary for lower-emphasis supporting actions
- Use Secondary alongside a Primary to offer an alternative action
- Use two Primary buttons side by side — one action should always dominate
- Use a Button for navigation between pages — use a Link instead
- Use Ghost for destructive actions — Ghost implies safe/neutral, use Danger
- Stack more than 3 buttons in a single action area without grouping them
- Use a Button when an input field is needed — use Text Input
DigiLawyer Patterns
Product-specific conventions used across DigiLawyer interfaces. These apply on top of the generic usage rules above.
.btn-square for equal padding on all sides. The button keeps the same height — only the width adapts to a square.[icon] Label [icon] is valid — [icon] [icon] is not.Anatomy
A Button is composed of up to five parts. Only the label is required.
- 1Container — The clickable surface. Height is set by the size modifier (32 / 40 / 48 px).
- 2Leading icon — Optional. Placed left of the label to reinforce the action visually.
- 3Label — Required. Describes the action clearly and concisely in 1–3 words.
- 4Trailing icon — Optional. Use for directional cues such as arrows or chevrons.
- 5Loading spinner — Replaces all content during async operations when
.btn--loadingis applied.
Basic button
Apply .btn plus a variant class. Medium size is the default.
<button class="btn btn-primary btn-md"><span class="btn-label">Label</span></button> <button class="btn btn-secondary btn-md"><span class="btn-label">Label</span></button> <button class="btn btn-tertiary btn-md"><span class="btn-label">Label</span></button> <button class="btn btn-ghost btn-md"><span class="btn-label">Label</span></button> <button class="btn btn-danger btn-md"><span class="btn-label">Label</span></button>
Variants
Choose the variant that matches the action's emphasis level.
Sizes
btn-lg (48px) · btn-md (40px) · btn-sm (32px) · btn-xs (24px).
<button class="btn btn-primary btn-lg">...</button> <!-- 48px --> <button class="btn btn-primary btn-md">...</button> <!-- 40px --> <button class="btn btn-primary btn-sm">...</button> <!-- 32px --> <button class="btn btn-primary btn-xs">...</button> <!-- 24px -->
States
Hover and active handled by CSS. Disabled uses token-specific colors (not opacity). Active (Solid Border) is Tertiary-only.
<!-- Disabled — token-specific colors, not opacity --> <button class="btn btn-primary btn-md" disabled>...</button> <!-- Active solid border (Tertiary only) --> <button class="btn btn-active-border btn-md">...</button>
With icons
Wrap SVGs in <span class="icon">. Icon size is set automatically by the size modifier. Label padding is handled by .btn-label.
Loading
Add .btn-loading with disabled. Spinner color inherits from the variant token.
<button class="btn btn-primary btn-md btn-loading" disabled>...</button>
Full matrix
Every combination of state × size × variant.
| State / Size | Primary | Secondary | Tertiary | Ghost | Danger |
|---|
Responsive
Add .btn-full-mobile to stretch a button to full width on screens narrower than 744 px. At wider breakpoints the button stays auto-width. Use .btn-full to force full width at every breakpoint.
Frame above simulates a 390 px mobile viewport. On desktop the buttons remain auto-width.
<button class="btn btn-primary btn-md btn-full-mobile">...</button>
Accessibility
Button follows the WAI-ARIA Button pattern. Using a native <button> element provides all required semantics automatically.
| Attribute / Behaviour | Value | Notes |
|---|---|---|
| Role | button | Implicit from native <button> — no explicit role needed |
| Keyboard — activate | Enter Space | Both keys trigger the click handler on a focused button |
| Keyboard — focus | Tab / Shift+Tab | Buttons are in the natural tab order unless disabled |
disabled | HTML boolean attribute | Removes the button from tab order and blocks all pointer events |
aria-busy="true" | Applied when .btn--loading | Announced to screen readers during async operations |
aria-label | Descriptive string | Required on icon-only buttons where there is no visible label text |
type="button" | Always set explicitly | Prevents accidental form submission when the button is inside a <form> |
API
| Class | Values | Default | Description |
|---|---|---|---|
| variant | btn-primary|secondary|tertiary|ghost|danger | btn-primary | Visual style and emphasis |
| size | btn-lg|md|sm|xs | btn-md | Height: 48/40/32/24px |
| disabled | HTML attr | — | Token-based disabled colors per variant |
| btn-active-border | — | — | Solid border active state (Tertiary only) |
| btn-loading | — | — | Spinner, combine with disabled |
| .btn-label | wrap text content | — | 8px L/R padding (4px for xs) |
| .icon | wrap SVG | — | Auto-sized icon slot |