button.tsx58 lines · main
| 1 | import { cva, type VariantProps } from 'class-variance-authority'; |
| 2 | import { forwardRef, type ButtonHTMLAttributes } from 'react'; |
| 3 | |
| 4 | import { cn } from '../lib/cn.js'; |
| 5 | |
| 6 | const buttonVariants = cva( |
| 7 | [ |
| 8 | 'inline-flex items-center justify-center gap-2 whitespace-nowrap', |
| 9 | 'rounded-[var(--radius-md)] font-medium', |
| 10 | 'transition-[background-color,border-color,color,box-shadow] duration-[var(--duration-fast)] ease-[var(--ease-briven)]', |
| 11 | 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary)]', |
| 12 | 'disabled:pointer-events-none disabled:opacity-50', |
| 13 | ].join(' '), |
| 14 | { |
| 15 | variants: { |
| 16 | variant: { |
| 17 | primary: [ |
| 18 | 'bg-[var(--color-primary)] text-[var(--color-text-inverse)]', |
| 19 | 'hover:bg-[var(--color-primary-hover)] active:bg-[var(--color-primary-pressed)]', |
| 20 | 'shadow-[var(--shadow-sm)]', |
| 21 | ].join(' '), |
| 22 | outline: [ |
| 23 | 'border border-[var(--color-border)] bg-transparent text-[var(--color-text)]', |
| 24 | 'hover:border-[var(--color-border-strong)] hover:bg-[var(--color-surface-raised)]', |
| 25 | ].join(' '), |
| 26 | ghost: [ |
| 27 | 'bg-transparent text-[var(--color-text)]', |
| 28 | 'hover:bg-[var(--color-primary-ghost)]', |
| 29 | ].join(' '), |
| 30 | danger: [ |
| 31 | 'bg-[var(--color-error)] text-[var(--color-text-inverse)]', |
| 32 | 'hover:opacity-90', |
| 33 | ].join(' '), |
| 34 | }, |
| 35 | size: { |
| 36 | sm: 'h-8 px-3 text-[var(--text-small)]', |
| 37 | md: 'h-10 px-4 text-[var(--text-body)]', |
| 38 | lg: 'h-12 px-6 text-[var(--text-body)]', |
| 39 | }, |
| 40 | }, |
| 41 | defaultVariants: { |
| 42 | variant: 'primary', |
| 43 | size: 'md', |
| 44 | }, |
| 45 | }, |
| 46 | ); |
| 47 | |
| 48 | export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & |
| 49 | VariantProps<typeof buttonVariants>; |
| 50 | |
| 51 | export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button( |
| 52 | { className, variant, size, ...rest }, |
| 53 | ref, |
| 54 | ) { |
| 55 | return ( |
| 56 | <button ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...rest} /> |
| 57 | ); |
| 58 | }); |