"use client"
import {
Button as ButtonPrimitive,
type ButtonProps as ButtonPrimitiveProps,
} from "react-aria-components"
import { tv, type VariantProps } from "tailwind-variants"
import { cx } from "@/lib/primitive"
export const buttonStyles = tv({
base: [
"[--btn-border:var(--color-fg)]/15 [--btn-icon-active:var(--btn-fg)] [--btn-outline:var(--btn-bg)] [--btn-radius:calc(var(--radius-lg)-1px)] [--btn-ring:var(--btn-bg)]/20",
"bg-(--btn-bg) text-(--btn-fg) outline-(--btn-outline) ring-(--btn-ring) hover:bg-(--btn-overlay)",
"relative isolate inline-flex items-center justify-center border border-(--btn-border) font-medium hover:no-underline",
"focus:outline-0 focus-visible:outline focus-visible:outline-offset-2 focus-visible:ring-2 focus-visible:ring-offset-3 focus-visible:ring-offset-bg",
"*:data-[slot=icon]:-mx-0.5 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:self-center *:data-[slot=icon]:text-(--btn-icon) focus-visible:*:data-[slot=icon]:text-(--btn-icon-active)/80 hover:*:data-[slot=icon]:text-(--btn-icon-active)/90 forced-colors:[--btn-icon:ButtonText] forced-colors:hover:[--btn-icon:ButtonText]",
"*:data-[slot=loader]:-mx-0.5 *:data-[slot=loader]:shrink-0 *:data-[slot=loader]:self-center *:data-[slot=loader]:text-(--btn-icon)",
"pending:opacity-50 disabled:opacity-50 disabled:forced-colors:text-[GrayText]",
"*:data-[slot=color-swatch]:-mx-0.5 *:data-[slot=color-swatch]:shrink-0 *:data-[slot=color-swatch]:self-center *:data-[slot=color-swatch]:[--color-swatch-size:--spacing(5)]",
],
variants: {
intent: {
primary:
"[--btn-bg:var(--color-primary)] [--btn-fg:var(--color-primary-fg)] [--btn-icon-active:var(--primary-fg)]/80 [--btn-icon:var(--primary-fg)]/60 [--btn-overlay:color-mix(in_oklab,var(--color-primary-fg)_10%,var(--color-primary)_90%)]",
secondary:
"[--btn-bg:var(--color-secondary)] [--btn-fg:var(--color-secondary-fg)] [--btn-icon:var(--color-muted-fg)] [--btn-outline:var(--color-secondary-fg)] [--btn-overlay:var(--color-muted-fg)]/25 [--btn-ring:var(--color-muted-fg)]/20",
warning:
"[--btn-bg:var(--color-warning)] [--btn-fg:var(--color-warning-fg)] [--btn-icon:var(--color-warning-fg)]/60 [--btn-overlay:var(--color-warning)]/85",
danger:
"[--btn-bg:var(--color-danger)] [--btn-fg:var(--color-danger-fg)] [--btn-icon:color-mix(in_oklab,var(--color-danger-fg)_60%,var(--danger)_40%)] [--btn-overlay:var(--color-danger)]/85",
outline:
"border-border [--btn-bg:transparent] [--btn-icon:var(--color-muted-fg)] [--btn-outline:var(--color-ring)] [--btn-overlay:var(--color-muted-fg)]/10 [--btn-ring:var(--color-ring)]/20",
plain:
"border-transparent [--btn-bg:transparent] [--btn-icon:var(--color-muted-fg)] [--btn-outline:var(--color-ring)] [--btn-overlay:var(--color-muted-fg)]/10 [--btn-ring:var(--color-ring)]/20",
},
size: {
xs: [
"min-h-8 gap-x-1.5 px-[calc(--spacing(3)-1px)] py-[calc(--spacing(1.5)-1px)] text-sm sm:min-h-7 sm:px-2 sm:py-[calc(--spacing(1.5)-1px)] sm:text-xs/4",
"*:data-[slot=icon]:-mx-px *:data-[slot=icon]:size-3.5 sm:*:data-[slot=icon]:size-3",
"*:data-[slot=loader]:-mx-px *:data-[slot=loader]:size-3.5 sm:*:data-[slot=loader]:size-3",
],
sm: [
"min-h-9 gap-x-1.5 px-3 py-[calc(--spacing(2)-1px)] sm:min-h-8 sm:px-[calc(--spacing(3)-1px)] sm:py-[calc(--spacing(1.5)-1px)] sm:text-sm/5",
"*:data-[slot=icon]:size-4.5 sm:*:data-[slot=icon]:size-4",
"*:data-[slot=loader]:size-4.5 sm:*:data-[slot=loader]:size-4",
],
md: [
"min-h-10 gap-x-2 px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(2.5)-1px)] sm:min-h-9 sm:px-3 sm:py-[calc(--spacing(1.5)-1px)] sm:text-sm/6",
"*:data-[slot=icon]:size-5 sm:*:data-[slot=icon]:size-4",
"*:data-[slot=loader]:size-5 sm:*:data-[slot=loader]:size-4",
],
lg: [
"min-h-10 gap-x-2 px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(3)-1px)] sm:min-h-9 sm:px-3 sm:py-[calc(--spacing(1.5)-1px)] sm:text-sm/7",
"*:data-[slot=icon]:size-5 sm:*:data-[slot=icon]:size-4.5",
"*:data-[slot=loader]:size-5 sm:*:data-[slot=loader]:size-4.5",
],
"sq-xs": [
"touch-target size-8 sm:size-7",
"*:data-[slot=icon]:size-3.5 sm:*:data-[slot=icon]:size-3",
"*:data-[slot=loader]:size-3.5 sm:*:data-[slot=loader]:size-3",
],
"sq-sm": [
"touch-target size-10 sm:size-8",
"*:data-[slot=icon]:size-4.5 sm:*:data-[slot=icon]:size-4",
"*:data-[slot=loader]:size-4.5 sm:*:data-[slot=loader]:size-4",
],
"sq-md": [
"touch-target size-11 sm:size-9",
"*:data-[slot=icon]:size-5 sm:*:data-[slot=icon]:size-4.5",
"*:data-[slot=loader]:size-5 sm:*:data-[slot=loader]:size-4.5",
],
"sq-lg": [
"touch-target size-12 sm:size-10",
"*:data-[slot=icon]:size-6 sm:*:data-[slot=icon]:size-5",
"*:data-[slot=loader]:size-6 sm:*:data-[slot=loader]:size-5",
],
},
isCircle: {
true: "rounded-full",
false: "rounded-lg",
},
},
defaultVariants: {
intent: "primary",
size: "md",
isCircle: false,
},
})
export interface ButtonProps extends ButtonPrimitiveProps, VariantProps<typeof buttonStyles> {
ref?: React.Ref<HTMLButtonElement>
}
export function Button({ className, intent, size, isCircle, ref, ...props }: ButtonProps) {
return (
<ButtonPrimitive
ref={ref}
{...props}
className={cx(
buttonStyles({
intent,
size,
isCircle,
}),
className,
)}
/>
)
}