3,200+ hardcoded color values replaced with CSS variable-backed Tailwind classes (bg-card, text-foreground, border-border, etc.). Enables light mode via CSS variable swap. Only syntax highlighting colors and intentional one-offs remain hardcoded (~15 values). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
import { cva, type VariantProps } from 'class-variance-authority'
|
|
import { cn } from '@/lib/utils'
|
|
import { Spinner } from '@/components/common/Spinner'
|
|
|
|
const buttonVariants = cva(
|
|
'inline-flex items-center justify-center gap-2 font-medium transition-all duration-200 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98]',
|
|
{
|
|
variants: {
|
|
variant: {
|
|
primary:
|
|
'bg-primary text-white font-semibold hover:brightness-110',
|
|
secondary:
|
|
'bg-input border border-border text-foreground hover:border-border-hover hover:bg-border',
|
|
destructive:
|
|
'bg-red-400/10 text-red-400 border border-red-400/20 hover:bg-red-400/20',
|
|
ghost:
|
|
'text-muted-foreground hover:bg-accent hover:text-foreground',
|
|
link:
|
|
'text-primary underline-offset-4 hover:underline p-0 h-auto',
|
|
},
|
|
size: {
|
|
sm: 'h-8 px-3 text-xs rounded-lg',
|
|
md: 'h-9 px-4 text-sm rounded-lg',
|
|
lg: 'h-10 px-6 text-sm rounded-lg',
|
|
icon: 'size-9 rounded-lg',
|
|
'icon-sm': 'size-8 rounded-lg',
|
|
},
|
|
},
|
|
defaultVariants: {
|
|
variant: 'primary',
|
|
size: 'md',
|
|
},
|
|
}
|
|
)
|
|
|
|
export interface ButtonProps
|
|
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
VariantProps<typeof buttonVariants> {
|
|
loading?: boolean
|
|
}
|
|
|
|
export function Button({
|
|
className,
|
|
variant,
|
|
size,
|
|
loading,
|
|
children,
|
|
disabled,
|
|
...props
|
|
}: ButtonProps) {
|
|
return (
|
|
<button
|
|
className={cn(buttonVariants({ variant, size, className }))}
|
|
disabled={disabled || loading}
|
|
{...props}
|
|
>
|
|
{loading && <Spinner size="sm" />}
|
|
{children}
|
|
</button>
|
|
)
|
|
}
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export { buttonVariants }
|