Skip to content

Commit 30f9b34

Browse files
authored
Merge pull request #99 from makeswift/andrew/button-styles
Andrew/button styles
2 parents 1da74c3 + 24cca33 commit 30f9b34

File tree

10 files changed

+104
-92
lines changed

10 files changed

+104
-92
lines changed

src/components/banner/storybook/banner.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const BannerWithReset = ({
3737
{children}
3838
</Banner>
3939
<div className="mt-8 flex justify-center">
40-
<Button onClick={handleReset} variant="secondary">
40+
<Button onClick={handleReset} variant="primary">
4141
Reset Banner
4242
</Button>
4343
</div>
@@ -157,7 +157,7 @@ export const InteractiveBanner = () => {
157157
<strong>&quot;WELCOME&quot;</strong>
158158
</Banner>
159159
<div className="mt-8 flex justify-center">
160-
<Button onClick={handleReset} variant="secondary">
160+
<Button onClick={handleReset} variant="primary">
161161
Reset Banner
162162
</Button>
163163
</div>
@@ -196,7 +196,7 @@ export const MultipleBanners = () => {
196196
</Banner>
197197
</div>
198198
<div className="mt-8 flex justify-center">
199-
<Button onClick={handleResetAll} variant="secondary">
199+
<Button onClick={handleResetAll} variant="primary">
200200
Reset All Banners
201201
</Button>
202202
</div>

src/components/button-link/button-link.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { ComponentProps } from 'react';
44
import { cn } from '@/lib';
55

66
export interface ButtonLinkProps extends ComponentProps<'a'> {
7-
variant?: 'primary' | 'secondary' | 'tertiary' | 'ghost';
7+
variant?: 'primary' | 'brand' | 'outline' | 'ghost' | 'danger';
88
size?: 'large' | 'medium' | 'small' | 'x-small';
99
shape?: 'pill' | 'rounded' | 'square' | 'circle';
1010
asChild?: boolean;
@@ -51,45 +51,52 @@ export function ButtonLink({
5151
return (
5252
<Comp
5353
className={cn(
54-
'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 after:duration-300 after:[animation-timing-function:cubic-bezier(0,0.25,0,1)] hover:after:translate-x-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--button-focus,hsl(var(--primary)))] focus-visible:ring-offset-2',
54+
'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',
5555
{
56+
brand:
57+
'bg-[var(--button-brand-background,hsl(var(--primary)))] text-[var(--button-brand-text,hsl(var(--foreground)))] hover:opacity-70',
5658
primary:
57-
'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%))]',
58-
secondary:
59-
'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)))]',
60-
tertiary:
61-
'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)))]',
59+
'bg-[var(--button-primary-background,hsl(var(--foreground)))] text-[var(--button-primary-text,hsl(var(--background)))] hover:opacity-70',
60+
outline:
61+
'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',
6262
ghost:
63-
'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))]',
63+
'bg-transparent text-[var(--button-ghost-text,hsl(var(--foreground)))] hover:bg-foreground/5',
64+
danger:
65+
'bg-[var(--button-danger-background,hsl(var(--error)))] text-[var(--button-danger-text,hsl(var(--background)))] hover:opacity-70',
6466
}[variant],
65-
{
66-
pill: 'rounded-full after:rounded-full',
67-
rounded: 'rounded-lg after:rounded-lg',
68-
square: 'rounded-none after:rounded-none',
69-
circle: 'rounded-full after:rounded-full',
70-
}[shape],
67+
shape === 'rounded'
68+
? {
69+
'x-small': 'rounded-lg',
70+
small: 'rounded-lg',
71+
medium: 'rounded-xl',
72+
large: 'rounded-xl',
73+
}[size]
74+
: {
75+
pill: 'rounded-full',
76+
square: 'rounded-none',
77+
circle: 'rounded-full',
78+
}[shape],
7179
className,
7280
)}
7381
{...props}
7482
>
7583
<span
7684
className={cn(
77-
'inline-flex items-center justify-center',
85+
'inline-flex items-center justify-center transition-all duration-300 ease-in-out',
7886
shape === 'circle' && 'aspect-square',
7987
{
8088
'x-small': 'min-h-8 text-xs',
81-
small: 'min-h-10 text-sm',
82-
medium: 'min-h-12 text-base',
89+
small: 'min-h-9 text-sm',
90+
medium: 'min-h-11 text-base',
8391
large: 'min-h-14 text-base',
8492
}[size],
8593
shape !== 'circle' &&
8694
{
8795
'x-small': 'gap-x-2 px-3 py-1.5',
88-
small: 'gap-x-2 px-4 py-2.5',
89-
medium: 'gap-x-2.5 px-5 py-3',
90-
large: 'gap-x-3 px-6 py-4',
96+
small: 'gap-x-2 px-3.5 py-2',
97+
medium: 'gap-x-2.5 px-4 py-2.5',
98+
large: 'gap-x-3 px-5 py-4',
9199
}[size],
92-
variant === 'secondary' && 'mix-blend-difference',
93100
)}
94101
>
95102
<Slottable>{children}</Slottable>

src/components/button-link/storybook/button-link.stories.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const meta: Meta<typeof ButtonLink> = {
1313
argTypes: {
1414
variant: {
1515
control: 'select',
16-
options: ['primary', 'secondary', 'tertiary', 'ghost'],
16+
options: ['primary', 'brand', 'outline', 'ghost'],
1717
description: 'The visual style variant of the button link',
1818
},
1919
size: {
@@ -41,23 +41,24 @@ export default meta;
4141
type Story = StoryObj<ButtonLinkProps>;
4242

4343
// Variant stories
44+
4445
export const Primary: Story = {
4546
args: {
4647
variant: 'primary',
47-
children: 'Shop Now',
48+
children: 'Learn More',
4849
},
4950
};
5051

51-
export const Secondary: Story = {
52+
export const Brand: Story = {
5253
args: {
53-
variant: 'secondary',
54-
children: 'Learn More',
54+
variant: 'brand',
55+
children: 'Shop Now',
5556
},
5657
};
5758

58-
export const Tertiary: Story = {
59+
export const Outline: Story = {
5960
args: {
60-
variant: 'tertiary',
61+
variant: 'outline',
6162
children: 'View Details',
6263
},
6364
};
@@ -164,7 +165,7 @@ export const CallToAction: Story = {
164165

165166
export const SecondaryAction: Story = {
166167
args: {
167-
variant: 'secondary',
168+
variant: 'primary',
168169
size: 'medium',
169170
children: 'View Collection',
170171
},
@@ -185,7 +186,7 @@ export const ButtonGroup: Story = {
185186
<ButtonLink href="#" variant="primary">
186187
Primary Action
187188
</ButtonLink>
188-
<ButtonLink href="#" variant="secondary">
189+
<ButtonLink href="#" variant="outline">
189190
Secondary Action
190191
</ButtonLink>
191192
<ButtonLink href="#" variant="ghost">
@@ -199,14 +200,14 @@ export const AllVariants: Story = {
199200
render: () => (
200201
<div className="flex flex-col gap-3">
201202
<div className="flex flex-wrap gap-3">
203+
<ButtonLink href="#" variant="brand">
204+
Brand
205+
</ButtonLink>
202206
<ButtonLink href="#" variant="primary">
203207
Primary
204208
</ButtonLink>
205-
<ButtonLink href="#" variant="secondary">
206-
Secondary
207-
</ButtonLink>
208-
<ButtonLink href="#" variant="tertiary">
209-
Tertiary
209+
<ButtonLink href="#" variant="outline">
210+
Outline
210211
</ButtonLink>
211212
<ButtonLink href="#" variant="ghost">
212213
Ghost

src/components/button/button.tsx

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { ComponentProps } from 'react';
66
import { cn } from '@/lib';
77

88
export 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>

src/components/button/storybook/button.stories.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const meta = {
1313
argTypes: {
1414
variant: {
1515
control: 'select',
16-
options: ['primary', 'secondary', 'tertiary', 'ghost', 'danger'],
16+
options: ['primary', 'brand', 'outline', 'ghost', 'danger'],
1717
description: 'The visual style variant of the button',
1818
},
1919
size: {
@@ -51,17 +51,17 @@ export const Primary: Story = {
5151
},
5252
};
5353

54-
export const Secondary: Story = {
54+
export const Brand: Story = {
5555
args: {
56-
variant: 'secondary',
57-
children: 'Secondary Button',
56+
variant: 'brand',
57+
children: 'Brand Button',
5858
},
5959
};
6060

61-
export const Tertiary: Story = {
61+
export const Outline: Story = {
6262
args: {
63-
variant: 'tertiary',
64-
children: 'Tertiary Button',
63+
variant: 'outline',
64+
children: 'Outline Button',
6565
},
6666
};
6767

@@ -162,9 +162,9 @@ export const DangerSmallPill: Story = {
162162
},
163163
};
164164

165-
export const SecondaryMediumRounded: Story = {
165+
export const PrimaryMediumRounded: Story = {
166166
args: {
167-
variant: 'secondary',
167+
variant: 'primary',
168168
size: 'medium',
169169
shape: 'rounded',
170170
children: 'Cancel',

src/components/dropdown-menu/storybook/dropdown-menu.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export const WithCustomTrigger: Story = {
103103
args: {
104104
label: 'Account',
105105
trigger: (
106-
<Button size="medium" variant="secondary">
106+
<Button size="medium" variant="primary">
107107
<User size={18} />
108108
My Account
109109
</Button>
@@ -186,7 +186,7 @@ export const WithGroups: Story = {
186186
args: {
187187
label: 'File Menu',
188188
trigger: (
189-
<Button variant="secondary">
189+
<Button variant="primary">
190190
<FileText size={18} />
191191
File
192192
</Button>
@@ -522,7 +522,7 @@ export const WithScrollArea: Story = {
522522
args: {
523523
label: 'Select Item',
524524
trigger: (
525-
<Button size="medium" variant="secondary">
525+
<Button size="medium" variant="primary">
526526
Choose Option
527527
</Button>
528528
),

src/components/modal/storybook/modal.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export const Default: Story = {
6363
This is a basic modal. It uses a background overlay and prevents body scroll while open.
6464
</p>
6565
<div className="mt-4 flex justify-end gap-2">
66-
<Button onClick={() => setOpen(false)} variant="secondary">
66+
<Button onClick={() => setOpen(false)} variant="primary">
6767
Close
6868
</Button>
6969
<Button onClick={() => setOpen(false)}>Continue</Button>

0 commit comments

Comments
 (0)