Interactive Playground

Build your button by selecting options below.

<button class="btn btn-primary btn-md">Button</button>

Button Variants

Three variants for different levels of visual emphasis.

<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-ghost">Ghost</button>

Sizes

Three sizes to fit different contexts and hierarchy.

<button class="btn btn-primary btn-sm">Small</button>
<button class="btn btn-primary btn-md">Medium</button>  
<button class="btn btn-primary btn-lg">Large</button>

With Icons

Buttons can include icons for additional visual context.

<button class="btn btn-primary btn-icon-left">
  <svg>...</svg>
  Continue
</button>

<button class="btn btn-ghost btn-icon-only" aria-label="Settings">
  <svg>...</svg>
</button>

Persona Variants

Buttons can adopt persona colors for contextual actions.

<button class="btn btn-persona btn-persona--ferni">Talk to Ferni</button>
<button class="btn btn-persona btn-persona--maya">Talk to Maya</button>
<button class="btn btn-persona btn-persona--peter">Talk to Peter</button>

States

Buttons provide visual feedback for different interaction states.

<button class="btn btn-primary">Default</button>
<button class="btn btn-primary" disabled>Disabled</button>
<button class="btn btn-primary btn-loading">
  <span class="btn-spinner"></span>
  Loading
</button>

Full Width

Buttons can expand to fill their container.

<button class="btn btn-primary btn-block">Full Width Button</button>

CSS Custom Properties

Token Description
--accent-primary Primary button background
--accent-hover Primary button hover state
--border-medium Secondary button border
--radius-md Button border radius
--duration-fast Transition duration

Full CSS

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-5);
  border: none;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-ease-out);
  text-decoration: none;
}

/* Primary */
.btn-primary {
  background: var(--accent-primary);
  color: var(--text-inverse);
}

.btn-primary:hover {
  background: var(--accent-hover);
  transform: translateY(-1px);
}

/* Secondary */
.btn-secondary {
  background: transparent;
  color: var(--text-primary);
  border: 1px solid var(--border-medium);
}

.btn-secondary:hover {
  border-color: var(--accent-primary);
  color: var(--accent-primary);
}

/* Ghost */
.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
}

.btn-ghost:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

/* Sizes */
.btn-sm { padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }
.btn-md { padding: var(--space-3) var(--space-5); font-size: var(--text-sm); }
.btn-lg { padding: var(--space-4) var(--space-6); font-size: var(--text-base); }

/* States */
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.btn-block {
  width: 100%;
}

/* Loading */
.btn-loading {
  pointer-events: none;
}

.btn-spinner {
  width: 16px;
  height: 16px;
  border: 2px solid transparent;
  border-top-color: currentColor;
  border-radius: 50%;
  animation: btn-spin 0.8s linear infinite;
}

@keyframes btn-spin {
  to { transform: rotate(360deg); }
}

Accessibility

Focus Indicators

All buttons have visible focus rings for keyboard navigation. Never remove :focus-visible styles.

Icon-Only Buttons

Always include aria-label on icon-only buttons to describe the action.

Loading States

Use aria-busy="true" during loading to announce state to screen readers.