@hyphen/hyphen-components 6.12.0 → 6.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,100 @@
1
1
  import React from 'react';
2
+ import { ICON_NAMES } from '@hyphen/hyphen-design-tokens/build/assets/icons';
2
3
  import { Box } from '../Box/Box';
3
- import { Button } from './Button';
4
- import type { Meta } from '@storybook/react-vite';
4
+ import { Button, ButtonSize, ButtonVariant } from './Button';
5
+ import type { Meta, StoryObj } from '@storybook/react-vite';
5
6
  import { allModes } from '../../modes';
7
+ import { BoxShadowSize } from '../../types';
8
+
9
+ const BUTTON_VARIANTS: ButtonVariant[] = [
10
+ 'primary',
11
+ 'secondary',
12
+ 'tertiary',
13
+ 'danger',
14
+ 'link',
15
+ ];
16
+ const BUTTON_SIZES: ButtonSize[] = ['sm', 'md', 'lg'];
17
+ const BUTTON_SHADOWS: BoxShadowSize[] = ['sm', 'md', 'lg', 'xl', '2xl'];
6
18
 
7
19
  const meta: Meta<typeof Button> = {
8
20
  title: 'Components/Button',
9
21
  component: Button,
22
+ argTypes: {
23
+ variant: {
24
+ control: 'select',
25
+ options: BUTTON_VARIANTS,
26
+ description: 'Visual variant of the button',
27
+ },
28
+ size: {
29
+ control: 'select',
30
+ options: BUTTON_SIZES,
31
+ description: 'Size of the button',
32
+ },
33
+ isDisabled: {
34
+ control: 'boolean',
35
+ description: 'Disables the button',
36
+ },
37
+ isLoading: {
38
+ control: 'boolean',
39
+ description: 'Displays a loading spinner and disables the button',
40
+ },
41
+ fullWidth: {
42
+ control: 'boolean',
43
+ description: 'Button takes up the full width of its parent container',
44
+ },
45
+ iconPrefix: {
46
+ control: 'select',
47
+ options: ICON_NAMES,
48
+ description: 'Icon displayed before the button label',
49
+ mapping: {
50
+ none: undefined,
51
+ },
52
+ },
53
+ iconSuffix: {
54
+ control: 'select',
55
+ options: ICON_NAMES,
56
+ description: 'Icon displayed after the button label',
57
+ mapping: {
58
+ none: undefined,
59
+ },
60
+ },
61
+ shadow: {
62
+ control: 'select',
63
+ options: BUTTON_SHADOWS,
64
+ description: 'Size of the drop shadow applied to the button',
65
+ },
66
+ asChild: {
67
+ control: 'boolean',
68
+ description: 'Render as child (e.g., anchor)',
69
+ },
70
+ className: {
71
+ control: 'text',
72
+ description: 'Custom class to apply to the button',
73
+ },
74
+ children: {
75
+ control: 'text',
76
+ description: 'Button content',
77
+ },
78
+ type: {
79
+ control: 'select',
80
+ options: ['button', 'submit', 'reset'],
81
+ description: 'Button type attribute',
82
+ },
83
+ },
84
+ args: {
85
+ variant: 'primary',
86
+ size: 'md',
87
+ isDisabled: false,
88
+ isLoading: false,
89
+ fullWidth: false,
90
+ iconPrefix: undefined,
91
+ iconSuffix: undefined,
92
+ shadow: undefined,
93
+ asChild: false,
94
+ className: '',
95
+ children: 'Button',
96
+ type: 'button',
97
+ },
10
98
  parameters: {
11
99
  chromatic: {
12
100
  modes: {
@@ -19,139 +107,189 @@ const meta: Meta<typeof Button> = {
19
107
 
20
108
  export default meta;
21
109
 
22
- export const Default = () => (
23
- <Button onClick={() => alert('clicked')}>Button</Button>
24
- );
110
+ type Story = StoryObj<typeof Button>;
25
111
 
26
- export const AsChild = () => (
27
- <Button asChild>
28
- <a href="https://ux.hyphen.ai" target="_blank" rel="noreferrer">
29
- I'm an anchor
30
- </a>
31
- </Button>
32
- );
112
+ export const Default: Story = {
113
+ args: {
114
+ children: 'Button',
115
+ onClick: () => alert('clicked'),
116
+ },
117
+ };
33
118
 
34
- export const Variants = () => (
35
- <Box
36
- gap="md"
37
- background="primary"
38
- direction="row"
39
- alignItems="center"
40
- fontSize="sm"
41
- >
42
- <Button variant="primary">Primary</Button>
43
- <Button variant="secondary">Secondary</Button>
44
- <Button variant="tertiary">Tertiary</Button>
45
- <Button variant="danger">Danger</Button>
46
- <Button variant="link">Link</Button>
47
- </Box>
48
- );
119
+ export const AsChild: Story = {
120
+ args: {
121
+ asChild: true,
122
+ children: (
123
+ <a href="https://ux.hyphen.ai" target="_blank" rel="noreferrer">
124
+ I'm an anchor
125
+ </a>
126
+ ),
127
+ },
128
+ };
49
129
 
50
- export const Sizes = () => (
51
- <Box gap="sm" direction="row" alignItems="flex-start">
52
- <Button variant="primary" size="sm">
53
- Label
54
- </Button>
55
- <Button variant="primary" size="md">
56
- Label
57
- </Button>
58
- <Button variant="primary" size="lg">
59
- Label
60
- </Button>
61
- <Button
62
- variant="primary"
63
- size={{
64
- base: 'sm',
65
- tablet: 'md',
66
- desktop: 'lg',
67
- hd: 'lg',
68
- }}
130
+ export const Variants: Story = {
131
+ render: () => (
132
+ <Box
133
+ gap="md"
134
+ background="primary"
135
+ direction="row"
136
+ alignItems="center"
137
+ fontSize="sm"
69
138
  >
70
- Label
71
- </Button>
72
- </Box>
73
- );
139
+ {BUTTON_VARIANTS.map((variant) => (
140
+ <Button key={variant} variant={variant}>
141
+ {variant.charAt(0).toUpperCase() + variant.slice(1)}
142
+ </Button>
143
+ ))}
144
+ </Box>
145
+ ),
146
+ parameters: {
147
+ controls: { disable: true },
148
+ },
149
+ };
74
150
 
75
- export const FullWidth = () => (
76
- <Button variant="primary" fullWidth>
77
- Full Width
78
- </Button>
79
- );
151
+ export const Sizes: Story = {
152
+ render: () => (
153
+ <Box gap="sm" direction="row" alignItems="flex-start">
154
+ <Button variant="primary" size="sm">
155
+ Label
156
+ </Button>
157
+ <Button variant="primary" size="md">
158
+ Label
159
+ </Button>
160
+ <Button variant="primary" size="lg">
161
+ Label
162
+ </Button>
163
+ <Button
164
+ variant="primary"
165
+ size={{
166
+ base: 'sm',
167
+ tablet: 'md',
168
+ desktop: 'lg',
169
+ hd: 'lg',
170
+ }}
171
+ >
172
+ Label
173
+ </Button>
174
+ </Box>
175
+ ),
176
+ parameters: {
177
+ controls: { disable: true },
178
+ },
179
+ };
180
+
181
+ export const FullWidth: Story = {
182
+ args: {
183
+ variant: 'primary',
184
+ fullWidth: true,
185
+ children: 'Full Width',
186
+ },
187
+ };
80
188
 
81
- export const Icons = () => (
82
- <Box direction="row" gap="md" alignItems="flex-start">
83
- <Button variant="primary" iconPrefix="mail">
84
- Email
85
- </Button>
86
- <Button variant="secondary" iconSuffix="chat">
87
- Chat Now
88
- </Button>
89
- </Box>
90
- );
189
+ export const Icons: Story = {
190
+ render: () => (
191
+ <Box direction="row" gap="md" alignItems="flex-start">
192
+ <Button variant="primary" iconPrefix="mail">
193
+ Email
194
+ </Button>
195
+ <Button variant="secondary" iconSuffix="chat">
196
+ Chat Now
197
+ </Button>
198
+ </Box>
199
+ ),
200
+ parameters: {
201
+ controls: { disable: true },
202
+ },
203
+ };
91
204
 
92
- export const IconButton = () => (
93
- <Box gap="lg" direction="row" alignItems="center">
94
- <Button variant="tertiary" iconPrefix="add" aria-label="add" />
95
- <Button variant="tertiary" iconPrefix="dots" aria-label="open menu" />
96
- <Button variant="danger" iconPrefix="trash" aria-label="remove" />
97
- <Button variant="link" iconPrefix="chat" aria-label="chat" />
98
- </Box>
99
- );
205
+ export const IconButton: Story = {
206
+ render: () => (
207
+ <Box gap="lg" direction="row" alignItems="center">
208
+ <Button variant="tertiary" iconPrefix="add" aria-label="add" />
209
+ <Button variant="tertiary" iconPrefix="dots" aria-label="open menu" />
210
+ <Button variant="danger" iconPrefix="trash" aria-label="remove" />
211
+ <Button variant="link" iconPrefix="chat" aria-label="chat" />
212
+ </Box>
213
+ ),
214
+ parameters: {
215
+ controls: { disable: true },
216
+ },
217
+ };
100
218
 
101
- export const Loading = () => (
102
- <Box direction="row" gap="md" fontSize="sm">
103
- <Button isLoading aria-label="primary loading">
104
- Primary Loading
105
- </Button>
106
- <Button variant="secondary" isLoading aria-label="secondary loading">
107
- Secondary Loading
108
- </Button>
109
- <Button variant="tertiary" isLoading aria-label="tertiary loading">
110
- Tertiary Loading
111
- </Button>
112
- <Button variant="link" isLoading aria-label="link loading">
113
- Link Loading
114
- </Button>
115
- </Box>
116
- );
219
+ export const Loading: Story = {
220
+ render: () => (
221
+ <Box direction="row" gap="md" fontSize="sm">
222
+ <Button isLoading aria-label="primary loading">
223
+ Primary Loading
224
+ </Button>
225
+ <Button variant="secondary" isLoading aria-label="secondary loading">
226
+ Secondary Loading
227
+ </Button>
228
+ <Button variant="tertiary" isLoading aria-label="tertiary loading">
229
+ Tertiary Loading
230
+ </Button>
231
+ <Button variant="link" isLoading aria-label="link loading">
232
+ Link Loading
233
+ </Button>
234
+ </Box>
235
+ ),
236
+ parameters: {
237
+ controls: { disable: true },
238
+ },
239
+ };
117
240
 
118
- export const Disabled = () => (
119
- <Box direction="row" gap="md" fontSize="sm">
120
- <Button variant="primary" isDisabled>
121
- Primary Disabled
122
- </Button>
123
- <Button variant="secondary" isDisabled>
124
- Secondary Disabled
125
- </Button>
126
- <Button variant="tertiary" isDisabled>
127
- Tertiary Disabled
128
- </Button>
129
- <Button variant="link" isDisabled>
130
- Link Disabled
131
- </Button>
132
- </Box>
133
- );
241
+ export const Disabled: Story = {
242
+ render: () => (
243
+ <Box direction="row" gap="md" fontSize="sm">
244
+ <Button variant="primary" isDisabled>
245
+ Primary Disabled
246
+ </Button>
247
+ <Button variant="secondary" isDisabled>
248
+ Secondary Disabled
249
+ </Button>
250
+ <Button variant="tertiary" isDisabled>
251
+ Tertiary Disabled
252
+ </Button>
253
+ <Button variant="link" isDisabled>
254
+ Link Disabled
255
+ </Button>
256
+ </Box>
257
+ ),
258
+ parameters: {
259
+ controls: { disable: true },
260
+ },
261
+ };
134
262
 
135
- export const Shadow = () => (
136
- <Box direction="row" gap="md">
137
- <Button variant="secondary" shadow="xs">
138
- xs shadow
139
- </Button>
140
- <Button variant="secondary" shadow="sm">
141
- sm shadow
142
- </Button>
143
- <Button variant="secondary" shadow="md">
144
- md shadow
145
- </Button>
146
- </Box>
147
- );
263
+ export const Shadow: Story = {
264
+ render: () => (
265
+ <Box direction="row" gap="md">
266
+ <Button variant="secondary" shadow="sm">
267
+ sm shadow
268
+ </Button>
269
+ <Button variant="secondary" shadow="md">
270
+ md shadow
271
+ </Button>
272
+ <Button variant="secondary" shadow="lg">
273
+ lg shadow
274
+ </Button>
275
+ </Box>
276
+ ),
277
+ parameters: {
278
+ controls: { disable: true },
279
+ },
280
+ };
148
281
 
149
- export const InlineLink = () => (
150
- <Box display="block" as="p" fontSize="sm" color="base" width="8xl">
151
- This is an example of a button used as an inline link.{' '}
152
- <Button variant="link" size="md">
153
- Inline Link Button
154
- </Button>
155
- . It will wrap with text.
156
- </Box>
157
- );
282
+ export const InlineLink: Story = {
283
+ render: () => (
284
+ <Box display="block" as="p" fontSize="sm" color="base" width="8xl">
285
+ This is an example of a button used as an inline link.{' '}
286
+ <Button variant="link" size="md">
287
+ Inline Link Button
288
+ </Button>
289
+ . It will wrap with text.
290
+ </Box>
291
+ ),
292
+ parameters: {
293
+ controls: { disable: true },
294
+ },
295
+ };