@transferwise/components 46.105.5 → 46.107.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.
Files changed (100) hide show
  1. package/build/actionOption/ActionOption.js.map +1 -1
  2. package/build/actionOption/ActionOption.mjs.map +1 -1
  3. package/build/checkboxOption/CheckboxOption.js.map +1 -1
  4. package/build/checkboxOption/CheckboxOption.mjs.map +1 -1
  5. package/build/header/Header.js.map +1 -1
  6. package/build/header/Header.mjs.map +1 -1
  7. package/build/inputs/SelectInput.js.map +1 -1
  8. package/build/inputs/SelectInput.mjs.map +1 -1
  9. package/build/legacylistItem/LegacyListItem.js.map +1 -1
  10. package/build/legacylistItem/LegacyListItem.mjs.map +1 -1
  11. package/build/listItem/ListItem.js +8 -8
  12. package/build/listItem/ListItem.js.map +1 -1
  13. package/build/listItem/ListItem.mjs +8 -8
  14. package/build/listItem/ListItem.mjs.map +1 -1
  15. package/build/main.css +28 -7
  16. package/build/navigationOption/NavigationOption.js.map +1 -1
  17. package/build/navigationOption/NavigationOption.mjs.map +1 -1
  18. package/build/navigationOptionsList/NavigationOptionsList.js.map +1 -1
  19. package/build/navigationOptionsList/NavigationOptionsList.mjs.map +1 -1
  20. package/build/radioOption/RadioOption.js.map +1 -1
  21. package/build/radioOption/RadioOption.mjs.map +1 -1
  22. package/build/styles/listItem/ListItem.css +28 -7
  23. package/build/styles/listItem/ListItem.grid.css +11 -3
  24. package/build/styles/listItem/ListItem.vars.css +0 -0
  25. package/build/styles/main.css +28 -7
  26. package/build/summary/Summary.js +8 -0
  27. package/build/summary/Summary.js.map +1 -1
  28. package/build/summary/Summary.mjs +8 -0
  29. package/build/summary/Summary.mjs.map +1 -1
  30. package/build/switchOption/SwitchOption.js +8 -0
  31. package/build/switchOption/SwitchOption.js.map +1 -1
  32. package/build/switchOption/SwitchOption.mjs +8 -0
  33. package/build/switchOption/SwitchOption.mjs.map +1 -1
  34. package/build/types/actionOption/ActionOption.d.ts +8 -0
  35. package/build/types/actionOption/ActionOption.d.ts.map +1 -1
  36. package/build/types/checkboxOption/CheckboxOption.d.ts +8 -0
  37. package/build/types/checkboxOption/CheckboxOption.d.ts.map +1 -1
  38. package/build/types/header/Header.d.ts +2 -2
  39. package/build/types/header/Header.d.ts.map +1 -1
  40. package/build/types/inputs/SelectInput.d.ts +2 -1
  41. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  42. package/build/types/legacylistItem/LegacyListItem.d.ts +8 -0
  43. package/build/types/legacylistItem/LegacyListItem.d.ts.map +1 -1
  44. package/build/types/listItem/ListItem.d.ts.map +1 -1
  45. package/build/types/listItem/_stories/helpers.d.ts +1 -1
  46. package/build/types/listItem/_stories/helpers.d.ts.map +1 -1
  47. package/build/types/listItem/_stories/subcomponents.d.ts +3 -0
  48. package/build/types/listItem/_stories/subcomponents.d.ts.map +1 -1
  49. package/build/types/listItem/_stories/variants/helpers.d.ts.map +1 -1
  50. package/build/types/listItem/constants.d.ts +16 -0
  51. package/build/types/listItem/constants.d.ts.map +1 -0
  52. package/build/types/navigationOption/NavigationOption.d.ts +8 -0
  53. package/build/types/navigationOption/NavigationOption.d.ts.map +1 -1
  54. package/build/types/navigationOptionsList/NavigationOptionsList.d.ts +9 -0
  55. package/build/types/navigationOptionsList/NavigationOptionsList.d.ts.map +1 -1
  56. package/build/types/radioOption/RadioOption.d.ts +8 -0
  57. package/build/types/radioOption/RadioOption.d.ts.map +1 -1
  58. package/build/types/summary/Summary.d.ts +8 -0
  59. package/build/types/summary/Summary.d.ts.map +1 -1
  60. package/build/types/switchOption/SwitchOption.d.ts +8 -0
  61. package/build/types/switchOption/SwitchOption.d.ts.map +1 -1
  62. package/package.json +3 -3
  63. package/src/actionOption/ActionOption.story.tsx +4 -0
  64. package/src/actionOption/ActionOption.tsx +8 -0
  65. package/src/checkboxOption/CheckboxOption.story.tsx +4 -0
  66. package/src/checkboxOption/CheckboxOption.tsx +8 -0
  67. package/src/header/Header.tsx +2 -2
  68. package/src/inputs/SelectInput.tsx +2 -1
  69. package/src/legacylistItem/LegacyListItem.story.tsx +4 -0
  70. package/src/legacylistItem/LegacyListItem.tsx +8 -0
  71. package/src/listItem/ListItem.css +28 -7
  72. package/src/listItem/ListItem.grid.css +11 -3
  73. package/src/listItem/ListItem.grid.less +14 -4
  74. package/src/listItem/ListItem.less +16 -4
  75. package/src/listItem/ListItem.spec.tsx +4 -1
  76. package/src/listItem/ListItem.tsx +9 -9
  77. package/src/listItem/ListItem.vars.css +0 -0
  78. package/src/listItem/ListItem.vars.less +11 -0
  79. package/src/listItem/_stories/ListItem.layout.test.story.tsx +10 -155
  80. package/src/listItem/_stories/ListItem.scenarios.story.tsx +4 -25
  81. package/src/listItem/_stories/ListItem.story.tsx +16 -10
  82. package/src/listItem/_stories/helpers.tsx +22 -6
  83. package/src/listItem/_stories/subcomponents.tsx +14 -2
  84. package/src/listItem/_stories/variants/ListItem.medium.test.story.tsx +1 -1
  85. package/src/listItem/_stories/variants/ListItem.neutral.test.story.tsx +55 -0
  86. package/src/listItem/_stories/variants/ListItem.small.test.story.tsx +1 -1
  87. package/src/listItem/_stories/variants/helpers.tsx +28 -1
  88. package/src/listItem/constants.ts +15 -0
  89. package/src/main.css +28 -7
  90. package/src/navigationOption/NavigationOption.story.tsx +4 -1
  91. package/src/navigationOption/NavigationOption.tsx +8 -0
  92. package/src/navigationOptionsList/NavigationOptionsList.story.tsx +4 -0
  93. package/src/navigationOptionsList/NavigationOptionsList.tsx +9 -0
  94. package/src/radioOption/RadioOption.story.tsx +4 -0
  95. package/src/radioOption/RadioOption.tsx +8 -0
  96. package/src/summary/Summary.story.tsx +4 -0
  97. package/src/summary/Summary.tsx +8 -0
  98. package/src/switchOption/SwitchOption.story.tsx +4 -1
  99. package/src/switchOption/SwitchOption.tsx +8 -0
  100. package/src/table/Table.story.tsx +1 -1
@@ -9,7 +9,7 @@
9
9
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-noInfo-hasPrompt:not(:has(.wds-list-item-subtitle-value, .wds-list-item-subtitle)) .wds-list-item-prompt {
10
10
  margin-top: -2px;
11
11
  }
12
- @container (min-width: 375px) {
12
+ @container (min-width: 309px) {
13
13
  .wds-list-item-gridWrapper .wds-list-item-control-wrapper {
14
14
  height: var(--wds-list-item-control-wrapper-height);
15
15
  align-content: center;
@@ -105,7 +105,7 @@
105
105
  grid-template-areas: "body";
106
106
  }
107
107
  }
108
- @container (min-width: 297px) and (max-width: 375px) {
108
+ @container (min-width: 241px) and (max-width: 308px) {
109
109
  .wds-list-item-gridWrapper .wds-list-item-media-image {
110
110
  -o-object-position: bottom left;
111
111
  object-position: bottom left;
@@ -231,8 +231,12 @@
231
231
  grid-template-rows: auto;
232
232
  grid-template-areas: "body";
233
233
  }
234
+ .wds-list-item-gridWrapper .wds-list-item-button-control--hasPrompt {
235
+ margin-top: 4px;
236
+ margin-top: var(--size-4);
237
+ }
234
238
  }
235
- @container (max-width: 297px) {
239
+ @container (max-width: 240px) {
236
240
  .wds-list-item-gridWrapper .wds-list-item-control-wrapper {
237
241
  align-content: start;
238
242
  }
@@ -373,6 +377,10 @@
373
377
  .wds-list-item-gridWrapper .wds-list-item-body .wds-list-item-value {
374
378
  text-align: left;
375
379
  }
380
+ .wds-list-item-gridWrapper .wds-list-item-button-control--hasPrompt {
381
+ margin-top: 4px;
382
+ margin-top: var(--size-4);
383
+ }
376
384
  }
377
385
  .wds-list-item-prompt {
378
386
  grid-area: prompt;
@@ -654,7 +662,7 @@
654
662
  }
655
663
  .wds-list-item-body {
656
664
  grid-area: body;
657
- align-items: center;
665
+ align-items: start;
658
666
  width: 100%;
659
667
  display: grid;
660
668
  grid-template-columns: 1fr max-content;
@@ -665,14 +673,27 @@
665
673
  gap: var(--size-16);
666
674
  word-break: break-word;
667
675
  }
676
+ .wds-list-item-titles,
677
+ .wds-list-item-value {
678
+ display: flex;
679
+ flex-direction: column;
680
+ justify-content: center;
681
+ }
682
+ @container (min-width: 309px) {
683
+ .wds-list-item-titles,
684
+ .wds-list-item-value {
685
+ min-height: 100%;
686
+ min-height: var(--wds-list-item-value-min-height, 100%);
687
+ }
688
+ }
689
+ .wds-list-item-value {
690
+ text-align: right;
691
+ }
668
692
  .wds-list-item-title,
669
693
  .wds-list-item-title-value {
670
694
  color: #37517e;
671
695
  color: var(--color-content-primary);
672
696
  }
673
- .wds-list-item-value {
674
- text-align: right;
675
- }
676
697
  .wds-list-item-body-center {
677
698
  display: flex;
678
699
  flex-direction: row;
@@ -9,7 +9,7 @@
9
9
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-noInfo-hasPrompt:not(:has(.wds-list-item-subtitle-value, .wds-list-item-subtitle)) .wds-list-item-prompt {
10
10
  margin-top: -2px;
11
11
  }
12
- @container (min-width: 375px) {
12
+ @container (min-width: 309px) {
13
13
  .wds-list-item-gridWrapper .wds-list-item-control-wrapper {
14
14
  height: var(--wds-list-item-control-wrapper-height);
15
15
  align-content: center;
@@ -105,7 +105,7 @@
105
105
  grid-template-areas: "body";
106
106
  }
107
107
  }
108
- @container (min-width: 297px) and (max-width: 375px) {
108
+ @container (min-width: 241px) and (max-width: 308px) {
109
109
  .wds-list-item-gridWrapper .wds-list-item-media-image {
110
110
  -o-object-position: bottom left;
111
111
  object-position: bottom left;
@@ -231,8 +231,12 @@
231
231
  grid-template-rows: auto;
232
232
  grid-template-areas: "body";
233
233
  }
234
+ .wds-list-item-gridWrapper .wds-list-item-button-control--hasPrompt {
235
+ margin-top: 4px;
236
+ margin-top: var(--size-4);
237
+ }
234
238
  }
235
- @container (max-width: 297px) {
239
+ @container (max-width: 240px) {
236
240
  .wds-list-item-gridWrapper .wds-list-item-control-wrapper {
237
241
  align-content: start;
238
242
  }
@@ -373,4 +377,8 @@
373
377
  .wds-list-item-gridWrapper .wds-list-item-body .wds-list-item-value {
374
378
  text-align: left;
375
379
  }
380
+ .wds-list-item-gridWrapper .wds-list-item-button-control--hasPrompt {
381
+ margin-top: 4px;
382
+ margin-top: var(--size-4);
383
+ }
376
384
  }
@@ -1,3 +1,5 @@
1
+ @import (reference) "./ListItem.vars.less";
2
+
1
3
  .wds-list-item {
2
4
  &-gridWrapper {
3
5
  display: grid;
@@ -10,9 +12,9 @@
10
12
  margin-top: -2px;
11
13
  }
12
14
  }
13
- }
15
+ }
14
16
 
15
- @container (min-width: 375px) {
17
+ @container (min-width: unit(@wds-list-item-cq-max + 1, px)) {
16
18
  .wds-list-item-control-wrapper {
17
19
  height: var(--wds-list-item-control-wrapper-height);
18
20
  align-content: center;
@@ -167,7 +169,7 @@
167
169
  }
168
170
  }
169
171
 
170
- @container (min-width: 297px) and (max-width: 375px) {
172
+ @container (min-width: unit(@wds-list-item-cq-min + 1, px)) and (max-width: unit(@wds-list-item-cq-max, px)) {
171
173
  .wds-list-item-media-image{
172
174
  object-position: bottom left;
173
175
  }
@@ -396,9 +398,13 @@
396
398
  "body"
397
399
  }
398
400
  }
401
+
402
+ .wds-list-item-button-control--hasPrompt{
403
+ margin-top: var(--size-4);
404
+ }
399
405
  }
400
406
 
401
- @container (max-width: 297px) {
407
+ @container (max-width: unit(@wds-list-item-cq-min, px)) {
402
408
  .wds-list-item-control-wrapper {
403
409
  align-content: start;
404
410
  }
@@ -631,6 +637,10 @@
631
637
  text-align: left;
632
638
  }
633
639
  }
640
+
641
+ .wds-list-item-button-control--hasPrompt{
642
+ margin-top: var(--size-4);
643
+ }
634
644
  }
635
645
  }
636
646
  }
@@ -1,6 +1,7 @@
1
1
  @import "./ListItem.grid.less";
2
2
  @import "./Prompt/ListItemPrompt.less";
3
3
  @import (reference) "../../node_modules/@transferwise/neptune-css/src/less/ring.less";
4
+ @import (reference) "./ListItem.vars.less";
4
5
 
5
6
  .wds-list-item {
6
7
  list-style: none;
@@ -164,7 +165,7 @@
164
165
 
165
166
  &-body {
166
167
  grid-area: body;
167
- align-items: center;
168
+ align-items: start;
168
169
  width: 100%;
169
170
  display: grid;
170
171
  grid-template-columns: var(--wds-list-item-body-left, 1fr) var(--wds-list-item-body-right, max-content);
@@ -172,14 +173,25 @@
172
173
  word-break: break-word;
173
174
  }
174
175
 
175
- &-title, &-title-value {
176
- color: var(--color-content-primary);
176
+ &-titles,
177
+ &-value{
178
+ display: flex;
179
+ flex-direction: column;
180
+ justify-content: center;
181
+
182
+ @container (min-width: unit(@wds-list-item-cq-max + 1, px)) {
183
+ min-height: var(--wds-list-item-value-min-height, 100%);
184
+ }
177
185
  }
178
186
 
179
187
  &-value {
180
188
  text-align: right;
181
189
  }
182
190
 
191
+ &-title, &-title-value {
192
+ color: var(--color-content-primary);
193
+ }
194
+
183
195
  &-body-center {
184
196
  display: flex;
185
197
  flex-direction: row;
@@ -252,7 +264,7 @@
252
264
  }
253
265
  }
254
266
 
255
-
267
+
256
268
  }
257
269
 
258
270
  .wds-list-item-spotlight__border{
@@ -1484,6 +1484,7 @@ describe('ListItem', () => {
1484
1484
  const listItem = screen.getByRole('listitem');
1485
1485
  expect(listItem).toHaveClass('wds-list-item-interactive');
1486
1486
  expect(listItem).toHaveClass('wds-list-item-spotlight-active');
1487
+ expect(listItem.querySelector('.wds-list-item-spotlight__border')).not.toBeInTheDocument();
1487
1488
  });
1488
1489
 
1489
1490
  it('only fully interactive variant can have spotlight:inactive', () => {
@@ -1497,15 +1498,17 @@ describe('ListItem', () => {
1497
1498
  const listItem = screen.getByRole('listitem');
1498
1499
  expect(listItem).toHaveClass('wds-list-item-interactive');
1499
1500
  expect(listItem).toHaveClass('wds-list-item-spotlight-inactive');
1501
+ expect(listItem.querySelector('.wds-list-item-spotlight__border')).toBeInTheDocument();
1500
1502
  });
1501
1503
 
1502
- it('non interactive variant can have spotlight', () => {
1504
+ it('non interactive variant cannot have spotlight', () => {
1503
1505
  render(<ListItem title="Test Title" spotlight="inactive" />);
1504
1506
  const listItem = screen.getByRole('listitem');
1505
1507
  expect(listItem).toHaveClass('wds-list-item-non-interactive');
1506
1508
  expect(listItem).not.toHaveClass('wds-list-item-interactive');
1507
1509
  expect(listItem).not.toHaveClass('wds-list-item-spotlight-inactive');
1508
1510
  expect(listItem).not.toHaveClass('wds-list-item-spotlight-active');
1511
+ expect(listItem.querySelector('.wds-list-item-spotlight__border')).not.toBeInTheDocument();
1509
1512
  });
1510
1513
  });
1511
1514
  });
@@ -229,8 +229,13 @@ export const ListItem = ({
229
229
  )}
230
230
  id={id}
231
231
  aria-disabled={disabled}
232
+ style={
233
+ {
234
+ '--wds-list-item-value-min-height': mediaSize ? `${mediaSize}px` : undefined,
235
+ } as React.CSSProperties
236
+ }
232
237
  >
233
- {spotlight === 'inactive' && (
238
+ {isFullyInteractive && spotlight === 'inactive' && (
234
239
  <svg aria-hidden="true" className="wds-list-item-spotlight__border">
235
240
  <rect />
236
241
  </svg>
@@ -256,11 +261,7 @@ export const ListItem = ({
256
261
  style={valueColumnWidth ? gridColumnsStyle : undefined}
257
262
  >
258
263
  {/* Title + Subtitle + Values - Group */}
259
- <span
260
- className={clsx({
261
- 'wds-list-item-body-center': title && !subtitle,
262
- })}
263
- >
264
+ <span className="wds-list-item-titles">
264
265
  {(() => {
265
266
  const titles = [
266
267
  <Body
@@ -287,8 +288,6 @@ export const ListItem = ({
287
288
  <span
288
289
  className={clsx('wds-list-item-value', {
289
290
  'flex-column': valueTitle !== undefined || valueSubtitle !== undefined,
290
- 'wds-list-item-body-center':
291
- (valueTitle && !valueSubtitle) || (!valueTitle && valueSubtitle),
292
291
  })}
293
292
  >
294
293
  {(() => {
@@ -326,6 +325,8 @@ export const ListItem = ({
326
325
  <Body
327
326
  className={clsx('wds-list-item-control-wrapper', {
328
327
  'wds-list-item-button-control': controlType === 'button',
328
+ 'wds-list-item-button-control--hasPrompt':
329
+ controlType === 'button' && Boolean(prompt),
329
330
  })}
330
331
  style={
331
332
  {
@@ -351,7 +352,6 @@ type ViewProps = PropsWithChildren<{
351
352
 
352
353
  function View({
353
354
  children,
354
- subtitle,
355
355
  additionalInfo,
356
356
  prompt,
357
357
  disabled,
File without changes
@@ -0,0 +1,11 @@
1
+ // List item has 3 unique layouts managed through container queries:
2
+ // * width <= cq-min
3
+ // * cq-min < width <= cq-max
4
+ // * width > cq-max
5
+ //
6
+ // ⚠️ These values must be kept in sync with:
7
+ // `packages/components/src/listItem/constants.ts`
8
+ //
9
+ // @see https://storybook.wise.design/?path=/story/content-listitem--responsiveness
10
+ @wds-list-item-cq-min: 240;
11
+ @wds-list-item-cq-max: 308;
@@ -1,7 +1,5 @@
1
1
  import { Fragment } from 'react';
2
2
  import { Meta, StoryObj } from '@storybook/react-webpack5';
3
- import { Bank, FastFlag, MultiCurrency, Receipt, Savings } from '@transferwise/icons';
4
- import Link from '../../link';
5
3
  import List from '../../list';
6
4
  import { ListItem, type ListItemProps } from '../ListItem';
7
5
  import { lorem10, lorem20, lorem5 } from '../../test-utils';
@@ -9,20 +7,8 @@ import portraitImage from '../../test-utils/assets/placeholder-landscape.svg';
9
7
  import landscapeImage from '../../test-utils/assets/placeholder-portrait.svg';
10
8
  import { SB_LIST_ITEM_CONTROLS as CONTROLS, SB_LIST_ITEM_MEDIA as MEDIA } from './subcomponents';
11
9
  import { ListItemMediaSize } from '../ListItemContext';
12
-
13
- const withSizedContainer = (width: number) => (Story: any) => (
14
- <List
15
- className="list-unstyled"
16
- style={{
17
- width,
18
- display: 'flex',
19
- flexDirection: 'column',
20
- gap: 16,
21
- }}
22
- >
23
- <Story />
24
- </List>
25
- );
10
+ import { withSizedContainer } from './helpers';
11
+ import { LISTITEM_CQ } from '../constants';
26
12
 
27
13
  export default {
28
14
  title: 'Content/ListItem/tests/layout',
@@ -36,143 +22,6 @@ export default {
36
22
  } satisfies Meta<ListItemProps>;
37
23
  type Story = StoryObj<ListItemProps>;
38
24
 
39
- const variants = [
40
- <ListItem
41
- key="button"
42
- title="Button only"
43
- control={
44
- <ListItem.Button priority="secondary-neutral" onClick={() => {}}>
45
- Click me
46
- </ListItem.Button>
47
- }
48
- />,
49
- <ListItem
50
- key="media"
51
- title="With media"
52
- subtitle="Short subtitle"
53
- additionalInfo={<ListItem.AdditionalInfo>{lorem5}</ListItem.AdditionalInfo>}
54
- media={
55
- <ListItem.AvatarView>
56
- <FastFlag />
57
- </ListItem.AvatarView>
58
- }
59
- />,
60
- <ListItem key="value" title="With value" valueTitle="100 GBP" valueSubtitle="100 USD" />,
61
- <ListItem
62
- key="prompt"
63
- title="With prompt"
64
- prompt={
65
- <ListItem.Prompt sentiment="positive">
66
- This is a prompt with <Link href="https://wise.com">a link</Link>.
67
- </ListItem.Prompt>
68
- }
69
- />,
70
- <ListItem
71
- key="button-media"
72
- title="Button + media"
73
- media={
74
- <ListItem.AvatarView>
75
- <MultiCurrency />
76
- </ListItem.AvatarView>
77
- }
78
- control={
79
- <ListItem.Button priority="primary" onClick={() => {}}>
80
- Action
81
- </ListItem.Button>
82
- }
83
- />,
84
- <ListItem
85
- key="button-value"
86
- title="Button + value"
87
- valueTitle="42 EUR"
88
- control={
89
- <ListItem.Button priority="secondary-neutral" onClick={() => {}}>
90
- Pay
91
- </ListItem.Button>
92
- }
93
- />,
94
- <ListItem
95
- key="media-value"
96
- valueColumnWidth={80}
97
- title="Media + value"
98
- subtitle="this column is 20% wide"
99
- media={
100
- <ListItem.AvatarView>
101
- <Bank />
102
- </ListItem.AvatarView>
103
- }
104
- valueTitle="1,000 USD"
105
- />,
106
- <ListItem
107
- key="prompt-value"
108
- title="Prompt + value"
109
- valueTitle="10 GBP"
110
- prompt={<ListItem.Prompt sentiment="warning">Warning prompt!</ListItem.Prompt>}
111
- />,
112
- <ListItem
113
- key="media-prompt"
114
- title="Media + prompt"
115
- media={
116
- <ListItem.AvatarView>
117
- <Receipt />
118
- </ListItem.AvatarView>
119
- }
120
- prompt={<ListItem.Prompt sentiment="positive">Discount available!</ListItem.Prompt>}
121
- />,
122
- <ListItem
123
- key="most"
124
- title="Everything but button"
125
- subtitle="No control"
126
- media={
127
- <ListItem.AvatarView>
128
- <Savings />
129
- </ListItem.AvatarView>
130
- }
131
- valueTitle="999 GBP"
132
- prompt={
133
- <ListItem.Prompt sentiment="positive">
134
- <Link href="https://wise.com">See details</Link>
135
- </ListItem.Prompt>
136
- }
137
- />,
138
- <ListItem
139
- key="all"
140
- title="All together"
141
- subtitle="Everything in one"
142
- media={
143
- <ListItem.AvatarView>
144
- <Savings />
145
- </ListItem.AvatarView>
146
- }
147
- valueTitle="999 GBP"
148
- prompt={
149
- <ListItem.Prompt sentiment="positive">
150
- <Link href="https://wise.com">See details</Link>
151
- </ListItem.Prompt>
152
- }
153
- control={
154
- <ListItem.Button priority="secondary-neutral" onClick={() => {}}>
155
- Go
156
- </ListItem.Button>
157
- }
158
- />,
159
- ];
160
-
161
- export const Under320: Story = {
162
- render: () => <>{variants}</>,
163
- decorators: [withSizedContainer(320)],
164
- };
165
-
166
- export const Between321And399: Story = {
167
- render: () => <>{variants}</>,
168
- decorators: [withSizedContainer(360)],
169
- };
170
-
171
- export const Over400: Story = {
172
- render: () => <>{variants}</>,
173
- decorators: [withSizedContainer(400)],
174
- };
175
-
176
25
  export const LongButton: Story = {
177
26
  render: () => (
178
27
  <ListItem
@@ -190,7 +39,7 @@ export const LongButton: Story = {
190
39
  }
191
40
  />
192
41
  ),
193
- decorators: [withSizedContainer(400)],
42
+ decorators: [withSizedContainer(400, false)],
194
43
  };
195
44
 
196
45
  export const GapsBetweenItems: Story = {
@@ -317,7 +166,13 @@ const ImageAlignmentStory: StoryObj<PreviewStoryArgs> = {
317
166
  )}
318
167
  <List
319
168
  className="list-unstyled"
320
- style={{ display: 'grid', gridTemplateColumns: '340px 400px', gap: '16px' }}
169
+ style={{
170
+ display: 'grid',
171
+ gridTemplateColumns: [LISTITEM_CQ.MAX, LISTITEM_CQ.MAX + 10]
172
+ .map((size) => `${size}px`)
173
+ .join(' '),
174
+ gap: '16px',
175
+ }}
321
176
  >
322
177
  <Story />
323
178
  </List>
@@ -235,23 +235,16 @@ export const CopyAndPasteWithSnackbar: Story = storySourceWithoutNoise({
235
235
  },
236
236
  });
237
237
 
238
- export const Summary: Story = {
238
+ export const Summary: Story = storySourceWithoutNoise({
239
239
  parameters: {
240
240
  docs: {
241
241
  canvas: {
242
242
  sourceState: 'shown',
243
243
  },
244
244
  },
245
- backgrounds: {
246
- default: 'light',
247
- values: [
248
- { name: 'light', value: '#f8f9fa' },
249
- { name: 'dark', value: '#343a40' },
250
- ],
251
- },
252
245
  },
253
- render: () => {
254
- const listItems = (
246
+ render: function Summary() {
247
+ return (
255
248
  <List>
256
249
  <ListItem
257
250
  title="System maintenance"
@@ -327,19 +320,5 @@ export const Summary: Story = {
327
320
  />
328
321
  </List>
329
322
  );
330
- return (
331
- <>
332
- <div style={{ padding: '24px', width: '450px' }}>{listItems}</div>
333
- <div
334
- style={{
335
- padding: '24px',
336
- width: '450px',
337
- backgroundColor: 'var(--color-background-neutral)',
338
- }}
339
- >
340
- {listItems}
341
- </div>
342
- </>
343
- );
344
323
  },
345
- };
324
+ });
@@ -3,8 +3,10 @@ import { Meta, StoryObj } from '@storybook/react-webpack5';
3
3
  import { MultiCurrency, Plus } from '@transferwise/icons';
4
4
  import { lorem5, lorem10 } from '../../test-utils';
5
5
  import Emphasis from '../../emphasis';
6
+ import Link from '../../link';
6
7
  import List from '../../list';
7
8
  import { ListItem, type ListItemProps } from '../ListItem';
9
+ import { LISTITEM_CQ } from '../constants';
8
10
  import {
9
11
  SB_LIST_ITEM_CONTROLS as CONTROLS,
10
12
  SB_LIST_ITEM_ADDITIONAL_INFO as ADDITIONAL_INFO,
@@ -12,7 +14,6 @@ import {
12
14
  SB_LIST_ITEM_MEDIA as MEDIA,
13
15
  } from './subcomponents';
14
16
  import { disableControls, storySourceWithoutNoise, withoutKey } from './helpers';
15
- import Link from '../../link';
16
17
 
17
18
  const hideControls = disableControls([
18
19
  'additionalInfo',
@@ -46,7 +47,6 @@ export default {
46
47
  'ListItem.Image': ListItem.Image,
47
48
  },
48
49
  title: 'Content/ListItem',
49
- tags: ['early-access'],
50
50
  parameters: {
51
51
  docs: {
52
52
  toc: true,
@@ -274,19 +274,15 @@ export const Playground: StoryObj<PreviewStoryArgs> = {
274
274
  decorators: [withoutKey],
275
275
  };
276
276
 
277
- /**
278
- * ListItem uses container queries under the hood, which means its layout self-adjusts based on
279
- * the available space. At the 100% zoom level, these breakpoints correspond to
280
- * containers under `290px`, those between `291px and 380px`, and finally everything including
281
- * and above `381px`. <br />
282
- * This also supports high levels of zoom for assistive tech users.
283
- */
284
277
  export const Responsiveness: StoryObj<PreviewStoryArgs> = {
285
278
  parameters: {
286
279
  docs: {
287
280
  canvas: {
288
281
  sourceState: 'hidden',
289
282
  },
283
+ description: {
284
+ story: `ListItem uses container queries under the hood, which means its layout self-adjusts based on the available space. At the 100% zoom level, these breakpoints correspond to containers under \`${LISTITEM_CQ.MIN}px\`, those between \`${LISTITEM_CQ.MIN + 1}px and ${LISTITEM_CQ.MAX}px\`, and finally everything including and above \`${LISTITEM_CQ.MAX + 1}px\`.\n\nThis also supports high levels of zoom for assistive tech users.`,
285
+ },
290
286
  },
291
287
  },
292
288
  argTypes: {
@@ -311,7 +307,17 @@ export const Responsiveness: StoryObj<PreviewStoryArgs> = {
311
307
  <List
312
308
  as="ol"
313
309
  className="list-unstyled"
314
- style={{ display: 'grid', gridTemplateColumns: '290px 350px 381px', gap: 16 }}
310
+ style={{
311
+ display: 'grid',
312
+ gridTemplateColumns: [
313
+ LISTITEM_CQ.MIN,
314
+ Math.round((LISTITEM_CQ.MAX - LISTITEM_CQ.MIN) / 2 + LISTITEM_CQ.MIN),
315
+ 510,
316
+ ]
317
+ .map((width) => `${width}px`)
318
+ .join(' '),
319
+ gap: 16,
320
+ }}
315
321
  >
316
322
  <ListItem {...props} {...previewProps} />
317
323
  <ListItem {...props} {...previewProps} />
@@ -1,5 +1,6 @@
1
1
  import { StoryObj, type Decorator } from '@storybook/react-webpack5';
2
2
  import type { ListItemProps } from '../ListItem';
3
+ import { LISTITEM_CQ } from '../constants';
3
4
 
4
5
  type Story = StoryObj<ListItemProps>;
5
6
 
@@ -49,12 +50,27 @@ export const withoutKey: Decorator = (Story, { args }) => {
49
50
  };
50
51
 
51
52
  export const withSizedContainer =
52
- (width: number): Decorator =>
53
- (Story, { args }) => (
54
- <div style={{ width, border: '1px dashed #ccc', padding: '8px' }}>
55
- <Story />
56
- </div>
57
- );
53
+ (size: 'small' | 'medium' | 'large' | number = 'large', border = true): Decorator =>
54
+ (Story, { args }) => {
55
+ const width =
56
+ typeof size === 'number'
57
+ ? size
58
+ : {
59
+ small: LISTITEM_CQ.MIN,
60
+ medium: Math.round((LISTITEM_CQ.MAX - LISTITEM_CQ.MIN) / 2 + LISTITEM_CQ.MIN),
61
+ large: LISTITEM_CQ.MAX + 1,
62
+ }[size];
63
+ return (
64
+ <div
65
+ style={{
66
+ width,
67
+ border: border ? '1px dashed #ccc' : undefined,
68
+ }}
69
+ >
70
+ <Story />
71
+ </div>
72
+ );
73
+ };
58
74
 
59
75
  /**
60
76
  * Not all stories need access to all controls as it causes unnecessary UI noise.