Skip to content

Button Component

A versatile, accessible button component with theme-aware styling, semantic color variants, and comprehensive interaction states. Built on modern web standards with full TypeScript support and cross-platform design token integration.

  • 🎨 Theme-Aware: Automatic light/dark mode support via CSS custom properties
  • 🎯 Semantic Variants: Contextual colors for success, warning, and error states
  • ♿ Accessible: Full keyboard navigation, focus management, and ARIA compliance
  • 🔧 Flexible: Multiple sizes, variants, and customization options
  • ⚡ Performance: Lightweight with minimal JavaScript footprint
  • 📱 Responsive: Adapts to different screen sizes and touch targets

Loading Button showcase...

The four core button variants provide different visual hierarchies for your interface:

// Primary: Main call-to-action, highest emphasis
<Button variant="primary">Get Started</Button>
// Secondary: Supporting actions, medium emphasis
<Button variant="secondary">Learn More</Button>
// Outline: Low emphasis, maintains presence
<Button variant="outline">Cancel</Button>
// Ghost: Minimal emphasis, subtle interactions
<Button variant="ghost">Skip</Button>

Usage Guidelines:

  • Primary: Use for the most important action on a page (typically 1 per view)
  • Secondary: For secondary actions that support the primary goal
  • Outline: For actions that need visual presence without strong emphasis
  • Ghost: For tertiary actions, navigation, or when space is constrained

Three carefully designed sizes to fit different contexts and hierarchies:

// Small: Compact spaces, toolbars, inline actions
<Button size="sm">Save</Button>
// Medium: Default size, most common use case
<Button size="md">Submit Form</Button>
// Large: Hero sections, prominent CTAs
<Button size="lg">Get Started Now</Button>

Size Guidelines:

  • Small (sm): 44px min height, ideal for toolbars and dense layouts
  • Medium (md): Default 48px height, optimal for most interfaces
  • Large (lg): 56px height, perfect for landing pages and CTAs

Semantic variants provide contextual meaning and immediate visual feedback:

// Success: Confirmations, completions
<Button semantic="success">Save Changes</Button>
// Warning: Caution required, reversible actions
<Button semantic="warning">Archive Item</Button>
// Error: Destructive actions, permanent changes
<Button semantic="error">Delete Account</Button>

All buttons include comprehensive interaction states for better user feedback:

// Disabled state
<Button disabled>Processing...</Button>
// With loading state (custom implementation)
<Button disabled>
Loading...
</Button>

Real-world example showing button variants working together in a form context:

<form onSubmit={handleSubmit}>
{/* Form fields */}
<div className="form-actions">
<Button
type="button"
variant="ghost"
onClick={() => router.back()}
>
Cancel
</Button>
<Button
type="button"
variant="outline"
onClick={saveDraft}
>
Save Draft
</Button>
<Button
type="submit"
variant="primary"
>
Publish Article
</Button>
</div>
</form>

Props

NameTypeRequiredDefaultDescription
variant"primary" | "secondary" | "outline" | "ghost" | undefinedOptionalThe visual style variant of the button
size"sm" | "md" | "lg" | undefinedOptionalThe size of the button
semantic"default" | "success" | "warning" | "error" | undefinedOptionalThe semantic color variant for contextual styling
PropTypeDefaultDescription
variant'primary' | 'secondary' | 'outline' | 'ghost''primary'Visual style variant
size'sm' | 'md' | 'lg''md'Button size
semantic'default' | 'success' | 'warning' | 'error''default'Semantic color variant
disabledbooleanfalseDisables button interaction
type'button' | 'submit' | 'reset''button'HTML button type
onClick(event: MouseEvent) => void-Click event handler
childrenReact.ReactNode-Button content
classNamestring-Additional CSS classes

The Button component extends HTMLButtonElement and accepts all standard button attributes:

  • aria-label, aria-describedby for accessibility
  • data-* attributes for testing and analytics
  • id, name for form integration
  • tabIndex for custom focus management

The Button component uses the following design tokens from @sparkle/theme:

/* Primary colors */
--theme-primary-50 to --theme-primary-900
/* Semantic colors */
--theme-success-50 to --theme-success-900
--theme-warning-50 to --theme-warning-900
--theme-error-50 to --theme-error-900
/* Secondary colors */
--theme-secondary-50 to --theme-secondary-900
/* Button padding */
--spacing-sm: 0.5rem
--spacing-md: 1rem
--spacing-lg: 1.5rem
/* Typography */
--font-weight-medium: 500
--border-radius-md: 0.375rem

The Button component is built with accessibility as a priority:

  • Space/Enter: Activates the button
  • Tab: Moves focus to/from the button
  • Escape: Can be used to cancel actions (custom implementation)
  • Proper semantic <button> element
  • Support for aria-label and aria-describedby
  • Clear focus indicators with high contrast
  • Disabled state properly communicated
// ✅ Good: Clear, descriptive text
<Button>Save Document</Button>
// ✅ Good: Descriptive aria-label for icon buttons
<Button aria-label="Close dialog">×</Button>
// ✅ Good: Disabled state with loading indicator
<Button disabled aria-label="Saving document...">
Saving...
</Button>
// ❌ Avoid: Vague or unclear text
<Button>Click Here</Button>
// ❌ Avoid: Missing labels for icon-only buttons
<Button>×</Button>
  • Visible focus ring with 2px offset
  • High contrast focus indicators
  • Respects prefers-reduced-motion
  • Focus trapping in modal contexts (when applicable)

The Button component generates semantic CSS classes that can be targeted for customization:

/* Component styles */
.theme-transition { /* Base transition styles */ }
/* Size variants */
.btn-sm { /* Small button styles */ }
.btn-md { /* Medium button styles */ }
.btn-lg { /* Large button styles */ }
/* Variant styles applied via Tailwind utilities */
// Custom CSS classes
<Button className="my-custom-button">
Custom Button
</Button>
// Styled with CSS-in-JS
const StyledButton = styled(Button)`
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
&:hover {
transform: translateY(-2px);
}
`;

Modify button appearance by updating theme tokens:

tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
'theme-primary': {
500: '#your-brand-color',
600: '#your-brand-hover',
}
}
}
}
}
const [loading, setLoading] = useState(false);
<Button
disabled={loading}
onClick={async () => {
setLoading(true);
await saveData();
setLoading(false);
}}
>
{loading ? 'Saving...' : 'Save'}
</Button>
<Button
variant={isDestructive ? 'primary' : 'outline'}
semantic={isDestructive ? 'error' : 'default'}
>
{isDestructive ? 'Delete' : 'Archive'}
</Button>
import { SaveIcon } from '@heroicons/react/24/outline';
<Button>
<SaveIcon className="w-4 h-4 mr-2" />
Save Document
</Button>
  • Form - For form submission buttons
  • FormSubmit - Specialized submit button with validation
  • Link Button - For navigation actions (coming soon)

View the source code for this component:

  • v1.0.0: Initial button component with variants and semantic colors
  • v1.1.0: Added size variants and improved accessibility
  • v1.2.0: Enhanced theme integration and design tokens

For detailed TypeScript definitions and additional API information, see the API Documentation.

Three sizes available: small, medium (default), and large:

<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>

Semantic color variants for contextual actions:

<Button semantic="default">Default</Button>
<Button semantic="success">Success</Button>
<Button semantic="warning">Warning</Button>
<Button semantic="error">Error</Button>

Different interactive states including disabled:

<Button>Normal</Button>
<Button disabled>Disabled</Button>
<Button onClick={() => alert('Clicked!')}>Clickable</Button>

Complex combinations of variants, sizes, and semantic colors:

<Button variant="primary" size="lg" semantic="success">
✅ Save Changes
</Button>
<Button variant="outline" size="lg" semantic="error">
❌ Cancel
</Button>
<Button variant="ghost" size="sm">
📝 Edit
</Button>
<Button variant="ghost" size="sm" semantic="error">
🗑️ Delete
</Button>

Props

NameTypeRequiredDefaultDescription
variant"primary" | "secondary" | "outline" | "ghost" | undefinedOptionalThe visual style variant of the button
size"sm" | "md" | "lg" | undefinedOptionalThe size of the button
semantic"default" | "success" | "warning" | "error" | undefinedOptionalThe semantic color variant for contextual styling

Explore all Button variations in our interactive Storybook:

  • Primary actions: Use the primary variant for the main action on a page
  • Secondary actions: Use secondary or outline variants for supporting actions
  • Destructive actions: Use the error semantic variant for delete/remove actions
  • Success confirmations: Use the success semantic variant for save/confirm actions

The Button component includes:

  • Proper ARIA attributes for screen readers
  • Keyboard navigation support (Tab, Enter, Space)
  • Focus indicators that meet WCAG contrast requirements
  • Disabled state handling that prevents interaction

Buttons automatically adapt to light and dark themes using CSS custom properties from @sparkle/theme. The semantic color variants maintain proper contrast ratios across all theme modes.

  • IconButton: For icon-only actions
  • ButtonGroup: For related button collections
  • ToggleButton: For on/off state toggles