@@ -6,7 +6,7 @@ import type { ComponentProps } from 'react';
66import { cn } from '@/lib' ;
77
88export interface ButtonProps extends ComponentProps < 'button' > {
9- variant ?: 'primary' | 'secondary ' | 'tertiary ' | 'ghost' | 'danger' ;
9+ variant ?: 'primary' | 'brand ' | 'outline ' | 'ghost' | 'danger' ;
1010 size ?: 'large' | 'medium' | 'small' | 'x-small' ;
1111 shape ?: 'pill' | 'rounded' | 'square' | 'circle' ;
1212 loading ?: boolean ;
@@ -20,18 +20,18 @@ export interface ButtonProps extends ComponentProps<'button'> {
2020 * :root {
2121 * --button-focus: hsl(var(--primary));
2222 * --button-font-family: var(--font-family-body);
23- * --button-primary -background: hsl(var(--primary));
24- * --button-primary -background-hover: color-mix(in oklab, hsl(var(--primary)), white 75%);
25- * --button-primary -text: hsl(var(--foreground));
26- * --button-primary -border: hsl(var(--primary));
27- * --button-secondary -background: hsl(var(--foreground));
28- * --button-secondary -background-hover: hsl(var(--background));
29- * --button-secondary -text: hsl(var(--background));
30- * --button-secondary -border: hsl(var(--foreground));
31- * --button-tertiary -background: hsl(var(--background));
32- * --button-tertiary -background-hover: hsl(var(--contrast-100));
33- * --button-tertiary -text: hsl(var(--foreground));
34- * --button-tertiary -border: hsl(var(--contrast-200));
23+ * --button-brand -background: hsl(var(--primary));
24+ * --button-brand -background-hover: color-mix(in oklab, hsl(var(--primary)), white 75%);
25+ * --button-brand -text: hsl(var(--foreground));
26+ * --button-brand -border: hsl(var(--primary));
27+ * --button-primary -background: hsl(var(--foreground));
28+ * --button-primary -background-hover: hsl(var(--background));
29+ * --button-primary -text: hsl(var(--background));
30+ * --button-primary -border: hsl(var(--foreground));
31+ * --button-outline -background: hsl(var(--background));
32+ * --button-outline -background-hover: hsl(var(--contrast-100));
33+ * --button-outline -text: hsl(var(--foreground));
34+ * --button-outline -border: hsl(var(--contrast-200));
3535 * --button-ghost-background: transparent;
3636 * --button-ghost-background-hover: color-mix(in oklab, hsl(var(--foreground)) 5%, transparent);
3737 * --button-ghost-text: hsl(var(--foreground));
@@ -59,26 +59,31 @@ export function Button({
5959 < button
6060 aria-busy = { loading }
6161 className = { cn (
62- 'after:ease-[cubic-bezier(0,0.25,0,1)] relative z-0 inline-flex h-fit select-none items-center justify-center overflow-hidden border text-center font-semibold leading-normal [font-family:var(--button-font-family,var(--font-family-body))] after:absolute after:inset-0 after:-z-10 after:-translate-x-[105%] after:transition-[opacity,transform] after:duration-300 focus-visible:outline-2 focus-visible:outline-[var(--button-focus,hsl(var(--primary)))] disabled:pointer-events-none disabled:opacity-30' ,
62+ 'relative z-0 inline-flex h-fit select-none items-center justify-center overflow-hidden text-center font-semibold leading-normal duration-200 ease-in-out [font-family:var(--button-font-family,var(--font-family-body))] focus-visible:outline-2 focus-visible:outline-offset -2 focus-visible:outline-[var(--button-focus,hsl(var(--primary)))] disabled:pointer-events-none disabled:opacity-30' ,
6363 {
64+ brand :
65+ 'bg-[var(--button-brand-background,hsl(var(--primary)))] text-[var(--button-brand-text,hsl(var(--foreground)))] hover:opacity-70' ,
6466 primary :
65- 'border-[var(--button-primary-border,hsl(var(--primary)))] bg-[var(--button-primary-background,hsl(var(--primary)))] text-[var(--button-primary-text,hsl(var(--foreground)))] after:bg-[var(--button-primary-background-hover,color-mix(in_oklab,hsl(var(--primary)),white_75%))] focus-visible:outline-offset-2' ,
66- secondary :
67- 'border-[var(--button-secondary-border,hsl(var(--foreground)))] bg-[var(--button-secondary-background,hsl(var(--foreground)))] text-[var(--button-secondary-text,hsl(var(--background)))] after:bg-[var(--button-secondary-background-hover,hsl(var(--background)))] focus-visible:outline-offset-2' ,
68- tertiary :
69- 'border-[var(--button-tertiary-border,hsl(var(--contrast-200)))] bg-[var(--button-tertiary-background,hsl(var(--background)))] text-[var(--button-tertiary-text,hsl(var(--foreground)))] after:bg-[var(--button-tertiary-background-hover,hsl(var(--contrast-100)))] focus-visible:outline-offset-2' ,
67+ 'bg-[var(--button-primary-background,hsl(var(--foreground)))] text-[var(--button-primary-text,hsl(var(--background)))] hover:opacity-70' ,
68+ outline :
69+ 'border border-[var(--button-outline-border,hsl(var(--contrast-200)))] bg-[var(--button-outline-background,hsl(var(--background)))] text-[var(--button-outline-text,hsl(var(--foreground)))] hover:bg-foreground/5' ,
7070 ghost :
71- 'border-[var(--button-ghost-border,transparent)] bg-[var(--button-ghost-background, transparent)] text-[var(--button-ghost-text,hsl(var(--foreground)))] after :bg-[var(--button-ghost-background-hover,color-mix(in_oklab,hsl(var(-- foreground))_5%,transparent))] focus-visible:outline-offset-0 ' ,
71+ 'bg-transparent text-[var(--button-ghost-text,hsl(var(--foreground)))] hover :bg-foreground/5 ' ,
7272 danger :
73- 'border-[var(--button-danger-border,color-mix(in_oklab,hsl(var(--error)),white_30%))] bg-[var(--button-danger-background,color-mix(in_oklab, hsl(var(--error)),white_30%)) ] text-[var(--button-danger-text,hsl(var(--foreground)))] after:bg-[var(--button-danger- background-hover,color-mix(in_oklab,hsl(var(--error)),white_75%))] focus-visible:outline-offset-2 ' ,
73+ 'bg-[var(--button-danger-background,hsl(var(--error))) ] text-[var(--button-danger-text,hsl(var(--background)))] hover:opacity-70 ' ,
7474 } [ variant ] ,
75- {
76- pill : 'rounded-full after:rounded-full' ,
77- rounded : 'rounded-lg after:rounded-lg' ,
78- square : 'rounded-none after:rounded-none' ,
79- circle : 'rounded-full after:rounded-full' ,
80- } [ shape ] ,
81- ! loading && ! disabled && 'hover:after:translate-x-0' ,
75+ shape === 'rounded'
76+ ? {
77+ 'x-small' : 'rounded-lg' ,
78+ small : 'rounded-lg' ,
79+ medium : 'rounded-xl' ,
80+ large : 'rounded-xl' ,
81+ } [ size ]
82+ : {
83+ pill : 'rounded-full' ,
84+ square : 'rounded-none' ,
85+ circle : 'rounded-full' ,
86+ } [ shape ] ,
8287 loading && 'pointer-events-none' ,
8388 className ,
8489 ) }
@@ -90,36 +95,35 @@ export function Button({
9095 < span
9196 className = { cn (
9297 'inline-flex items-center justify-center transition-all duration-300 ease-in-out' ,
93- loading ? '-translate-y-10 opacity-0' : 'translate-y-0 opacity-100' ,
98+ loading ? '-translate-y-full opacity-0' : 'translate-y-0 opacity-100' ,
9499 shape === 'circle' && 'aspect-square' ,
95100 {
96101 'x-small' : 'min-h-8 text-xs' ,
97- small : 'min-h-10 text-sm' ,
98- medium : 'min-h-12 text-base' ,
102+ small : 'min-h-9 text-sm' ,
103+ medium : 'min-h-11 text-base' ,
99104 large : 'min-h-14 text-base' ,
100105 } [ size ] ,
101106 shape !== 'circle' &&
102107 {
103108 'x-small' : 'gap-x-2 px-3 py-1.5' ,
104- small : 'gap-x-2 px-4 py-2.5 ' ,
105- medium : 'gap-x-2.5 px-5 py-3 ' ,
106- large : 'gap-x-3 px-6 py-4' ,
109+ small : 'gap-x-2 px-3.5 py-2' ,
110+ medium : 'gap-x-2.5 px-4 py-2.5 ' ,
111+ large : 'gap-x-3 px-5 py-4' ,
107112 } [ size ] ,
108- variant === 'secondary' && 'mix-blend-difference' ,
109113 ) }
110114 >
111115 { children }
112116 </ span >
113117 < span
114118 className = { cn (
115119 'absolute inset-0 grid place-content-center transition-all duration-300 ease-in-out' ,
116- loading ? 'translate-y-0 opacity-100' : 'translate-y-10 opacity-0' ,
120+ loading ? 'translate-y-0 opacity-100' : 'translate-y-full opacity-0' ,
117121 ) }
118122 >
119123 < Loader2
120124 className = { cn (
121125 'animate-spin' ,
122- variant === 'tertiary ' && 'text-[var(--button-loader-icon,hsl(var(--foreground)))]' ,
126+ variant === 'outline ' && 'text-[var(--button-loader-icon,hsl(var(--foreground)))]' ,
123127 ) }
124128 />
125129 </ span >
0 commit comments