@transferwise/components 0.0.0-experimental-4af964d → 0.0.0-experimental-04f7ce3

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.
@@ -13,112 +13,289 @@ import {
13
13
  Bank,
14
14
  Freeze,
15
15
  } from '@transferwise/icons';
16
+ import { fn } from 'storybook/test';
16
17
  import IconButton, { Props } from './IconButton';
17
- import { action } from 'storybook/actions';
18
- import Body from '../body';
19
18
  import SentimentSurface from '../sentimentSurface';
20
19
 
20
+ /**
21
+ * **Design guidance**: <a href="https://wise.design/components/icon-button" target="_blank">wise.design/components/icon-button</a>
22
+ */
21
23
  export default {
22
24
  title: 'Actions/IconButton',
23
25
  component: IconButton,
26
+ args: {
27
+ onClick: fn(),
28
+ 'aria-label': 'Action',
29
+ },
30
+ argTypes: {
31
+ children: {
32
+ description: 'Icon rendered inside the button.',
33
+ },
34
+ 'aria-label': {
35
+ description: 'Provides the accessible name when the control has no visible text label.',
36
+ },
37
+ size: {
38
+ description: 'Sets the button diameter in pixels.',
39
+ },
40
+ priority: {
41
+ description: 'Sets the visual hierarchy of the action.',
42
+ },
43
+ type: {
44
+ description: 'Emphasises the nature of the action. Use `negative` for destructive actions.',
45
+ },
46
+ disabled: {
47
+ description: 'Toggles the disabled state.',
48
+ },
49
+ href: {
50
+ description: 'Renders the component as a link when provided.',
51
+ },
52
+ target: {
53
+ description: 'Controls where the linked document opens. Use `_blank` to open in a new tab.',
54
+ },
55
+ id: { description: '', table: { category: 'Common' } },
56
+ className: { description: '', table: { category: 'Common' } },
57
+ role: { description: '', table: { category: 'Common' } },
58
+ tabIndex: { description: '', table: { category: 'Common' } },
59
+ 'data-testid': { description: '', table: { category: 'Common' } },
60
+ onClick: { description: '', table: { category: 'Common' } },
61
+ },
62
+ parameters: {
63
+ docs: { toc: true },
64
+ },
24
65
  } satisfies Meta<typeof IconButton>;
25
66
 
26
67
  type Story = StoryObj<typeof IconButton>;
27
68
 
28
69
  const sizes: Props['size'][] = [16, 24, 32, 40, 48, 56, 72];
29
70
 
30
- const Template = ({ size, disabled }: Props) => {
31
- return (
71
+ /**
72
+ * Explore size, priority, type, and disabled state via the controls panel.
73
+ * Use `aria-label` to provide an accessible name.
74
+ */
75
+ export const Playground: Story = {
76
+ args: {
77
+ size: 48,
78
+ priority: 'primary',
79
+ type: 'default',
80
+ disabled: false,
81
+ },
82
+ render: (args) => (
83
+ <IconButton {...args}>
84
+ <Plus />
85
+ </IconButton>
86
+ ),
87
+ };
88
+
89
+ /**
90
+ * Priorities set a visual hierarchy amongst the buttons displayed on the
91
+ * screen to help more important buttons to take precedence over others. <br />
92
+ * <a href="https://wise.design/components/icon-button#priorities" target="_blank">Design documentation</a>
93
+ */
94
+ export const Priority: Story = {
95
+ args: {
96
+ type: 'default',
97
+ },
98
+ argTypes: {
99
+ type: {
100
+ control: 'radio',
101
+ options: ['default', 'negative'],
102
+ },
103
+ priority: { table: { disable: true } },
104
+ size: { table: { disable: true } },
105
+ disabled: { table: { disable: true } },
106
+ href: { table: { disable: true } },
107
+ target: { table: { disable: true } },
108
+ onClick: { table: { disable: true } },
109
+ },
110
+ decorators: [
111
+ (Story) => (
112
+ <div style={{ display: 'flex', gap: '24px', alignItems: 'center', justifyContent: 'center' }}>
113
+ <Story />
114
+ </div>
115
+ ),
116
+ ],
117
+ render: (args: Props) => (
32
118
  <>
33
- <IconButton
34
- size={size}
35
- disabled={disabled}
36
- aria-label="One step back"
37
- priority="primary"
38
- type="default"
39
- onClick={action('button click')}
40
- >
119
+ <IconButton priority="primary" type={args.type} aria-label="Primary" onClick={fn()}>
41
120
  <Plus />
42
121
  </IconButton>
43
- <IconButton
44
- size={size}
45
- disabled={disabled}
46
- aria-label="One step back"
47
- priority="secondary"
48
- type="default"
49
- onClick={action('button click')}
50
- >
51
- <Defrost />
122
+ <IconButton priority="secondary" type={args.type} aria-label="Secondary" onClick={fn()}>
123
+ <Settings />
52
124
  </IconButton>
53
- <IconButton
54
- size={size}
55
- disabled={disabled}
56
- aria-label="One step back"
57
- priority="tertiary"
58
- type="default"
59
- onClick={action('button click')}
60
- >
61
- <ArrowLeft />
125
+ <IconButton priority="tertiary" type={args.type} aria-label="Tertiary" onClick={fn()}>
126
+ <Star />
62
127
  </IconButton>
63
- <IconButton
64
- size={size}
65
- disabled={disabled}
66
- aria-label="One step back"
67
- priority="minimal"
68
- type="default"
69
- onClick={action('button click')}
70
- >
128
+ <IconButton priority="minimal" type={args.type} aria-label="Minimal" onClick={fn()}>
71
129
  <Menu />
72
130
  </IconButton>
73
- <IconButton
74
- size={size}
75
- disabled={disabled}
76
- aria-label="One step back"
77
- priority="primary"
78
- type="negative"
79
- onClick={action('button click')}
80
- >
81
- <Cross />
131
+ </>
132
+ ),
133
+ };
134
+
135
+ /**
136
+ * There are two different types of button – default and negative – designed to emphasise the nature of the action. <br />
137
+ * <a href="https://wise.design/components/icon-button#types" target="_blank">Design documentation</a>
138
+ */
139
+ export const Type: Story = {
140
+ args: {
141
+ priority: 'primary',
142
+ },
143
+ argTypes: {
144
+ priority: {
145
+ control: 'radio',
146
+ options: ['primary', 'secondary', 'tertiary', 'minimal'],
147
+ },
148
+ type: { table: { disable: true } },
149
+ size: { table: { disable: true } },
150
+ disabled: { table: { disable: true } },
151
+ href: { table: { disable: true } },
152
+ target: { table: { disable: true } },
153
+ onClick: { table: { disable: true } },
154
+ },
155
+ decorators: [
156
+ (Story) => (
157
+ <div style={{ display: 'flex', gap: '24px', alignItems: 'center', justifyContent: 'center' }}>
158
+ <Story />
159
+ </div>
160
+ ),
161
+ ],
162
+ render: (args: Props) => (
163
+ <>
164
+ <IconButton priority={args.priority} type="default" aria-label="Default" onClick={fn()}>
165
+ <Plus />
82
166
  </IconButton>
83
- <IconButton
84
- size={size}
85
- disabled={disabled}
86
- aria-label="One step back"
87
- priority="secondary"
88
- type="negative"
89
- onClick={action('button click')}
90
- >
91
- <Edit />
167
+ <IconButton priority={args.priority} type="negative" aria-label="Negative" onClick={fn()}>
168
+ <Cross />
92
169
  </IconButton>
93
170
  </>
94
- );
171
+ ),
95
172
  };
96
173
 
97
- export const Basic: Story = {
98
- render: () => {
99
- return (
100
- <div
101
- style={{
102
- gap: '1em',
103
- display: 'grid',
104
- justifyContent: 'space-between',
105
- gridTemplate: `auto auto / repeat(6, min-content)`,
106
- }}
107
- >
108
- {['Primary', 'Secondary', 'Tertiary', 'Minimal', 'Neg primary', 'Neg secondary'].map(
109
- (variant) => (
110
- <Body key={variant} type="body-default-bold">
111
- {variant}
112
- </Body>
113
- ),
114
- )}
115
- {sizes.map((size) => (
116
- <Template key={size} size={size} />
117
- ))}
118
- <Template size={72} disabled />
174
+ /**
175
+ * IconButton is available in 7 sizes: 16, 24, 32, 40, 48, 56, 72. <br />
176
+ * <a href="https://wise.design/components/icon-button#sizes" target="_blank">Design documentation</a>
177
+ */
178
+ export const Size: Story = {
179
+ args: {
180
+ priority: 'primary',
181
+ type: 'default',
182
+ },
183
+ argTypes: {
184
+ priority: {
185
+ control: 'radio',
186
+ options: ['primary', 'secondary', 'tertiary', 'minimal'],
187
+ },
188
+ type: {
189
+ control: 'radio',
190
+ options: ['default', 'negative'],
191
+ },
192
+ size: { table: { disable: true } },
193
+ disabled: { table: { disable: true } },
194
+ href: { table: { disable: true } },
195
+ target: { table: { disable: true } },
196
+ onClick: { table: { disable: true } },
197
+ },
198
+ decorators: [
199
+ (Story) => (
200
+ <div style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>
201
+ <Story />
119
202
  </div>
120
- );
203
+ ),
204
+ ],
205
+ render: (args: Props) => (
206
+ <>
207
+ {sizes.map((size) => (
208
+ <div
209
+ key={size}
210
+ style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '8px' }}
211
+ >
212
+ <IconButton
213
+ size={size}
214
+ priority={args.priority}
215
+ type={args.type}
216
+ aria-label={`${size}px`}
217
+ >
218
+ <ArrowLeft />
219
+ </IconButton>
220
+ <span style={{ fontSize: '12px' }}>{size}px</span>
221
+ </div>
222
+ ))}
223
+ </>
224
+ ),
225
+ parameters: {
226
+ docs: {
227
+ source: {
228
+ code: `{[16, 24, 32, 40, 48, 56, 72].map((size) => (
229
+ <div key={size}>
230
+ <IconButton size={size} priority="primary" type="default" aria-label={\`\${size}px\`}>
231
+ <ArrowLeft />
232
+ </IconButton>
233
+ <span>{size}px</span>
234
+ </div>
235
+ ))}`,
236
+ },
237
+ },
238
+ },
239
+ };
240
+
241
+ /**
242
+ * Disabled buttons cannot be interacted with and are visually distinct.
243
+ */
244
+ export const Disabled: Story = {
245
+ args: {
246
+ priority: 'primary',
247
+ type: 'default',
121
248
  },
249
+ argTypes: {
250
+ priority: {
251
+ control: 'radio',
252
+ options: ['primary', 'secondary', 'tertiary', 'minimal'],
253
+ },
254
+ type: {
255
+ control: 'radio',
256
+ options: ['default', 'negative'],
257
+ },
258
+ size: { table: { disable: true } },
259
+ disabled: { table: { disable: true } },
260
+ href: { table: { disable: true } },
261
+ target: { table: { disable: true } },
262
+ onClick: { table: { disable: true } },
263
+ },
264
+ render: (args: Props) => (
265
+ <IconButton disabled priority={args.priority} type={args.type} aria-label="Disabled">
266
+ <Plus />
267
+ </IconButton>
268
+ ),
269
+ };
270
+
271
+ /**
272
+ * IconButton can render as an anchor element when `href` is provided.
273
+ */
274
+ export const AsAnchor: Story = {
275
+ args: {
276
+ priority: 'primary',
277
+ type: 'default',
278
+ href: 'https://wise.com',
279
+ target: '_blank',
280
+ },
281
+ argTypes: {
282
+ priority: {
283
+ control: 'radio',
284
+ options: ['primary', 'secondary', 'tertiary', 'minimal'],
285
+ },
286
+ type: {
287
+ control: 'radio',
288
+ options: ['default', 'negative'],
289
+ },
290
+ size: { table: { disable: true } },
291
+ disabled: { table: { disable: true } },
292
+ onClick: { table: { disable: true } },
293
+ },
294
+ render: (args: Props) => (
295
+ <IconButton {...args} aria-label="External link">
296
+ <ArrowLeft />
297
+ </IconButton>
298
+ ),
122
299
  };
123
300
 
124
301
  /**
@@ -126,8 +303,25 @@ export const Basic: Story = {
126
303
  * the [SentimentSurface](?path=/docs/foundations-sentimentsurface--docs) component
127
304
  */
128
305
  export const SentimentAwareness: Story = {
129
- render: () => {
130
- const priorities = ['primary', 'secondary', 'tertiary', 'minimal', 'disabled'] as const;
306
+ args: {
307
+ size: 48,
308
+ },
309
+ argTypes: {
310
+ size: {
311
+ control: 'radio',
312
+ options: [16, 24, 32, 40, 48, 56, 72],
313
+ },
314
+ },
315
+ render: (args: Props) => {
316
+ const priorities = [
317
+ { key: 'primary', label: 'primary' },
318
+ { key: 'secondary', label: 'secondary' },
319
+ { key: 'tertiary', label: 'tertiary' },
320
+ { key: 'minimal', label: 'minimal' },
321
+ { key: 'neg-primary', label: 'negative\nprimary' },
322
+ { key: 'neg-secondary', label: 'negative\nsecondary' },
323
+ { key: 'disabled', label: 'disabled' },
324
+ ] as const;
131
325
  const sentiments = ['success', 'warning', 'negative', 'neutral', 'proposition'] as const;
132
326
 
133
327
  return (
@@ -137,21 +331,23 @@ export const SentimentAwareness: Story = {
137
331
  <div style={{ width: '82px', paddingLeft: '8px' }} />
138
332
  {priorities.map((priority) => (
139
333
  <div
140
- key={priority}
334
+ key={priority.key}
141
335
  style={{
142
- width: '32px',
336
+ width: `${args.size}px`,
143
337
  textAlign: 'center',
144
338
  fontSize: '11px',
145
339
  fontWeight: 'bold',
146
340
  writingMode: 'vertical-rl',
147
341
  transform: 'rotate(180deg)',
148
- height: '60px',
342
+ height: '80px',
149
343
  display: 'flex',
150
344
  alignItems: 'center',
151
345
  justifyContent: 'center',
346
+ whiteSpace: 'pre',
347
+ lineHeight: '1',
152
348
  }}
153
349
  >
154
- {priority}
350
+ {priority.label}
155
351
  </div>
156
352
  ))}
157
353
  </div>
@@ -176,48 +372,66 @@ export const SentimentAwareness: Story = {
176
372
  {sentiment} (base)
177
373
  </div>
178
374
  <IconButton
179
- size={32}
375
+ size={args.size}
180
376
  aria-label="Primary action"
181
377
  priority="primary"
182
378
  type="default"
183
- onClick={action('button click')}
379
+ onClick={fn()}
184
380
  >
185
381
  <Plus />
186
382
  </IconButton>
187
383
  <IconButton
188
- size={32}
384
+ size={args.size}
189
385
  aria-label="Secondary action"
190
386
  priority="secondary"
191
387
  type="default"
192
- onClick={action('button click')}
388
+ onClick={fn()}
193
389
  >
194
390
  <Settings />
195
391
  </IconButton>
196
392
  <IconButton
197
- size={32}
393
+ size={args.size}
198
394
  aria-label="Tertiary action"
199
395
  priority="tertiary"
200
396
  type="default"
201
- onClick={action('button click')}
397
+ onClick={fn()}
202
398
  >
203
399
  <Star />
204
400
  </IconButton>
205
401
  <IconButton
206
- size={32}
402
+ size={args.size}
207
403
  aria-label="Minimal action"
208
404
  priority="minimal"
209
405
  type="default"
210
- onClick={action('button click')}
406
+ onClick={fn()}
211
407
  >
212
408
  <Travel />
213
409
  </IconButton>
214
410
  <IconButton
215
- size={32}
411
+ size={args.size}
412
+ aria-label="Negative primary action"
413
+ priority="primary"
414
+ type="negative"
415
+ onClick={fn()}
416
+ >
417
+ <Cross />
418
+ </IconButton>
419
+ <IconButton
420
+ size={args.size}
421
+ aria-label="Negative secondary action"
422
+ priority="secondary"
423
+ type="negative"
424
+ onClick={fn()}
425
+ >
426
+ <Edit />
427
+ </IconButton>
428
+ <IconButton
429
+ size={args.size}
216
430
  aria-label="Disabled action"
217
431
  priority="primary"
218
432
  type="default"
219
433
  disabled
220
- onClick={action('button click')}
434
+ onClick={fn()}
221
435
  >
222
436
  <Menu />
223
437
  </IconButton>
@@ -240,48 +454,66 @@ export const SentimentAwareness: Story = {
240
454
  {sentiment} (elevated)
241
455
  </div>
242
456
  <IconButton
243
- size={32}
457
+ size={args.size}
244
458
  aria-label="Primary action"
245
459
  priority="primary"
246
460
  type="default"
247
- onClick={action('button click')}
461
+ onClick={fn()}
248
462
  >
249
463
  <Briefcase />
250
464
  </IconButton>
251
465
  <IconButton
252
- size={32}
466
+ size={args.size}
253
467
  aria-label="Secondary action"
254
468
  priority="secondary"
255
469
  type="default"
256
- onClick={action('button click')}
470
+ onClick={fn()}
257
471
  >
258
472
  <Bank />
259
473
  </IconButton>
260
474
  <IconButton
261
- size={32}
475
+ size={args.size}
262
476
  aria-label="Tertiary action"
263
477
  priority="tertiary"
264
478
  type="default"
265
- onClick={action('button click')}
479
+ onClick={fn()}
266
480
  >
267
481
  <Freeze />
268
482
  </IconButton>
269
483
  <IconButton
270
- size={32}
484
+ size={args.size}
271
485
  aria-label="Minimal action"
272
486
  priority="minimal"
273
487
  type="default"
274
- onClick={action('button click')}
488
+ onClick={fn()}
275
489
  >
276
490
  <Edit />
277
491
  </IconButton>
278
492
  <IconButton
279
- size={32}
493
+ size={args.size}
494
+ aria-label="Negative primary action"
495
+ priority="primary"
496
+ type="negative"
497
+ onClick={fn()}
498
+ >
499
+ <Cross />
500
+ </IconButton>
501
+ <IconButton
502
+ size={args.size}
503
+ aria-label="Negative secondary action"
504
+ priority="secondary"
505
+ type="negative"
506
+ onClick={fn()}
507
+ >
508
+ <Edit />
509
+ </IconButton>
510
+ <IconButton
511
+ size={args.size}
280
512
  aria-label="Disabled action"
281
513
  priority="primary"
282
514
  type="default"
283
515
  disabled
284
- onClick={action('button click')}
516
+ onClick={fn()}
285
517
  >
286
518
  <Cross />
287
519
  </IconButton>
@@ -292,10 +524,7 @@ export const SentimentAwareness: Story = {
292
524
  },
293
525
  parameters: {
294
526
  docs: {
295
- source: { type: 'dynamic' },
296
- canvas: {
297
- sourceState: 'hidden',
298
- },
527
+ canvas: { sourceState: 'hidden' },
299
528
  },
300
529
  },
301
530
  };