Overview
The Button component provides an accessible, customizable button with support for multiple variants, sizes, and icons. It’s built on React Aria Components for full keyboard navigation and screen reader support.
Import
import { Button } from 'stride-ds';
Basic Usage
import { Button } from 'stride-ds';
function Example() {
return <Button>Click me</Button>;
}
Variants
The Button component supports four visual variants:
Primary
The default variant for primary actions.
<Button variant="primary">Primary Button</Button>
Secondary
For secondary actions with a subtle appearance.
<Button variant="secondary">Secondary Button</Button>
Ghost
For tertiary actions with minimal styling.
<Button variant="ghost">Ghost Button</Button>
Destructive
For dangerous or destructive actions.
<Button variant="destructive">Delete Account</Button>
Sizes
Three size options are available:
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
With Icons
Left Icon
import { Download } from 'lucide-react';
<Button leftIcon={<Download size={16} />}>
Download
</Button>
Right Icon
import { ArrowRight } from 'lucide-react';
<Button rightIcon={<ArrowRight size={16} />}>
Continue
</Button>
Both Icons
import { Star, ArrowRight } from 'lucide-react';
<Button
leftIcon={<Star size={16} />}
rightIcon={<ArrowRight size={16} />}
>
Favorite
</Button>
States
Disabled
<Button isDisabled>Disabled Button</Button>
Loading State
Combine with a loading icon for async operations:
import { Loader2 } from 'lucide-react';
<Button
isDisabled={isLoading}
leftIcon={isLoading ? <Loader2 className="animate-spin" size={16} /> : null}
>
{isLoading ? 'Loading...' : 'Submit'}
</Button>
Props
variant
'primary' | 'secondary' | 'ghost' | 'destructive'
default:"'primary'"
Visual style variant of the button.
size
'sm' | 'md' | 'lg'
default:"'md'"
Size of the button. Affects height, padding, and font size.
Icon to display on the left side of the button text.
Icon to display on the right side of the button text.
Whether the button is disabled. When disabled, the button cannot be pressed and shows reduced opacity.
Handler called when the button is pressed.
Handler called when a press interaction starts.
Handler called when a press interaction ends.
Additional CSS classes to apply to the button.
The content to display inside the button.
type
'button' | 'submit' | 'reset'
default:"'button'"
The button type (for form submission).
Accessibility
The Button component is built with React Aria Components and provides:
- Keyboard Navigation: Fully accessible via keyboard (Space/Enter to activate)
- Focus Management: Clear focus indicators that respect the design system
- Screen Reader Support: Proper ARIA attributes and roles
- Disabled State: Properly communicated to assistive technologies
Best Practices
-
Always provide meaningful text content or
aria-label for icon-only buttons:
<Button aria-label="Close dialog">
<X size={16} />
</Button>
-
Use appropriate variants for context:
primary for main actions
secondary for alternative actions
ghost for tertiary actions
destructive for dangerous operations
-
Provide visual feedback for loading states when performing async operations
Examples
All Variants
<div className="flex gap-4">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
</div>
All Sizes with Icons
import { Download } from 'lucide-react';
<div className="flex gap-4 items-center">
<Button size="sm" leftIcon={<Download size={14} />}>
Small
</Button>
<Button size="md" leftIcon={<Download size={16} />}>
Medium
</Button>
<Button size="lg" leftIcon={<Download size={18} />}>
Large
</Button>
</div>
function MyForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
return (
<form onSubmit={handleSubmit}>
{/* form fields */}
<Button
type="submit"
isDisabled={isSubmitting}
leftIcon={isSubmitting ? <Loader2 className="animate-spin" size={16} /> : null}
>
{isSubmitting ? 'Submitting...' : 'Submit Form'}
</Button>
</form>
);
}