Button

Forms
Core

Versatile button component with multiple variants, sizes, loading states, and icon support. Fully accessible with WCAG 2.2 AA compliance.

Preview

Interactive button examples

Variants

Semantic variants for different actions

Sizes

Standard and icon-only sizes

Standard Sizes

Icon-Only

With Icons

Icons before or after button text

Loading States

Built-in loading spinner with accessible labels

Full Width

Buttons that stretch to fill their container

Disabled State

Consistent disabled styling across variants

Props

Button component API reference

PropTypeDefaultDescription
variant'primary' | 'secondary' | 'inverse' | 'ghost' | 'destructive' | 'destructive-secondary' | 'link''primary'Visual style variant
size'sm' | 'md' | 'lg' | 'icon-sm' | 'icon' | 'icon-lg''md'Size variant
fullWidthbooleanfalseFill container width
asChildbooleanfalseRender as child component (polymorphic)
loadingbooleanfalseShow loading spinner
loadingTextstringAccessible label for loading state
leftIconReactNodeIcon before the label
rightIconReactNodeIcon after the label
disabledbooleanfalseDisable interaction

Usage

Import and implementation example

import { Button } from '@/components/ui/button'
import { Download, Trash2 } from 'lucide-react'
import Link from 'next/link'

export default function Example() {
  return (
    <>
      {/* Basic usage */}
      <Button>Click me</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="inverse">Inverse</Button>

      {/* With icons */}
      <Button leftIcon={<Download />}>Download</Button>
      <Button variant="destructive" leftIcon={<Trash2 />}>Delete</Button>

      {/* Loading state */}
      <Button loading loadingText="Saving...">Save</Button>

      {/* Icon only */}
      <Button size="icon"><Settings /></Button>

      {/* As link */}
      <Button asChild>
        <Link href="/about">About</Link>
      </Button>
    </>
  )
}

Features

Built-in functionality

  • 7 variants: Primary, secondary, inverse, ghost, destructive, destructive-secondary, link
  • 6 sizes: sm, md, lg, icon-sm, icon, icon-lg
  • Loading states: Built-in spinner with custom loading text
  • Icon support: Left and right icon positioning
  • Polymorphic: Use asChild prop with Next.js Link
  • Full width: Option to fill container width
  • Accessible: WCAG 2.2 AA compliant with proper focus states
  • Dark mode: Full dark mode support

Accessibility

Accessibility considerations

ARIA Attributes

aria-disabled when disabled or loadingaria-busy during loading stateIcons have aria-hidden="true"

Keyboard Navigation

KeyAction
TabFocus the button
Enter / SpaceActivate the button

Notes

  • Uses native button element for accessibility
  • Loading state prevents double-submission
  • Focus ring visible on keyboard navigation
  • Color contrast meets WCAG AA requirements