import { Button as ButtonPrimitive } from "@base-ui/react/button" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" // Icon-only buttons get a 44 px hit area under a coarse pointer, centred and invisible, so they // stay small on screen but are easy to hit with a thumb or a glove (spec 4.5). const HIT_AREA = "relative pointer-coarse:after:absolute pointer-coarse:after:top-1/2 pointer-coarse:after:left-1/2 pointer-coarse:after:size-11 pointer-coarse:after:-translate-1/2" const buttonVariants = cva( "group/button inline-flex shrink-0 items-center justify-center rounded-xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all select-none motion-full:active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-inset aria-invalid:ring-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", { variants: { variant: { default: "bg-primary text-primary-foreground shadow-[var(--shadow-soft)] hover:shadow-[var(--shadow-elevated)] hover:brightness-105 active:brightness-95", outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground", ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground", destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20", link: "text-primary-ink underline-offset-4 hover:underline", }, size: { // 44 px for a thumb (often with gloves); compact only for a mouse or pen. default: "h-11 pointer-fine:h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", sm: "h-9 pointer-fine:h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5", lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", // 44 px: reliable with gloves or sticky fingers at the apiary. touch: "h-11 gap-2 px-4 text-base [&_svg:not([class*='size-'])]:size-5", icon: `size-8 ${HIT_AREA}`, "icon-xs": `size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3 ${HIT_AREA}`, "icon-sm": `size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg ${HIT_AREA}`, "icon-lg": `size-9 ${HIT_AREA}`, }, }, defaultVariants: { variant: "default", size: "default", }, } ) interface ButtonProps extends ButtonPrimitive.Props, VariantProps { /** * A toolbar toggle (bold, italic, a list view): sets aria-pressed. Not for a choice between * options - that is a ChoiceGroup (spec 10.2). */ pressed?: boolean } function Button({ className, variant = "default", size = "default", pressed, ...props }: ButtonProps) { return ( ) } export { Button, buttonVariants }