Button
A versatile button component with multiple variants, sizes, and states. Built with accessibility in mind and fully customizable.
Installation
Add the Button component to your project:
npx @elixir-labs/ui add button
Usage
import { Button } from "@/components/ui/button";
export default function MyComponent() {
return <Button>Click me</Button>;
}
Examples
Default
<Button>Button</Button>
Variants
<Button variant="default">Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
Sizes
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<Button size="icon">🚀</Button>
Disabled State
<Button disabled>Disabled</Button>
<Button variant="secondary" disabled>Disabled Secondary</Button>
With Icons
<Button>📧 Send Email</Button>
<Button variant="outline">⬇️ Download</Button>
<Button variant="secondary">🔄 Refresh</Button>
// With icon libraries like Lucide or Heroicons
import { Mail, Download, RefreshCw } from 'lucide-react';
<Button><Mail className="mr-2 h-4 w-4" />Send Email</Button>
<Button variant="outline"><Download className="mr-2 h-4 w-4" />Download</Button>
Interactive Example
const [clickCount, setClickCount] = useState(0);
return (
<div className="flex items-center gap-4">
<Button onClick={() => setClickCount(clickCount + 1)}>
Clicked {clickCount} times
</Button>
<Button variant="outline" onClick={() => setClickCount(0)}>
Reset
</Button>
</div>
);
API Reference
Prop | Type | Default | Description |
---|---|---|---|
variant | "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "default" | The visual style variant of the button |
size | "sm" | "md" | "lg" | "icon" | "md" | The size of the button |
disabled | boolean | false | Whether the button is disabled |
className | string | - | Additional CSS classes to apply |
children | ReactNode | - | The content of the button |
Source Code
The complete source code for the Button component:
import React from 'react';
import { clsx } from 'clsx';
const Button = React.forwardRef(({
children,
variant = 'default',
size = 'md',
disabled = false,
className,
...props
}, ref) => {
const baseClasses = 'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';
const variants = {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
};
const sizes = {
sm: 'h-9 rounded-md px-3 text-xs',
md: 'h-10 px-4 py-2',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10',
};
return (
<button
className={clsx(
baseClasses,
variants[variant],
sizes[size],
className
)}
ref={ref}
disabled={disabled}
{...props}
>
{children}
</button>
);
});
Button.displayName = 'Button';
export { Button };
Accessibility
The Button component follows WAI-ARIA guidelines:
- Uses semantic <button> element for proper screen reader support
- Includes focus-visible styles for keyboard navigation
- Properly handles disabled state with aria attributes
- Supports all standard button ARIA properties
Customization
You can customize the button by modifying the CSS variables or extending the component:
// Custom button with additional styling
const CustomButton = ({ className, ...props }) => {
return (
<Button
className={`shadow-lg transform hover:scale-105 transition-transform ${className}`}
{...props}
/>
);
};
// Usage
<CustomButton variant="default">Hover to scale</CustomButton>
💡 Pro Tip
Use the "asChild" pattern with React libraries like Next.js Link or React Router for navigation buttons while maintaining all button styling and accessibility features.