button.tsx raw
1 import * as React from 'react'
2 import { Slot } from '@radix-ui/react-slot'
3 import { cva, type VariantProps } from 'class-variance-authority'
4
5 import { cn } from '@/lib/utils'
6
7 const buttonVariants = cva(
8 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
9 {
10 variants: {
11 variant: {
12 default: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary-hover',
13 destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
14 outline:
15 'border border-input bg-background hover:bg-accent/40 hover:border-accent-foreground/20',
16 secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
17 'secondary-2':
18 'bg-secondary text-secondary-foreground hover:bg-primary hover:text-primary-foreground',
19 ghost: 'clickable hover:text-accent-foreground',
20 'ghost-destructive':
21 'cursor-pointer hover:bg-destructive/20 text-destructive hover:text-destructive',
22 link: 'text-foreground underline-offset-4 hover:underline'
23 },
24 size: {
25 default: 'h-9 px-4 py-2',
26 sm: 'h-8 rounded-md px-3 text-xs',
27 lg: 'h-10 rounded-lg px-8',
28 icon: 'h-9 w-9 shrink-0',
29 'titlebar-icon': 'h-10 w-10 shrink-0 rounded-xl [&_svg]:size-5'
30 }
31 },
32 defaultVariants: {
33 variant: 'default',
34 size: 'default'
35 }
36 }
37 )
38
39 export interface ButtonProps
40 extends React.ButtonHTMLAttributes<HTMLButtonElement>,
41 VariantProps<typeof buttonVariants> {
42 asChild?: boolean
43 }
44
45 const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
46 ({ className, variant, size, asChild = false, ...props }, ref) => {
47 const Comp = asChild ? Slot : 'button'
48 return (
49 <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
50 )
51 }
52 )
53 Button.displayName = 'Button'
54
55 export { Button, buttonVariants }
56