@transferwise/components 46.87.2 → 46.88.1

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.
Files changed (122) hide show
  1. package/build/avatarLayout/AvatarLayout.js +9 -2
  2. package/build/avatarLayout/AvatarLayout.js.map +1 -1
  3. package/build/avatarLayout/AvatarLayout.mjs +9 -2
  4. package/build/avatarLayout/AvatarLayout.mjs.map +1 -1
  5. package/build/button/Button.js +92 -79
  6. package/build/button/Button.js.map +1 -1
  7. package/build/button/Button.mjs +93 -80
  8. package/build/button/Button.mjs.map +1 -1
  9. package/build/button/Button.resolver.js +74 -0
  10. package/build/button/Button.resolver.js.map +1 -0
  11. package/build/button/Button.resolver.mjs +72 -0
  12. package/build/button/Button.resolver.mjs.map +1 -0
  13. package/build/button/LegacyButton.js +114 -0
  14. package/build/button/LegacyButton.js.map +1 -0
  15. package/build/button/LegacyButton.mjs +112 -0
  16. package/build/button/LegacyButton.mjs.map +1 -0
  17. package/build/circularButton/CircularButton.js.map +1 -1
  18. package/build/circularButton/CircularButton.mjs.map +1 -1
  19. package/build/criticalBanner/CriticalCommsBanner.js +2 -2
  20. package/build/criticalBanner/CriticalCommsBanner.js.map +1 -1
  21. package/build/criticalBanner/CriticalCommsBanner.mjs +1 -1
  22. package/build/header/Header.js +2 -2
  23. package/build/header/Header.js.map +1 -1
  24. package/build/header/Header.mjs +1 -1
  25. package/build/index.js +2 -2
  26. package/build/index.mjs +1 -1
  27. package/build/link/Link.js +8 -3
  28. package/build/link/Link.js.map +1 -1
  29. package/build/link/Link.mjs +8 -3
  30. package/build/link/Link.mjs.map +1 -1
  31. package/build/main.css +247 -0
  32. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.js +2 -4
  33. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.js.map +1 -1
  34. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.mjs +2 -4
  35. package/build/primitives/PrimitiveAnchor/src/PrimitiveAnchor.mjs.map +1 -1
  36. package/build/primitives/PrimitiveButton/src/PrimitiveButton.js +3 -5
  37. package/build/primitives/PrimitiveButton/src/PrimitiveButton.js.map +1 -1
  38. package/build/primitives/PrimitiveButton/src/PrimitiveButton.mjs +3 -5
  39. package/build/primitives/PrimitiveButton/src/PrimitiveButton.mjs.map +1 -1
  40. package/build/select/Select.js +2 -2
  41. package/build/select/Select.js.map +1 -1
  42. package/build/select/Select.mjs +1 -1
  43. package/build/styles/avatarLayout/AvatarLayout.css +11 -0
  44. package/build/styles/button/Button.css +228 -15
  45. package/build/styles/button/Button.vars.css +46 -0
  46. package/build/styles/button/LegacyButton.css +23 -0
  47. package/build/styles/main.css +247 -0
  48. package/build/types/avatarLayout/AvatarLayout.d.ts.map +1 -1
  49. package/build/types/button/Button.d.ts +4 -23
  50. package/build/types/button/Button.d.ts.map +1 -1
  51. package/build/types/button/Button.resolver.d.ts +11 -0
  52. package/build/types/button/Button.resolver.d.ts.map +1 -0
  53. package/build/types/button/Button.types.d.ts +70 -0
  54. package/build/types/button/Button.types.d.ts.map +1 -0
  55. package/build/types/button/LegacyButton.d.ts +44 -0
  56. package/build/types/button/LegacyButton.d.ts.map +1 -0
  57. package/build/types/button/index.d.ts +3 -2
  58. package/build/types/button/index.d.ts.map +1 -1
  59. package/build/types/circularButton/CircularButton.d.ts.map +1 -1
  60. package/build/types/index.d.ts +1 -1
  61. package/build/types/index.d.ts.map +1 -1
  62. package/build/types/link/Link.d.ts +2 -2
  63. package/build/types/link/Link.d.ts.map +1 -1
  64. package/build/types/primitives/PrimitiveAnchor/src/PrimitiveAnchor.d.ts.map +1 -1
  65. package/build/types/primitives/PrimitiveAnchor/src/PrimitiveAnchor.types.d.ts +6 -2
  66. package/build/types/primitives/PrimitiveAnchor/src/PrimitiveAnchor.types.d.ts.map +1 -1
  67. package/build/types/primitives/PrimitiveButton/src/PrimitiveButton.d.ts.map +1 -1
  68. package/build/types/test-utils/story-config.d.ts +1 -1
  69. package/build/types/test-utils/story-config.d.ts.map +1 -1
  70. package/build/upload/steps/completeStep/completeStep.js +2 -2
  71. package/build/upload/steps/completeStep/completeStep.js.map +1 -1
  72. package/build/upload/steps/completeStep/completeStep.mjs +1 -1
  73. package/build/upload/steps/processingStep/processingStep.js +2 -2
  74. package/build/upload/steps/processingStep/processingStep.js.map +1 -1
  75. package/build/upload/steps/processingStep/processingStep.mjs +1 -1
  76. package/build/uploadInput/UploadInput.js +3 -3
  77. package/build/uploadInput/UploadInput.js.map +1 -1
  78. package/build/uploadInput/UploadInput.mjs +1 -1
  79. package/package.json +3 -3
  80. package/src/alert/Alert.tests.story.tsx +1 -1
  81. package/src/avatar/Avatar.story.tsx +1 -1
  82. package/src/avatarLayout/AvatarLayout.css +11 -0
  83. package/src/avatarLayout/AvatarLayout.less +18 -1
  84. package/src/avatarLayout/AvatarLayout.tsx +10 -2
  85. package/src/avatarWrapper/AvatarWrapper.story.tsx +1 -1
  86. package/src/badge/Badge.story.tsx +1 -1
  87. package/src/button/Button.accessibility.docs.mdx +103 -0
  88. package/src/button/Button.css +228 -15
  89. package/src/button/Button.less +242 -14
  90. package/src/button/Button.resolver.tsx +73 -0
  91. package/src/button/Button.spec.tsx +329 -213
  92. package/src/button/Button.story.tsx +782 -134
  93. package/src/button/Button.tests.story.tsx +27 -0
  94. package/src/button/Button.tsx +109 -132
  95. package/src/button/Button.types.ts +92 -0
  96. package/src/button/Button.vars.css +46 -0
  97. package/src/button/Button.vars.less +59 -0
  98. package/src/button/LegacyButton.css +23 -0
  99. package/src/button/LegacyButton.less +24 -0
  100. package/src/button/LegacyButton.spec.tsx +147 -0
  101. package/src/button/LegacyButton.story.tsx +228 -0
  102. package/src/button/LegacyButton.tsx +177 -0
  103. package/src/button/index.ts +6 -2
  104. package/src/card/Card.story.tsx +6 -1
  105. package/src/circularButton/CircularButton.tsx +1 -0
  106. package/src/field/Field.story.tsx +1 -1
  107. package/src/flowNavigation/__snapshots__/FlowNavigation.spec.js.snap +1 -2
  108. package/src/index.ts +1 -1
  109. package/src/inputs/SelectInput.story.tsx +1 -1
  110. package/src/label/Label.story.tsx +1 -1
  111. package/src/link/Link.tsx +15 -6
  112. package/src/main.css +247 -0
  113. package/src/main.less +1 -0
  114. package/src/primitives/PrimitiveAnchor/src/PrimitiveAnchor.tsx +2 -8
  115. package/src/primitives/PrimitiveAnchor/src/PrimitiveAnchor.types.ts +7 -2
  116. package/src/primitives/PrimitiveAnchor/test/PrimitiveAnchor.spec.tsx +1 -3
  117. package/src/primitives/PrimitiveButton/src/PrimitiveButton.tsx +4 -12
  118. package/src/primitives/PrimitiveButton/test/PrimitiveButton.spec.tsx +16 -13
  119. package/src/select/Select.story.tsx +4 -1
  120. package/src/test-utils/Parameters.d.ts +9 -1
  121. package/src/test-utils/story-config.ts +10 -1
  122. package/src/button/__snapshots__/Button.spec.tsx.snap +0 -309
@@ -1,163 +1,811 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
- import { userEvent, within, fn } from '@storybook/test';
3
-
4
- import { ControlType, Priority } from '../common';
2
+ import { fn } from '@storybook/test';
3
+ import { Freeze, ArrowRight, ChevronRight } from '@transferwise/icons';
4
+ import { Flag } from '@wise/art';
5
+ import Button from './Button.resolver';
6
+ import type { ButtonProps, ButtonPriority } from './Button.types';
5
7
  import { storyConfig } from '../test-utils';
6
8
 
7
- import Button from './Button';
9
+ const withContainer = (Story: any) => (
10
+ <div style={{ display: 'flex', justifyContent: 'center' }}>
11
+ <Story />
12
+ </div>
13
+ );
8
14
 
9
- export default {
15
+ /**
16
+ * Used for showing multiple components within a Canvas.
17
+ * @decorator
18
+ */
19
+ const withComponentGrid =
20
+ (maxWidth = 'auto') =>
21
+ (Story: any) => (
22
+ <div
23
+ style={{
24
+ width: '100%',
25
+ placeItems: 'center',
26
+ justifyContent: 'center',
27
+ display: 'flex',
28
+ flexWrap: 'wrap',
29
+ gap: '2rem',
30
+ maxWidth,
31
+ }}
32
+ >
33
+ <Story />
34
+ </div>
35
+ );
36
+
37
+ /**
38
+ * Not all stories need access to all controls as it causes unnecessary UI noise.
39
+ */
40
+ const hideControls = (args: string[]) => {
41
+ const hidden = [
42
+ 'addonStart',
43
+ 'addonEnd',
44
+ 'onClick',
45
+ 'onBlur',
46
+ 'onFocus',
47
+ 'onKeyDown',
48
+ 'onMouseEnter',
49
+ 'onMouseLeave',
50
+ ...args,
51
+ ];
52
+
53
+ return Object.fromEntries(hidden.map((item) => [item, { table: { disable: true } }]));
54
+ };
55
+
56
+ /**
57
+ * Convenience controls for previewing rich markup,
58
+ * not otherwise possible via Storybook
59
+ */
60
+ type PreviewStoryArgs = Parameters<typeof Button>[0] & {
61
+ previewAddonStart: boolean | ButtonProps['addonStart'];
62
+ previewAddonEnd: boolean | ButtonProps['addonEnd'];
63
+ };
64
+ const previewArgTypes = {
65
+ previewAddonStart: {
66
+ control: 'select',
67
+ options: [
68
+ 'undefined',
69
+ 'icon',
70
+ 'avatar: flag',
71
+ 'avatar: initials',
72
+ 'avatar: icon',
73
+ 'avatar: image',
74
+ 'avatar: double',
75
+ ],
76
+ name: 'Preview with `addonStart`',
77
+ mapping: {
78
+ undefined,
79
+ icon: {
80
+ type: 'icon',
81
+ value: <Freeze />,
82
+ },
83
+ 'avatar: flag': {
84
+ type: 'avatar',
85
+ value: [{ asset: <Flag code="pl" /> }],
86
+ },
87
+ 'avatar: initials': {
88
+ type: 'avatar',
89
+ value: [{ profileName: 'Jay Jay' }],
90
+ },
91
+ 'avatar: icon': {
92
+ type: 'avatar',
93
+ value: [{ asset: <Freeze /> }],
94
+ },
95
+ 'avatar: image': {
96
+ type: 'avatar',
97
+ value: [{ imgSrc: '../avatar-square-dude.webp' }],
98
+ },
99
+ 'avatar: double': {
100
+ type: 'avatar',
101
+ value: [{ asset: <Flag code="gb" /> }, { imgSrc: '../avatar-square-dude.webp' }],
102
+ },
103
+ },
104
+ table: {
105
+ category: 'Preview options',
106
+ type: {
107
+ summary: undefined,
108
+ },
109
+ },
110
+ description:
111
+ '**NB:** The `lg` button does not support any addons. `md` button accepts either icons or avatars, while `sm` is restricted to icons only.',
112
+ },
113
+ previewAddonEnd: {
114
+ control: 'boolean',
115
+ name: 'Preview with `addonEnd`',
116
+ mapping: {
117
+ true: { type: 'icon', value: <ArrowRight /> },
118
+ },
119
+ description:
120
+ '**NB:** The `lg` button does not support any addons. `md` and `sm` allow for the use of icons only.',
121
+ table: {
122
+ category: 'Preview options',
123
+ type: {
124
+ summary: undefined,
125
+ },
126
+ },
127
+ },
128
+ } as const;
129
+
130
+ const getPropsForPreview = (args: PreviewStoryArgs) => {
131
+ const { previewAddonStart, previewAddonEnd, ...props } = args as {
132
+ previewAddonStart: ButtonProps['addonStart'];
133
+ previewAddonEnd: ButtonProps['addonEnd'];
134
+ props: typeof Button;
135
+ };
136
+
137
+ return [
138
+ props,
139
+ {
140
+ addonStart: previewAddonStart,
141
+ addonEnd: previewAddonEnd,
142
+ },
143
+ ];
144
+ };
145
+
146
+ /**
147
+ * The stories below document the new Button API, which requires `v2` prop to function. <br />For more details please refer to the [release notes](https://transferwise.atlassian.net/wiki/spaces/DS/pages/3542158737/Button+Updates+New+sizes+Loader+and+Cue) and the [design spec](https://wise.design/components/button). <br />
148
+ * You can still find the old Button documentation under [Legacy Button](?path=/docs/actions-button-legacy--docs)
149
+ *
150
+ *
151
+ */
152
+ const meta: Meta<typeof Button> = {
10
153
  component: Button,
11
154
  title: 'Actions/Button',
12
- args: {
13
- children: 'Button text',
14
- loading: false,
15
- onClick: fn(),
16
- onBlur: fn(),
17
- onFocus: fn(),
18
- },
19
155
  argTypes: {
20
- as: {
156
+ v2: {
157
+ table: {
158
+ readonly: true,
159
+ },
160
+ description: 'If set, toggles the new Button API',
161
+ },
162
+ size: {
163
+ type: {
164
+ name: 'enum',
165
+ value: ['lg', 'md', 'sm'],
166
+ },
167
+ table: {
168
+ type: {
169
+ summary: 'ButtonSize',
170
+ },
171
+ },
172
+ },
173
+ priority: {
21
174
  type: {
22
175
  name: 'enum',
23
- value: ['button', 'a'],
176
+ value: ['primary', 'secondary', 'secondary-neutral', 'tertiary'],
177
+ },
178
+ table: {
179
+ type: {
180
+ summary: 'ButtonPriority',
181
+ },
182
+ defaultValue: { summary: '"primary"' },
183
+ },
184
+ },
185
+ sentiment: {
186
+ type: {
187
+ name: 'enum',
188
+ value: ['default', 'negative'],
189
+ },
190
+ table: {
191
+ type: {
192
+ summary: 'ButtonSentiment',
193
+ },
194
+ },
195
+ },
196
+ disabled: {
197
+ description: 'Toggles the disabled state',
198
+ table: {
199
+ defaultValue: { summary: 'false' },
200
+ },
201
+ },
202
+ loading: {
203
+ description: 'Toggles the loading state',
204
+ table: {
205
+ defaultValue: { summary: 'false' },
206
+ },
207
+ },
208
+ block: {
209
+ table: {
210
+ defaultValue: { summary: 'false' },
211
+ },
212
+ },
213
+ href: {
214
+ type: {
215
+ name: 'string',
216
+ },
217
+ description: 'If set, the component will render as an HTML anchor.',
218
+ },
219
+ target: {
220
+ type: {
221
+ name: 'string',
222
+ },
223
+ table: {
224
+ type: {
225
+ summary: 'string',
226
+ },
227
+ },
228
+ },
229
+ addonStart: {
230
+ control: 'object',
231
+ },
232
+ addonEnd: {
233
+ control: 'object',
234
+ },
235
+ type: {
236
+ control: 'text',
237
+ table: {
238
+ type: {
239
+ summary: 'string',
240
+ },
241
+ },
242
+ description: "Native HTML button's `type` attribute",
243
+ },
244
+ htmlType: {
245
+ table: {
246
+ disable: true,
24
247
  },
25
248
  },
26
249
  },
250
+ args: {
251
+ v2: true,
252
+ size: undefined,
253
+ priority: undefined,
254
+ sentiment: undefined,
255
+ disabled: false,
256
+ loading: false,
257
+ block: false,
258
+ href: undefined,
259
+ target: undefined,
260
+ as: undefined,
261
+ type: undefined,
262
+ addonStart: undefined,
263
+ addonEnd: undefined,
264
+ className: undefined,
265
+ children: 'Button text',
266
+ onClick: fn(),
267
+ },
27
268
  tags: ['autodocs'],
28
- } satisfies Meta<typeof Button>;
269
+ decorators: [withContainer],
270
+ parameters: {
271
+ docs: {
272
+ toc: true,
273
+ },
274
+ },
275
+ };
276
+
277
+ export default meta;
29
278
 
30
279
  type Story = StoryObj<typeof Button>;
31
280
 
32
- export const Basic: Story = {};
281
+ export const Playground: StoryObj<PreviewStoryArgs> = {
282
+ render: function Render(args: PreviewStoryArgs) {
283
+ const [props, previewProps] = getPropsForPreview(args);
33
284
 
34
- export const Focused = storyConfig<Story>(
35
- {
36
- parameters: {
37
- chromatic: {
38
- delay: 1000,
39
- },
40
- },
41
- play: async ({ canvasElement }) => {
42
- const canvas = within(canvasElement);
43
- await userEvent.click(canvas.getByRole('button'));
44
- },
285
+ return <Button {...props} {...previewProps} v2 />;
45
286
  },
46
- {
47
- variants: ['dark'],
287
+ args: {
288
+ onBlur: fn(),
289
+ onFocus: fn(),
290
+ onKeyDown: fn(),
291
+ onMouseEnter: fn(),
292
+ onMouseLeave: fn(),
293
+ previewAddonStart: false,
294
+ previewAddonEnd: false,
48
295
  },
49
- );
296
+ argTypes: {
297
+ onClick: { table: { disable: true } },
298
+ onBlur: { table: { disable: true } },
299
+ onFocus: { table: { disable: true } },
300
+ onKeyDown: { table: { disable: true } },
301
+ onMouseEnter: { table: { disable: true } },
302
+ onMouseLeave: { table: { disable: true } },
303
+ ...previewArgTypes,
304
+ },
305
+ };
50
306
 
51
- export const Variants = storyConfig<Story>(
52
- {
53
- render: (args) => {
54
- return (
55
- <>
56
- <div className="m-b-2">
57
- <div className="title-4 m-b-1">Accent</div>
58
- <div className="d-flex flex-wrap" style={{ gap: 'var(--size-16)' }}>
59
- <Button {...args} priority={Priority.PRIMARY} type={ControlType.ACCENT} />
60
- <Button {...args} priority={Priority.SECONDARY} type={ControlType.ACCENT} />
61
- <Button {...args} priority={Priority.TERTIARY} type={ControlType.ACCENT} />
62
- </div>
63
- </div>
64
- <div className="m-b-2">
65
- <div className="title-4 m-b-1">Positive</div>
66
- <div className="d-flex flex-wrap" style={{ gap: 'var(--size-16)' }}>
67
- <Button {...args} priority={Priority.PRIMARY} type={ControlType.POSITIVE} />
68
- <Button {...args} priority={Priority.SECONDARY} type={ControlType.POSITIVE} />
69
- </div>
70
- </div>
71
- <div className="m-b-2">
72
- <div className="title-4 m-b-1">Negative</div>
73
- <div className="d-flex flex-wrap" style={{ gap: 'var(--size-16)' }}>
74
- <Button {...args} priority={Priority.PRIMARY} type={ControlType.NEGATIVE} />
75
- <Button {...args} priority={Priority.SECONDARY} type={ControlType.NEGATIVE} />
76
- </div>
77
- </div>
78
- <div className="m-b-2">
79
- <div className="title-4 m-b-1">Disabled</div>
80
- <div className="d-flex flex-wrap" style={{ gap: 'var(--size-16)' }}>
81
- <Button {...args} priority={Priority.PRIMARY} disabled />
82
- <Button {...args} priority={Priority.SECONDARY} disabled />
83
- <Button {...args} priority={Priority.TERTIARY} disabled />
84
- </div>
85
- </div>
86
- </>
87
- );
307
+ /**
308
+ * There are two different types of button – default and negative – designed to emphasise the nature of the action. <br />
309
+ * **NB:** Sentiment only applies to `primary` and `secondary` priorities. <br />
310
+ * [Design documentation](https://wise.design/components/button#types)
311
+ */
312
+ export const Sentiment: StoryObj<PreviewStoryArgs> = {
313
+ render: function Render(args: PreviewStoryArgs) {
314
+ const [props, previewProps] = getPropsForPreview(args);
315
+
316
+ return (
317
+ <>
318
+ <Button {...props} {...previewProps} v2>
319
+ Default Sentiment
320
+ </Button>
321
+ <Button {...props} {...previewProps} v2 sentiment="negative">
322
+ Negative Sentiment
323
+ </Button>
324
+ <Button {...props} {...previewProps} v2 priority="secondary">
325
+ Default Sentiment
326
+ </Button>
327
+ <Button {...props} {...previewProps} v2 priority="secondary" sentiment="negative">
328
+ Negative Sentiment
329
+ </Button>
330
+ </>
331
+ );
332
+ },
333
+ argTypes: {
334
+ ...hideControls([
335
+ 'sentiment',
336
+ 'priority',
337
+ 'block',
338
+ 'href',
339
+ 'target',
340
+ 'children',
341
+ 'type',
342
+ 'className',
343
+ ]),
344
+ ...previewArgTypes,
345
+ },
346
+ args: {
347
+ previewAddonStart: false,
348
+ previewAddonEnd: false,
349
+ },
350
+ decorators: [withComponentGrid('30rem')],
351
+ };
352
+
353
+ /**
354
+ * Priorities set a visual hierarchy amongst the buttons displayed on the
355
+ * screen to help more important buttons to take precedence over others. <br />
356
+ * [Design documentation](https://wise.design/components/button#priorities)
357
+ */
358
+ export const Priority: StoryObj<PreviewStoryArgs> = {
359
+ render: function Render(args: PreviewStoryArgs) {
360
+ const [props, previewProps] = getPropsForPreview(args);
361
+
362
+ return (
363
+ <>
364
+ <Button {...props} {...previewProps} v2>
365
+ Primary Priority (default)
366
+ </Button>
367
+ <Button {...props} {...previewProps} v2 priority="secondary">
368
+ Secondary Priority
369
+ </Button>
370
+ <Button {...props} {...previewProps} v2 priority="secondary-neutral">
371
+ Secondary neutral Priority
372
+ </Button>
373
+ <Button {...props} {...previewProps} v2 priority="tertiary">
374
+ Tertiary Priority
375
+ </Button>
376
+ </>
377
+ );
378
+ },
379
+ argTypes: {
380
+ ...hideControls(['priority', 'block', 'href', 'target', 'children', 'type', 'className']),
381
+ ...previewArgTypes,
382
+ },
383
+ args: {
384
+ previewAddonStart: false,
385
+ previewAddonEnd: false,
386
+ },
387
+ decorators: [withComponentGrid()],
388
+ };
389
+
390
+ /**
391
+ * There are three different button sizes – small (`sm`), medium (`md`) and large (`lg`) – each used for different purposes. <br />
392
+ * [Design documentation](https://wise.design/components/button#sizes)
393
+ */
394
+ export const Size: StoryObj<PreviewStoryArgs> = {
395
+ render: function Render(args: PreviewStoryArgs) {
396
+ const [props, previewProps] = getPropsForPreview(args);
397
+
398
+ return (
399
+ <>
400
+ <Button {...props} {...previewProps}>
401
+ Large button (default)
402
+ </Button>
403
+ <Button {...props} {...previewProps} size="md">
404
+ Medium button
405
+ </Button>
406
+ <Button {...props} {...previewProps} size="sm">
407
+ Small button
408
+ </Button>
409
+ </>
410
+ );
411
+ },
412
+ argTypes: {
413
+ ...hideControls(['size', 'block', 'href', 'target', 'children', 'type', 'className']),
414
+ ...previewArgTypes,
415
+ },
416
+ args: {
417
+ previewAddonStart: false,
418
+ previewAddonEnd: false,
419
+ },
420
+ decorators: [withComponentGrid()],
421
+ };
422
+
423
+ /**
424
+ * If `href` prop is set, the component will be automatically rendered as an HTML anchor element.
425
+ */
426
+ export const AsAnchor: StoryObj<PreviewStoryArgs> = {
427
+ render: function Render(args: PreviewStoryArgs) {
428
+ const [props, previewProps] = getPropsForPreview(args);
429
+
430
+ return (
431
+ <Button {...props} {...previewProps}>
432
+ Button as anchor
433
+ </Button>
434
+ );
435
+ },
436
+ argTypes: {
437
+ ...hideControls(['block']),
438
+ ...previewArgTypes,
439
+ },
440
+ args: {
441
+ href: '#',
442
+ previewAddonStart: false,
443
+ previewAddonEnd: false,
444
+ onClick: undefined,
445
+ },
446
+ };
447
+
448
+ export const Disabled: StoryObj<PreviewStoryArgs> = {
449
+ render: function Render(args: PreviewStoryArgs) {
450
+ const [props, previewProps] = getPropsForPreview(args);
451
+
452
+ return (
453
+ <Button {...props} {...previewProps}>
454
+ Disabled button
455
+ </Button>
456
+ );
457
+ },
458
+ argTypes: {
459
+ ...hideControls(['block']),
460
+ ...previewArgTypes,
461
+ },
462
+ args: {
463
+ disabled: true,
464
+ previewAddonStart: false,
465
+ previewAddonEnd: false,
466
+ },
467
+ };
468
+
469
+ export const Loading: StoryObj<PreviewStoryArgs> = {
470
+ render: function Render(args: PreviewStoryArgs) {
471
+ const [props, previewProps] = getPropsForPreview(args);
472
+
473
+ return (
474
+ <Button {...props} {...previewProps}>
475
+ Button as anchor
476
+ </Button>
477
+ );
478
+ },
479
+ argTypes: {
480
+ ...hideControls(['block']),
481
+ ...previewArgTypes,
482
+ },
483
+ args: {
484
+ loading: true,
485
+ previewAddonStart: false,
486
+ previewAddonEnd: false,
487
+ },
488
+ };
489
+
490
+ /**
491
+ * A Button that takes up the full width of its container (`display: block`).
492
+ */
493
+ export const DisplayBlock: StoryObj<PreviewStoryArgs> = {
494
+ render: function Render(args: PreviewStoryArgs) {
495
+ const [props, previewProps] = getPropsForPreview(args);
496
+
497
+ return (
498
+ <Button {...props} {...previewProps}>
499
+ Full-width button
500
+ </Button>
501
+ );
502
+ },
503
+ argTypes: {
504
+ ...hideControls([
505
+ 'href',
506
+ 'target',
507
+ 'priority',
508
+ 'sentiment',
509
+ 'disabled',
510
+ 'children',
511
+ 'type',
512
+ 'className',
513
+ ]),
514
+ ...previewArgTypes,
515
+ },
516
+ args: {
517
+ block: true,
518
+ previewAddonStart: false,
519
+ previewAddonEnd: false,
520
+ },
521
+ };
522
+
523
+ /**
524
+ * Icons are only supported for `sm` and `md` size Buttons. <br />
525
+ * [Design documentation](https://wise.design/components/button#accessories)
526
+ */
527
+ export const WithIcons: StoryObj<PreviewStoryArgs> = {
528
+ render: function Render(args: PreviewStoryArgs) {
529
+ const [props] = getPropsForPreview(args);
530
+
531
+ return (
532
+ <>
533
+ <Button {...props} v2 addonStart={{ type: 'icon', value: <Freeze /> }}>
534
+ With start icon
535
+ </Button>
536
+
537
+ <Button {...props} v2 addonEnd={{ type: 'icon', value: <ArrowRight /> }}>
538
+ With end icon
539
+ </Button>
540
+
541
+ <Button
542
+ {...props}
543
+ v2
544
+ addonStart={{ type: 'icon', value: <Freeze /> }}
545
+ addonEnd={{ type: 'icon', value: <ArrowRight /> }}
546
+ >
547
+ With both icons
548
+ </Button>
549
+ </>
550
+ );
551
+ },
552
+ argTypes: {
553
+ ...hideControls(['href', 'target', 'sentiment', 'disabled', 'children', 'type', 'className']),
554
+ },
555
+ args: {
556
+ size: 'md',
557
+ },
558
+ parameters: {
559
+ docs: {
560
+ source: {
561
+ code: `
562
+ <>
563
+ <Button v2 size="md" addonStart={{ type: 'icon', value: <Freeze /> }}>
564
+ With start icon
565
+ </Button>
566
+
567
+ <Button v2 size="md" addonEnd={{ type: 'icon', value: <ArrowRight /> }}>
568
+ With end icon
569
+ </Button>
570
+
571
+ <Button v2 size="md" addonStart={{ type: 'icon', value: <Freeze /> }} addonEnd={{ type: 'icon', value: <ArrowRight /> }}>
572
+ With both icons
573
+ </Button>
574
+ </>
575
+ `,
576
+ },
88
577
  },
89
578
  },
90
- { variants: ['default', 'dark', 'rtl'] },
91
- );
579
+ decorators: [withComponentGrid()],
580
+ };
92
581
 
93
582
  /**
94
- * The purpose of the `loading` mode is to convey a message to the
95
- * user that some asynchronous process has been triggered, likely
96
- * in response to their previous action.
97
- *
98
- * Although it carries some similarities with the `disabled` mode
99
- * (users cannot activate a loading button), it's not hidden from
100
- * the keyboard and assistive tech users (users can focus on it,
101
- * and it's announced by screen readers), and is also much more
102
- * accessible to sighted users due to its default, high contrast.
583
+ * Avatars are only supported by the `md` size Buttons and are only allowed before the label. <br />
584
+ * [Design documentation](https://wise.design/components/button#accessories)
103
585
  */
104
- export const Loading = storyConfig<Story>(
105
- {
106
- render: (args) => {
107
- return (
108
- <div className="d-flex flex-wrap" style={{ gap: 'var(--size-16)' }}>
109
- <Button {...args} loading priority={Priority.PRIMARY} />
110
- <Button {...args} loading priority={Priority.SECONDARY} />
111
- <Button {...args} loading priority={Priority.TERTIARY} />
112
- <Button {...args} loading priority={Priority.PRIMARY} type={ControlType.NEGATIVE} />
113
- <Button {...args} loading priority={Priority.SECONDARY} type={ControlType.NEGATIVE} />
114
- </div>
115
- );
116
- },
117
- args: {
118
- loading: true,
119
- },
120
- },
121
- { variants: ['default', 'dark', 'rtl'] },
122
- );
586
+ export const WithAvatars: StoryObj<PreviewStoryArgs> = {
587
+ render: function Render(args: PreviewStoryArgs) {
588
+ const [props] = getPropsForPreview(args);
589
+
590
+ return (
591
+ <>
592
+ <Button {...props} v2 addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}>
593
+ With single avatar
594
+ </Button>
595
+
596
+ <Button
597
+ {...props}
598
+ v2
599
+ addonStart={{
600
+ type: 'avatar',
601
+ value: [{ asset: <Flag code="br" /> }, { asset: <Flag code="jp" /> }],
602
+ }}
603
+ >
604
+ With double avatar
605
+ </Button>
606
+
607
+ <Button {...props} v2 addonStart={{ type: 'avatar', value: [{ profileName: 'John Doe' }] }}>
608
+ With initials
609
+ </Button>
610
+
611
+ <Button
612
+ {...props}
613
+ v2
614
+ addonStart={{ type: 'avatar', value: [{ imgSrc: '../avatar-square-dude.webp' }] }}
615
+ >
616
+ With an image
617
+ </Button>
618
+ </>
619
+ );
620
+ },
621
+ argTypes: hideControls([
622
+ 'href',
623
+ 'target',
624
+ 'sentiment',
625
+ 'disabled',
626
+ 'children',
627
+ 'type',
628
+ 'className',
629
+ ]),
630
+ args: {
631
+ size: 'md',
632
+ },
633
+ parameters: {
634
+ docs: {
635
+ source: {
636
+ code: `
637
+ <>
638
+ <Button
639
+ v2
640
+ size="md"
641
+ addonStart={{
642
+ type: 'avatar',
643
+ value: [{ asset: <Freeze /> }]
644
+ }}
645
+ >
646
+ With single avatar
647
+ </Button>
648
+
649
+ <Button
650
+ v2
651
+ size="md"
652
+ addonStart={{
653
+ type: 'avatar',
654
+ value: [{ asset: <Flag code="br" /> }, { asset: <Flag code="jp" /> }]
655
+ }}
656
+ >
657
+ With double avatar
658
+ </Button>
659
+
660
+ <Button
661
+ v2
662
+ size="md"
663
+ addonStart={{
664
+ type: 'avatar',
665
+ value: [{ profileName: 'John Doe' }]
666
+ }}
667
+ >
668
+ With initials
669
+ </Button>
670
+
671
+ <Button
672
+ v2
673
+ size="md"
674
+ addonStart={{
675
+ type: 'avatar',
676
+ value: [{ imgSrc: '../avatar-square-dude.webp' }]
677
+ }}
678
+ >
679
+ With image Avatar
680
+ </Button>
681
+ </>
682
+ `,
683
+ },
684
+ },
685
+ },
686
+ decorators: [withComponentGrid()],
687
+ };
123
688
 
124
- export const SocialMedia = storyConfig<Story>(
689
+ const buttonPriorities = ['primary', 'secondary', 'secondary-neutral', 'tertiary'] as const;
690
+ const buttonSizes = ['sm', 'md', 'lg'] as const;
691
+
692
+ export const AllVariants = storyConfig(
125
693
  {
126
- render: () => {
127
- return (
128
- <>
129
- <div className="m-b-2">
130
- <button type="button" className="btn btn-google">
131
- Login with Google
132
- </button>
133
- </div>
134
- <div className="m-b-2">
135
- <button type="button" className="btn btn-facebook">
136
- Login with Facebook
137
- </button>
138
- </div>
139
- <div className="m-b-2">
140
- <button type="button" className="btn btn-lg btn-facebook">
141
- Large Button
142
- </button>
143
- </div>
144
- <div className="m-b-2">
145
- <button type="button" className="btn btn-block btn-facebook">
146
- Block Button
147
- </button>
148
- </div>
149
- <div className="m-b-2">
150
- <button type="button" className="btn btn-lg btn-block btn-facebook">
151
- Large Block Button
152
- </button>
153
- </div>
154
- </>
155
- );
156
- },
157
- },
158
- { variants: ['default', 'dark', 'rtl'] },
694
+ tags: ['!autodocs'],
695
+ parameters: {
696
+ padding: '0',
697
+ },
698
+ render: () => (
699
+ <div
700
+ className="button-variants"
701
+ style={{ display: 'flex', flexWrap: 'wrap', gap: '16px', maxWidth: '1200px' }}
702
+ >
703
+ {buttonPriorities.map((priority) =>
704
+ buttonSizes.map((size) => (
705
+ <div
706
+ key={`${priority}-default-${size}`}
707
+ style={{ flex: '1 0 30%', marginBottom: '16px', justifyContent: 'space-between' }}
708
+ >
709
+ <Button
710
+ v2
711
+ priority={priority as ButtonPriority}
712
+ size={size}
713
+ addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
714
+ addonEnd={{ type: 'icon', value: <ArrowRight /> }}
715
+ block
716
+ >
717
+ {`${priority} default ${size}`}
718
+ </Button>
719
+ <Button
720
+ className="m-t-1 m-b-1"
721
+ v2
722
+ priority={priority as ButtonPriority}
723
+ size={size}
724
+ addonStart={{
725
+ type: 'avatar',
726
+ value: [{ asset: <Freeze /> }, { asset: <Freeze /> }],
727
+ }}
728
+ addonEnd={{ type: 'icon', value: <ArrowRight /> }}
729
+ block
730
+ disabled
731
+ >
732
+ {`${priority} default ${size} Disabled`}
733
+ </Button>
734
+ <Button
735
+ v2
736
+ priority={priority as ButtonPriority}
737
+ size={size}
738
+ addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
739
+ addonEnd={{ type: 'icon', value: <ArrowRight /> }}
740
+ block
741
+ loading
742
+ >
743
+ {`${priority} default ${size} Loading`}
744
+ </Button>
745
+ </div>
746
+ )),
747
+ )}
748
+ {['primary', 'secondary'].map((priority) =>
749
+ buttonSizes.map((size) => (
750
+ <div
751
+ key={`${priority}-negative-${size}`}
752
+ style={{ flex: '1 0 30%', marginBottom: '16px', justifyContent: 'space-between' }}
753
+ >
754
+ <Button
755
+ v2
756
+ sentiment="negative"
757
+ priority={priority as ButtonPriority}
758
+ size={size}
759
+ addonEnd={{ type: 'icon', value: <ChevronRight /> }}
760
+ addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
761
+ block
762
+ >
763
+ {`${priority} negative ${size}`}
764
+ </Button>
765
+ <Button
766
+ className="m-t-1 m-b-1"
767
+ v2
768
+ sentiment="negative"
769
+ priority={priority as ButtonPriority}
770
+ size={size}
771
+ addonEnd={{ type: 'icon', value: <ChevronRight /> }}
772
+ addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
773
+ block
774
+ disabled
775
+ >
776
+ {`${priority} negative ${size} Disabled`}
777
+ </Button>
778
+ <Button
779
+ v2
780
+ sentiment="negative"
781
+ priority={priority as ButtonPriority}
782
+ size={size}
783
+ addonEnd={{ type: 'icon', value: <ChevronRight /> }}
784
+ addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
785
+ block
786
+ loading
787
+ >
788
+ {`${priority} negative ${size} Loading`}
789
+ </Button>
790
+ </div>
791
+ )),
792
+ )}
793
+ </div>
794
+ ),
795
+ },
796
+ { variants: ['default', 'dark', 'bright-green', 'forest-green', 'rtl'] },
159
797
  );
160
798
 
161
- export const SocialMediaMobile = storyConfig<Story>(SocialMedia, {
162
- variants: ['default', 'dark', 'rtl', 'mobile'],
163
- });
799
+ export const AccessibilityAddons: Story = {
800
+ args: {
801
+ v2: true,
802
+ addonStart: {
803
+ type: 'avatar',
804
+ value: [{ asset: <Flag code="br" /> }, { asset: <Flag code="jp" /> }],
805
+ },
806
+ 'aria-label': 'Convert Real to Yen',
807
+ children: 'Convert',
808
+ size: 'md',
809
+ },
810
+ tags: ['!autodocs', '!dev'],
811
+ };