Primary for the one thing you want someone to do on the page. Secondary and ghost for everything else.

One primary button per view. More than one is a sign you have not yet decided what matters.

Usage

<button class="of-btn of-btn--primary of-btn--md">Book a call</button>
<button class="of-btn of-btn--secondary of-btn--md">Read the notes</button>
<button class="of-btn of-btn--ghost of-btn--md">Cancel</button>
<button class="of-btn of-btn--tint of-btn--md">Invite team</button>
<button class="of-btn of-btn--secondary of-btn--md of-btn--disabled" disabled>Unavailable</button>

Variants

Sizes

Disabled

Use disabled state when the action is not currently available. Keep the label specific so people know why the action exists.

Props

PropTypeDefaultDescription
variant'primary' | 'secondary' | 'ghost' | 'tint' | 'danger''primary'Visual weight
size'sm' | 'md' | 'lg''md'Target size; use lg on marketing pages
loadingbooleanfalseShows a spinner and disables the button
disabledbooleanfalseDisables the button
asElementType'button'Render as a different element (e.g. a)

Accessibility

Buttons are keyboard-focusable and trigger on Enter or Space. A loading button keeps focus and announces status via aria-busy. If you use as="a", make sure the link has an href — a link without one is not keyboard-focusable.