Skip to content

Button

The button pattern provides accessible, semantic buttons with consistent styling and multiple variants.

<button class="af-btn">
  Primary Button
</button>

Use the af-is-* modifier classes to change the button’s intent. af-btn is primary by default:

  • af-is-secondary - Secondary action (less prominent than primary)
  • af-is-tertiary - Tertiary action (least prominent)
  • af-is-success - Success/positive action
  • af-is-warning - Warning action
  • af-is-danger - Destructive action
  • af-is-info - Informational action
  • af-is-outline - Transparent background with border
<button class="af-btn">
  Primary
</button>
<button class="af-btn af-is-secondary">
  Secondary
</button>
<button class="af-btn af-is-tertiary">
  Tertiary
</button>
<button class="af-btn af-is-success">
  Success
</button>
<button class="af-btn af-is-warning">
  Warning
</button>
<button class="af-btn af-is-danger">
  Danger
</button>
<button class="af-btn af-is-info">
  Info
</button>
<button class="af-btn af-is-outline">
  Outline
</button>

Use af-is-outline to create a border-only button. It can be combined with intent classes.

<button class="af-btn af-is-outline">
  Outline
</button>
<button class="af-btn af-is-outline af-is-secondary">
  Outline Secondary
</button>
<button class="af-btn af-is-outline af-is-tertiary">
  Outline Tertiary
</button>
<button class="af-btn af-is-outline af-is-success">
  Outline Success
</button>

Buttons come in three sizes:

<button class="af-btn af-is-sm">
  Small
</button>
<button class="af-btn">
  Default
</button>
<button class="af-btn af-is-lg">
  Large
</button>

Buttons expose a few component tokens for easy sizing and spacing overrides:

  • --af-control-min-height (shared across controls)
  • --af-btn-min-height
  • --af-btn-gap
  • --af-btn-icon-size
  • --af-btn-padding-x, --af-btn-padding-y, --af-btn-radius
<style>
  :root { --af-btn-min-height: 3rem; --af-btn-gap: 0.75rem; }
</style>
<button class="af-btn">
  Primary
</button>

For accessibility, prefer the native disabled attribute first (for <button> elements), with the CSS class af-is-disabled available as a fallback (e.g., for <a> tags instead of <button>):

<!-- Preferred: Use native disabled attribute for accessibility -->
<button class="af-btn" disabled>
  Disabled Button
</button>
<button class="af-btn" disabled>
  Disabled Primary
</button>
<!-- Fallback: CSS class for non-button elements -->
<a href="#" class="af-btn af-is-disabled">
  Disabled Link
</a>

Use the loading state to indicate an action in progress. For accessibility, prefer ARIA attributes first (aria-busy="true"), with CSS classes available as a fallback (e.g., for <a> tags instead of <button>):

<!-- Preferred: Use ARIA attribute for accessibility -->
<button class="af-btn" aria-busy="true">
  Loading...
</button>
<!-- Fallback: CSS class for non-button elements -->
<a href="#" class="af-btn af-is-loading">
  Loading...
</a>

For toggle buttons or active states. For accessibility, prefer ARIA attributes first (aria-pressed="true" for toggles or aria-current="page" for navigation), with CSS classes available as a fallback (e.g., for <a> tags instead of <button>):

<!-- Preferred: Use ARIA attribute for accessibility -->
<button class="af-btn" aria-pressed="true">
  Active
</button>
<a href="#" class="af-btn" aria-current="page">
  Current Page
</a>
<!-- Fallback: CSS class for non-button elements -->
<a href="#" class="af-btn af-is-active">
  Active
</a>
  • Uses native <button> element for proper semantics
  • Visible focus ring enabled by default
  • Keyboard accessible (Enter/Space)
  • Screen reader friendly
  • Icon buttons must have aria-label for accessibility
  • Always use semantic <button> elements, not <div> with click handlers
  • Visible focus is enabled by default and should not be removed
  • Disabled buttons maintain proper ARIA attributes
  • Use link buttons (<a class="af-btn">) only for navigation, not actions
  • Provide aria-label for icon-only buttons