1import * as React from "react"
2import { cva, type VariantProps } from "class-variance-authority"
3import { Slot } from "radix-ui"
4
5import { cn } from "@/lib/utils"
6
7/* DESIGN-SYSTEM §7: tekan = hover geser -1,-1 px dengan bayangan 5 px,
8 aktif geser 4,4 px tanpa bayangan, transisi 120 ms. */
9const press =
10 "shadow-hard hover:shadow-hard-hover hover:-translate-x-px hover:-translate-y-px active:translate-x-1 active:translate-y-1 active:shadow-none"
11
12const buttonVariants = cva(
13 cn(
14 "group/button inline-flex shrink-0 items-center justify-center gap-2 rounded-pill border-2 border-ink whitespace-nowrap select-none",
15 "font-sans font-bold transition-[transform,box-shadow,background-color] duration-[120ms] outline-none",
16 "focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-violet",
17 "disabled:pointer-events-none disabled:border-dashed disabled:bg-cream disabled:text-muted disabled:shadow-none",
18 "[&_svg]:pointer-events-none [&_svg]:shrink-0"
19 ),
20 {
21 variants: {
22 variant: {
23 primary: cn("bg-primary text-primary-foreground", press),
24 secondary: cn("bg-secondary text-secondary-foreground", press),
25 neutral: cn("bg-paper text-ink", press),
26 ghost: cn("bg-transparent text-ink hover:bg-cream", press),
27 },
28 size: {
29 default: "h-11 gap-2 px-5 text-[15px]",
30 sm: "h-11 gap-2 px-4 text-[15px]",
31 lg: "h-14 gap-2.5 px-7 text-lg",
32 icon: "size-11",
33 "icon-lg": "size-14",
34 },
35 },
36 defaultVariants: {
37 variant: "primary",
38 size: "default",
39 },
40 }
41)
42
43function Button({
44 className,
45 variant = "primary",
46 size = "default",
47 asChild = false,
48 ...props
49}: React.ComponentProps<"button"> &
50 VariantProps<typeof buttonVariants> & {
51 asChild?: boolean
52 }) {
53 const Comp = asChild ? Slot.Root : "button"
54
55 return (
56 <Comp
57 data-slot="button"
58 data-variant={variant}
59 data-size={size}
60 className={cn(buttonVariants({ variant, size, className }))}
61 {...props}
62 />
63 )
64}
65
66export { Button, buttonVariants }
67