@@ -5,74 +5,92 @@ import {
55 type ButtonProps as ButtonPrimitiveProps ,
66 composeRenderProps ,
77} from "react-aria-components"
8- import { tv } from "tailwind-variants"
8+ import { type VariantProps , tv } from "tailwind-variants"
99
1010const buttonStyles = tv ( {
1111 base : [
12- "relative isolate inline-flex items-center justify-center gap-x-2 font-medium " ,
13- "outline-0 outline-offset-2 hover:no-underline focus-visible:outline-2 " ,
14- "inset-ring inset-ring-fg/20 bg-(--btn-bg) pressed:bg-(--btn-overlay) text-(--btn-fg) shadow-[shadow:inset_0_2px_--theme(--color-white/15%)] hover:bg-(--btn-overlay) dark:inset-ring-fg/15 dark:shadow-none " ,
15- "forced-colors :outline-[Highlight] forced-colors:[--btn-icon:ButtonText] forced-colors:hover:[--btn-icon:ButtonText] " ,
16- "*:data-[slot=icon]:-mx-0.5 *:data-[slot=icon]:my-1 *:data-[slot=icon]:size-4 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:text-current/60 pressed:*:data-[slot=icon]:text-current *:data-[slot=icon]:transition hover:*:data-[slot=icon]:text-current /90" ,
17- "*:data-[slot=avatar ]:-mx-0.5 *:data-[slot=avatar ]:my-1 *:data-[slot=avatar]:*:size-4 *:data-[slot=avatar]:size-4 *:data-[slot=avatar]:shrink-0 " ,
12+ "[--btn-icon-active:var(--btn-fg)] [--btn-outline:var(--btn-bg)] [--btn-ring:var(--btn-bg)]/20 " ,
13+ "bg-(--btn-bg) pressed:bg-(--btn-overlay) text-(--btn-fg) outline-(--btn-outline) ring-(--btn-ring) hover:bg-(--btn-overlay) " ,
14+ "relative inset-ring inset-ring-fg/15 isolate inline-flex items-center justify-center font-medium " ,
15+ "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 " ,
16+ "*:data-[slot=icon]:-mx-0.5 *:data-[slot=icon]:my-0.5 *:data-[slot=icon]:shrink-0 *:data-[slot=icon]:self-center *:data-[slot=icon]:text-(--btn-icon) pressed:*:data-[slot=icon]:text-(--btn-icon-active) focus-visible: *:data-[slot=icon]:text-(--btn-icon-active)/80 hover:*:data-[slot=icon]:text-(--btn-icon-active) /90 sm:*:data-[slot=icon]:my-1 forced-colors:[--btn-icon:ButtonText] forced-colors:hover:[--btn-icon:ButtonText] " ,
17+ "*:data-[slot=loader ]:-mx-0.5 *:data-[slot=loader ]:my-0.5 *:data-[slot=loader]:shrink-0 *:data-[slot=loader]:self-center *:data-[slot=loader]:text-(--btn-icon) sm: *:data-[slot=loader]:my-1 " ,
1818 ] ,
1919 variants : {
2020 intent : {
21- primary : [
22- "outline-primary [--btn-bg:var(--color-primary)]/95 [--btn-fg:var(--color-primary-fg)] [--btn-overlay:var(--color-primary)]" ,
23- ] ,
24- secondary : [
25- "outline-primary [--btn-bg:var(--color-secondary)]/90 [--btn-fg:var(--color-secondary-fg)] [--btn-overlay:var(--color-secondary)]" ,
26- ] ,
27- warning : [
28- "outline-warning [--btn-bg:var(--color-warning)]/95 [--btn-fg:var(--color-warning-fg)] [--btn-overlay:var(--color-warning)]" ,
21+ primary :
22+ "[--btn-bg:var(--color-primary)] [--btn-fg:var(--color-primary-fg)] [--btn-icon:color-mix(in_oklab,var(--primary-fg)_60%,var(--primary))] [--btn-overlay:var(--color-primary)]/85" ,
23+ secondary :
24+ "[--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-secondary)]/85 [--btn-ring:var(--color-muted-fg)]/20" ,
25+ warning :
26+ "[--btn-bg:var(--color-warning)] [--btn-fg:var(--color-warning-fg)] [--btn-icon:color-mix(in_oklab,var(--warning-fg)_60%,var(--warning))] [--btn-overlay:var(--color-warning)]/85" ,
27+ danger :
28+ "[--btn-bg:var(--color-danger)] [--btn-fg:var(--color-danger-fg)] [--btn-icon:color-mix(in_oklab,var(--danger-fg)_60%,var(--danger))] [--btn-overlay:var(--color-danger)]/85" ,
29+ outline :
30+ "inset-ring-border [--btn-bg:transparent] [--btn-icon:var(--color-muted-fg)] [--btn-outline:var(--color-ring)] [--btn-overlay:var(--color-muted)] [--btn-ring:var(--color-ring)]/20" ,
31+ plain :
32+ "inset-ring-transparent [--btn-bg:transparent] [--btn-icon:var(--color-muted-fg)] [--btn-outline:var(--color-ring)] [--btn-overlay:var(--color-muted)] [--btn-ring:var(--color-ring)]/20" ,
33+ } ,
34+ size : {
35+ xs : [
36+ "gap-x-1 px-2.5 py-1.5 text-sm sm:px-2 sm:py-1 sm:text-xs/4" ,
37+ "*:data-[slot=icon]:size-3.5 sm:*:data-[slot=icon]:size-3" ,
38+ "*:data-[slot=loader]:size-3.5 sm:*:data-[slot=loader]:size-3" ,
2939 ] ,
30- danger : [
31- "outline-danger [--btn-bg:var(--color-danger)]/95 [--btn-fg:var(--color-danger-fg)] [--btn-overlay:var(--color-danger)]" ,
40+ sm : [
41+ "gap-x-1.5 px-3 py-2 sm:px-2.5 sm:py-1.5 sm:text-sm/5" ,
42+ "*:data-[slot=icon]:size-4.5 sm:*:data-[slot=icon]:size-4" ,
43+ "*:data-[slot=loader]:size-4.5 sm:*:data-[slot=loader]:size-4" ,
3244 ] ,
33- outline : [
34- "shadow-none outline-primary [--btn-fg:var(--color-fg)] [--btn-overlay:var(--color-secondary)]/90" ,
45+ md : [
46+ "gap-x-2 px-3.5 py-2 sm:px-3 sm:py-1.5 sm:text-sm/6" ,
47+ "*:data-[slot=icon]:size-5 sm:*:data-[slot=icon]:size-4" ,
48+ "*:data-[slot=loader]:size-5 sm:*:data-[slot=loader]:size-4" ,
3549 ] ,
36- plain : [
37- "inset-ring-transparent shadow-none outline-primary [--btn-fg:var(--color-fg)] [--btn-overlay:var(--color-secondary)]/90 dark:inset-ring-transparent" ,
50+ lg : [
51+ "gap-x-2 px-4 py-2.5 sm:px-3.5 sm:py-2 sm:text-sm/6" ,
52+ "*:data-[slot=icon]:size-5 sm:*:data-[slot=icon]:size-4.5" ,
53+ "*:data-[slot=loader]:size-5 sm:*:data-[slot=loader]:size-4.5" ,
3854 ] ,
55+ "sq-xs" :
56+ "size-8 *:data-[slot=icon]:size-3.5 *:data-[slot=loader]:size-3.5 sm:size-7 sm:*:data-[slot=icon]:size-3 sm:*:data-[slot=loader]:size-3" ,
57+ "sq-sm" :
58+ "size-9 *:data-[slot=icon]:size-4.5 *:data-[slot=loader]:size-4.5 sm:size-8 sm:*:data-[slot=icon]:size-4 sm:*:data-[slot=loader]:size-4" ,
59+ "sq-md" :
60+ "size-10 *:data-[slot=icon]:size-5 *:data-[slot=loader]:size-5 sm:size-9 sm:*:data-[slot=icon]:size-4 sm:*:data-[slot=loader]:size-4" ,
61+ "sq-lg" :
62+ "size-11 *:data-[slot=icon]:size-5 *:data-[slot=loader]:size-5 sm:size-10 sm:*:data-[slot=icon]:size-4.5 sm:*:data-[slot=loader]:size-4.5" ,
3963 } ,
40- size : {
41- "extra-small" :
42- "h-8 px-[calc(var(--spacing)*2.7)] text-xs/4 **:data-[slot=avatar]:*:size-3.5 **:data-[slot=avatar]:size-3.5 **:data-[slot=icon]:size-3 lg:text-[0.800rem]/4" ,
43- small : "h-9 px-3.5 text-sm/5 sm:text-sm/5" ,
44- medium : "h-10 px-4 text-base sm:text-sm/6" ,
45- large :
46- "h-11 px-4.5 text-base *:data-[slot=icon]:mx-[-1.5px] sm:*:data-[slot=icon]:size-5 lg:text-base/7" ,
47- "square-petite" : "size-9 shrink-0" ,
48- } ,
49- shape : {
50- square : "rounded-lg" ,
51- circle : "rounded-full" ,
64+
65+ isCircle : {
66+ true : "rounded-full" ,
67+ false : "rounded-lg" ,
5268 } ,
5369 isDisabled : {
54- false : "cursor-pointer" ,
55- true : "inset-ring-0 cursor-default opacity-50 forced-colors:text-[GrayText]" ,
70+ true : "inset-ring-0 opacity-50 forced-colors:text-[GrayText]" ,
5671 } ,
5772 isPending : {
58- true : "cursor-default opacity-50" ,
73+ true : "opacity-50" ,
5974 } ,
6075 } ,
6176 defaultVariants : {
6277 intent : "primary" ,
63- size : "medium " ,
64- shape : "square" ,
78+ size : "md " ,
79+ isCircle : false ,
6580 } ,
81+ compoundVariants : [
82+ {
83+ size : [ "xs" , "sq-xs" ] ,
84+ className : "rounded-sm *:data-[slot=icon]:size-3" ,
85+ } ,
86+ ] ,
6687} )
6788
68- interface ButtonProps extends ButtonPrimitiveProps {
69- intent ?: "primary" | "secondary" | "danger" | "warning" | "outline" | "plain"
70- size ?: "medium" | "large" | "square-petite" | "extra-small" | "small"
71- shape ?: "square" | "circle"
89+ interface ButtonProps extends ButtonPrimitiveProps , VariantProps < typeof buttonStyles > {
7290 ref ?: React . Ref < HTMLButtonElement >
7391}
7492
75- const Button = ( { className, intent, size, shape , ref, ...props } : ButtonProps ) => {
93+ const Button = ( { className, intent, size, isCircle , ref, ...props } : ButtonProps ) => {
7694 return (
7795 < ButtonPrimitive
7896 ref = { ref }
@@ -82,7 +100,7 @@ const Button = ({ className, intent, size, shape, ref, ...props }: ButtonProps)
82100 ...renderProps ,
83101 intent,
84102 size,
85- shape ,
103+ isCircle ,
86104 className,
87105 } ) ,
88106 ) }
0 commit comments