Button

Atom

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

✅ Do
  • 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
❌ Don't
  • 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.

Secondary on dark backgrounds
Always use the Secondary variant when placing a button on a dark surface. Primary on dark creates contrast imbalance and draws too much weight.
Primary + Tertiary pairing
When offering a main action alongside an alternative, always pair Primary with Tertiary. Never pair two Primary buttons or Primary with Secondary.
Icon-only = single icon + equal padding
When using a button with no label, use exactly one icon and add .btn-square for equal padding on all sides. The button keeps the same height — only the width adapts to a square.
Never two icons without a label
Two icons side by side with no label is not allowed. A label must always sit between them. [icon] Label [icon] is valid — [icon] [icon] is not.
✅ Do
❌ Don't

Anatomy

A Button is composed of up to five parts. Only the label is required.

  1. 1Container — The clickable surface. Height is set by the size modifier (32 / 40 / 48 px).
  2. 2Leading icon — Optional. Placed left of the label to reinforce the action visually.
  3. 3Label — Required. Describes the action clearly and concisely in 1–3 words.
  4. 4Trailing icon — Optional. Use for directional cues such as arrows or chevrons.
  5. 5Loading spinner — Replaces all content during async operations when .btn--loading is applied.

Basic button

Apply .btn plus a variant class. Medium size is the default.

HTML
<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.

primaryHigh emphasis — main call to action
secondaryMedium emphasis — alternative action
tertiaryLow emphasis — outline style
ghostMinimal — toolbars and inline actions
dangerDestructive — delete, remove, reset

Sizes

btn-lg (48px) · btn-md (40px) · btn-sm (32px) · btn-xs (24px).

HTML
<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.

HTML
<!-- 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.

Left icon
Right icon
Both
Label only

Loading

Add .btn-loading with disabled. Spinner color inherits from the variant token.

HTML
<button class="btn btn-primary btn-md btn-loading" disabled>...</button>

Full matrix

Every combination of state × size × variant.

State / Size PrimarySecondaryTertiaryGhostDanger

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.

HTML
<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 / BehaviourValueNotes
RolebuttonImplicit from native <button> — no explicit role needed
Keyboard — activateEnter SpaceBoth keys trigger the click handler on a focused button
Keyboard — focusTab / Shift+TabButtons are in the natural tab order unless disabled
disabledHTML boolean attributeRemoves the button from tab order and blocks all pointer events
aria-busy="true"Applied when .btn--loadingAnnounced to screen readers during async operations
aria-labelDescriptive stringRequired on icon-only buttons where there is no visible label text
type="button"Always set explicitlyPrevents accidental form submission when the button is inside a <form>

API

ClassValuesDefaultDescription
variantbtn-primary|secondary|tertiary|ghost|dangerbtn-primaryVisual style and emphasis
sizebtn-lg|md|sm|xsbtn-mdHeight: 48/40/32/24px
disabledHTML attrToken-based disabled colors per variant
btn-active-borderSolid border active state (Tertiary only)
btn-loadingSpinner, combine with disabled
.btn-labelwrap text content8px L/R padding (4px for xs)
.iconwrap SVGAuto-sized icon slot