Skip to content

Commit 5e93cd3

Browse files
committed
Update: Support all icon usage directly in Button
1 parent 08c64aa commit 5e93cd3

File tree

4 files changed

+161
-129
lines changed

4 files changed

+161
-129
lines changed

src/components/Button/Button.stories.tsx

Lines changed: 82 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Meta, StoryObj } from '@storybook/react'
22

33
import { Button } from './Button'
4+
import { Icon } from '../Icon/Icon'
45

56
const meta: Meta<typeof Button> = {
67
component: Button,
@@ -9,78 +10,113 @@ const meta: Meta<typeof Button> = {
910
export default meta
1011
type Story = StoryObj<typeof Button>
1112

12-
export const Primary: Story = {
13-
decorators: [
14-
(Story) => (
15-
<div className='grid grid-cols-4 gap-x-4 gap-y-2 items-center justify-items-center'>
16-
<div>base</div>
17-
<div>hover</div>
18-
<div>active</div>
19-
<div>disabled</div>
20-
<Story />
21-
</div>
22-
),
23-
],
24-
render: () => (
13+
function ButtonRow(control: {
14+
disabled?: boolean
15+
pressed?: boolean
16+
hovered?: boolean
17+
}) {
18+
return (
2519
<>
26-
<Button variant='filled'>Button</Button>
27-
<Button variant='filled' className='C9Y-hover'>
20+
<Button variant='filled' {...control}>
2821
Button
2922
</Button>
30-
<Button variant='filled' className='C9Y-active'>
23+
<Button variant='filled' {...control}>
24+
<Icon id='code' />
3125
Button
3226
</Button>
33-
<Button variant='filled' disabled>
27+
<Button variant='filled' {...control}>
3428
Button
29+
<Icon id='code' />
30+
</Button>
31+
<Button variant='filled' {...control}>
32+
<Icon id='code' />
3533
</Button>
36-
<Button variant='outlined'>Button</Button>
37-
<Button variant='outlined' className='C9Y-hover'>
34+
<Button variant='outlined' {...control}>
3835
Button
3936
</Button>
40-
<Button variant='outlined' className='C9Y-active'>
37+
<Button variant='outlined' {...control}>
38+
<Icon id='code' />
4139
Button
4240
</Button>
43-
<Button variant='outlined' disabled>
41+
<Button variant='outlined' {...control}>
4442
Button
43+
<Icon id='code' />
44+
</Button>
45+
<Button variant='outlined' {...control}>
46+
<Icon id='code' />
4547
</Button>
4648
</>
47-
),
49+
)
4850
}
4951

50-
export const WithIcon: Story = {
52+
export const Primary: Story = {
5153
render: () => (
52-
<div className='flex flex-row items-center gap-4'>
53-
<Button variant='filled' size='small' startIcon='code' endIcon='code'>
54-
Button
55-
</Button>
56-
<Button variant='filled' startIcon='code' endIcon='code'>
57-
Button
58-
</Button>
59-
<Button variant='filled' size='large' startIcon='code' endIcon='code'>
60-
Button
61-
</Button>
54+
<div
55+
className='grid gap-x-4 gap-y-2 items-center justify-items-center'
56+
style={{ gridTemplateColumns: '70px repeat(8, auto)' }}
57+
>
58+
<div>base</div>
59+
<ButtonRow />
60+
61+
<div>hover</div>
62+
<ButtonRow hovered />
63+
64+
<div>pressed</div>
65+
<ButtonRow pressed />
66+
67+
<div>disabled</div>
68+
<ButtonRow disabled />
6269
</div>
6370
),
6471
}
6572

6673
export const Sizes: Story = {
6774
render: () => (
68-
<div className='flex flex-row items-center gap-4'>
75+
<div
76+
className='grid gap-x-4 gap-y-2 items-center justify-items-start'
77+
style={{ gridTemplateColumns: '60px repeat(4, auto)' }}
78+
>
79+
<div>small</div>
6980
<Button size='small'>Button</Button>
81+
<Button size='small'>
82+
<Icon id='code' />
83+
Button
84+
</Button>
85+
<Button size='small'>
86+
Button
87+
<Icon id='code' />
88+
</Button>
89+
<Button size='small'>
90+
<Icon id='code' />
91+
</Button>
92+
93+
<div>default</div>
7094
<Button>Button</Button>
95+
<Button>
96+
<Icon id='code' />
97+
Button
98+
</Button>
99+
<Button>
100+
Button
101+
<Icon id='code' />
102+
</Button>
103+
<Button>
104+
<Icon id='code' />
105+
</Button>
106+
107+
<div>large</div>
71108
<Button size='large'>Button</Button>
109+
<Button size='large'>
110+
<Icon id='code' />
111+
Button
112+
</Button>
113+
<Button size='large'>
114+
Button
115+
<Icon id='code' />
116+
</Button>
117+
<Button size='large'>
118+
<Icon id='code' />
119+
</Button>
72120
</div>
73121
),
74122
}
75-
76-
export const WithAnchor: Story = {
77-
args: {
78-
href: '#test',
79-
children: 'Button',
80-
},
81-
parameters: {
82-
docs: {
83-
description: 'Buttons with an `href` will be rendered as anchors',
84-
},
85-
},
86-
}

src/components/Button/Button.styles.ts

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { Theme } from '../../theme/theme'
77
export const buttonStyles = (theme: Theme): ButtonStyles => ({
88
// BASE
99
'.C9Y-Button-base': {
10+
height: '2rem',
11+
padding: '0 1rem',
1012
alignItems: 'center',
1113
display: 'inline-flex',
1214
justifyContent: 'center',
@@ -21,47 +23,56 @@ export const buttonStyles = (theme: Theme): ButtonStyles => ({
2123
'&:disabled, &.C9Y-disabled': {
2224
cursor: 'not-allowed',
2325
},
26+
27+
// ICONS
28+
'&:has(> svg:last-child)': {
29+
paddingRight: '0.75rem',
30+
},
31+
32+
'&:has(> svg:first-child)': {
33+
paddingLeft: '0.75rem',
34+
},
35+
36+
'&:has(> svg:only-child)': {
37+
width: '2rem',
38+
padding: 0,
39+
},
2440
},
2541

2642
// VARIANTS
2743
'.C9Y-Button-filled': {
28-
height: '2rem',
29-
padding: '0 1rem',
3044
backgroundColor: theme.colors.primary[500],
3145
borderRadius: theme.borderRadius.DEFAULT,
3246
color: theme.colors.inverse,
3347

3448
transition: 'background-color 0.15s linear',
3549

36-
'&:hover, &.C9Y-hover': {
50+
'&:hover, &.C9Y-hovered': {
3751
backgroundColor: theme.colors.primary[700],
3852
},
39-
'&:active, &.C9Y-active': {
53+
'&:active, &.C9Y-pressed': {
4054
backgroundColor: theme.colors.primary[900],
4155
},
4256
'&:disabled, &.C9Y-disabled': {
4357
backgroundColor: theme.colors.primary[300],
4458
},
4559

46-
// For buttons with color options you'll typically define them in each variant
47-
// like:
60+
// For buttons with color options you can define them in each variant, eg:
4861
// '&.C9Y-Button-errorColor': { ... }
4962
},
5063
'.C9Y-Button-outlined': {
51-
height: '2rem',
52-
padding: '0 1rem',
5364
backgroundColor: 'transparent',
5465
border: `1px solid ${theme.colors.primary[500]}`,
5566
borderRadius: theme.borderRadius.DEFAULT,
5667
color: theme.colors.primary[500],
5768

5869
transition: 'color, border-color 0.15s linear',
5970

60-
'&:hover, &.C9Y-hover': {
71+
'&:hover, &.C9Y-hovered': {
6172
borderColor: theme.colors.primary[700],
6273
color: theme.colors.primary[700],
6374
},
64-
'&:active, &.C9Y-active': {
75+
'&:active, &.C9Y-pressed': {
6576
borderColor: theme.colors.primary[900],
6677
color: theme.colors.primary[900],
6778
},
@@ -74,55 +85,79 @@ export const buttonStyles = (theme: Theme): ButtonStyles => ({
7485
// SIZES
7586
'.C9Y-Button-smallSize': {
7687
height: '1.5rem',
88+
gap: '0.375rem',
89+
padding: '0rem 0.5rem',
7790
borderRadius: theme.borderRadius.DEFAULT,
7891
fontSize: '0.75rem',
79-
padding: '0rem 0.5rem',
92+
93+
'&:has(> svg:last-child)': {
94+
paddingRight: '0.5rem',
95+
},
96+
97+
'&:has(> svg:first-child)': {
98+
paddingLeft: '0.5rem',
99+
},
100+
101+
'&:has(> svg:only-child)': {
102+
width: '1.5rem',
103+
padding: 0,
104+
},
80105
},
106+
81107
'.C9Y-Button-largeSize': {
82108
height: '2.5rem',
109+
gap: '0.625rem',
110+
padding: '0 1.5rem',
83111
borderRadius: theme.borderRadius.md,
84112
fontSize: '1rem',
85-
padding: '0 2rem',
86-
},
87113

88-
// ICONS
89-
'.C9Y-Button-icon': {
90-
fontSize: '1rem',
91-
},
92-
'.C9Y-Button-smallSizeIcon': {
93-
fontSize: '0.75rem',
94-
},
95-
'.C9Y-Button-largeSizeIcon': {
96-
fontSize: '1.25rem',
114+
'&:has(> svg:last-child)': {
115+
paddingRight: '1.25rem',
116+
},
117+
118+
'&:has(> svg:first-child)': {
119+
paddingLeft: '1.25rem',
120+
},
121+
122+
'&:has(> svg:only-child)': {
123+
width: '2.5rem',
124+
padding: 0,
125+
},
97126
},
98127
})
99128

100129
export interface ButtonStyles {
101130
/** Base class applied to all variants for shared structural styles */
102-
'.C9Y-Button-base': { '&:disabled, &.C9Y-disabled': CSSProperties } & CSSProperties
131+
'.C9Y-Button-base': {
132+
'&:has(> svg:last-child)': CSSProperties
133+
'&:has(> svg:first-child)': CSSProperties
134+
'&:has(> svg:only-child)': CSSProperties
135+
'&:disabled, &.C9Y-disabled': CSSProperties
136+
} & CSSProperties
103137

104138
/** Variant class applied when `variant="filled"` */
105139
'.C9Y-Button-filled': {
106-
'&:hover, &.C9Y-hover': CSSProperties
107-
'&:active, &.C9Y-active': CSSProperties
140+
'&:hover, &.C9Y-hovered': CSSProperties
141+
'&:active, &.C9Y-pressed': CSSProperties
108142
'&:disabled, &.C9Y-disabled': CSSProperties
109143
} & CSSProperties
110144
/** Variant class applied when `variant="outlined"` */
111145
'.C9Y-Button-outlined': {
112-
'&:hover, &.C9Y-hover': CSSProperties
113-
'&:active, &.C9Y-active': CSSProperties
146+
'&:hover, &.C9Y-hovered': CSSProperties
147+
'&:active, &.C9Y-pressed': CSSProperties
114148
'&:disabled, &.C9Y-disabled': CSSProperties
115149
} & CSSProperties
116150

117151
/** Sizing class applied when `size="small"` */
118-
'.C9Y-Button-smallSize': CSSProperties
152+
'.C9Y-Button-smallSize': {
153+
'&:has(> svg:last-child)': CSSProperties
154+
'&:has(> svg:first-child)': CSSProperties
155+
'&:has(> svg:only-child)': CSSProperties
156+
} & CSSProperties
119157
/** Sizing class applied when `size="large"` */
120-
'.C9Y-Button-largeSize': CSSProperties
121-
122-
/** Base class applied to all Button Icons */
123-
'.C9Y-Button-icon': CSSProperties
124-
/** Sizing class applied to Button Icons when `size="small"` */
125-
'.C9Y-Button-smallSizeIcon': CSSProperties
126-
/** Sizing class applied Button Icons when `size="large"` */
127-
'.C9Y-Button-largeSizeIcon': CSSProperties
158+
'.C9Y-Button-largeSize': {
159+
'&:has(> svg:last-child)': CSSProperties
160+
'&:has(> svg:first-child)': CSSProperties
161+
'&:has(> svg:only-child)': CSSProperties
162+
} & CSSProperties
128163
}

0 commit comments

Comments
 (0)