ComponentButtonInteractiveForms
Button Variants
A flexible button component with multiple variants including primary, secondary, outline, and ghost styles. Supports different sizes and loading states.
Preview
Code
import { clsx } from 'clsx'
import { Loader2 } from 'lucide-react'
type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost'
type ButtonSize = 'sm' | 'md' | 'lg'
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant
size?: ButtonSize
loading?: boolean
children: React.ReactNode
}
const variants: Record<ButtonVariant, string> = {
primary: 'bg-olive-950 text-white hover:bg-olive-800 dark:bg-olive-300 dark:text-olive-950',
secondary: 'bg-olive-100 text-olive-900 hover:bg-olive-200 dark:bg-olive-800 dark:text-olive-100',
outline: 'border border-olive-300 text-olive-700 hover:bg-olive-50 dark:border-olive-700 dark:text-olive-300',
ghost: 'text-olive-700 hover:bg-olive-100 dark:text-olive-300 dark:hover:bg-olive-800',
}
const sizes: Record<ButtonSize, string> = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-sm',
lg: 'px-6 py-3 text-base',
}
export function Button({
variant = 'primary',
size = 'md',
loading = false,
disabled,
children,
className,
...props
}: ButtonProps) {
return (
<button
disabled={disabled || loading}
className={clsx(
'inline-flex items-center justify-center gap-2 rounded-lg font-medium transition-colors',
'disabled:opacity-50 disabled:cursor-not-allowed',
variants[variant],
sizes[size],
className
)}
{...props}
>
{loading && <Loader2 className="size-4 animate-spin" />}
{children}
</button>
)
}Looking for more?
Browse the full collection of components or check out other exploration topics.