@transferwise/components 46.166.0 → 46.168.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 (246) hide show
  1. package/README.md +1 -1
  2. package/build/CardContainer/CardContainer.js +34 -0
  3. package/build/CardContainer/CardContainer.js.map +1 -0
  4. package/build/CardContainer/CardContainer.mjs +30 -0
  5. package/build/CardContainer/CardContainer.mjs.map +1 -0
  6. package/build/CardWidget/CardWidget.js +98 -0
  7. package/build/CardWidget/CardWidget.js.map +1 -0
  8. package/build/CardWidget/CardWidget.mjs +94 -0
  9. package/build/CardWidget/CardWidget.mjs.map +1 -0
  10. package/build/CardWidget/CardWidgetAction.js +73 -0
  11. package/build/CardWidget/CardWidgetAction.js.map +1 -0
  12. package/build/CardWidget/CardWidgetAction.mjs +68 -0
  13. package/build/CardWidget/CardWidgetAction.mjs.map +1 -0
  14. package/build/Link/Link.js.map +1 -1
  15. package/build/Link/Link.mjs.map +1 -1
  16. package/build/ListItem/ListItem.js +2 -0
  17. package/build/ListItem/ListItem.js.map +1 -1
  18. package/build/ListItem/ListItem.mjs +2 -0
  19. package/build/ListItem/ListItem.mjs.map +1 -1
  20. package/build/Loader/Loader.js.map +1 -1
  21. package/build/Loader/Loader.mjs.map +1 -1
  22. package/build/Prompt/PrimitivePrompt/PrimitivePrompt.js +2 -1
  23. package/build/Prompt/PrimitivePrompt/PrimitivePrompt.js.map +1 -1
  24. package/build/Prompt/PrimitivePrompt/PrimitivePrompt.mjs +2 -1
  25. package/build/Prompt/PrimitivePrompt/PrimitivePrompt.mjs.map +1 -1
  26. package/build/Prompt/Snackbar/Snackbar.js +205 -0
  27. package/build/Prompt/Snackbar/Snackbar.js.map +1 -0
  28. package/build/Prompt/Snackbar/Snackbar.messages.js +14 -0
  29. package/build/Prompt/Snackbar/Snackbar.messages.js.map +1 -0
  30. package/build/Prompt/Snackbar/Snackbar.messages.mjs +10 -0
  31. package/build/Prompt/Snackbar/Snackbar.messages.mjs.map +1 -0
  32. package/build/Prompt/Snackbar/Snackbar.mjs +203 -0
  33. package/build/Prompt/Snackbar/Snackbar.mjs.map +1 -0
  34. package/build/Prompt/Snackbar/SnackbarContext.js.map +1 -0
  35. package/build/Prompt/Snackbar/SnackbarContext.mjs.map +1 -0
  36. package/build/Prompt/Snackbar/SnackbarPortal.js +12 -0
  37. package/build/Prompt/Snackbar/SnackbarPortal.js.map +1 -0
  38. package/build/Prompt/Snackbar/SnackbarPortal.mjs +8 -0
  39. package/build/Prompt/Snackbar/SnackbarPortal.mjs.map +1 -0
  40. package/build/Prompt/Snackbar/SnackbarProvider.js +42 -0
  41. package/build/Prompt/Snackbar/SnackbarProvider.js.map +1 -0
  42. package/build/Prompt/Snackbar/SnackbarProvider.mjs +38 -0
  43. package/build/Prompt/Snackbar/SnackbarProvider.mjs.map +1 -0
  44. package/build/Prompt/Snackbar/constants.js +17 -0
  45. package/build/Prompt/Snackbar/constants.js.map +1 -0
  46. package/build/Prompt/Snackbar/constants.mjs +11 -0
  47. package/build/Prompt/Snackbar/constants.mjs.map +1 -0
  48. package/build/Prompt/Snackbar/useSnackbar.js.map +1 -0
  49. package/build/Prompt/Snackbar/useSnackbar.mjs.map +1 -0
  50. package/build/Prompt/Snackbar/useSnackbarAutoDismiss.js +66 -0
  51. package/build/Prompt/Snackbar/useSnackbarAutoDismiss.js.map +1 -0
  52. package/build/Prompt/Snackbar/useSnackbarAutoDismiss.mjs +62 -0
  53. package/build/Prompt/Snackbar/useSnackbarAutoDismiss.mjs.map +1 -0
  54. package/build/Prompt/Snackbar/useSnackbarManager.js +153 -0
  55. package/build/Prompt/Snackbar/useSnackbarManager.js.map +1 -0
  56. package/build/Prompt/Snackbar/useSnackbarManager.mjs +149 -0
  57. package/build/Prompt/Snackbar/useSnackbarManager.mjs.map +1 -0
  58. package/build/Prompt/Snackbar/useSnackbarSwipeDismiss.js +135 -0
  59. package/build/Prompt/Snackbar/useSnackbarSwipeDismiss.js.map +1 -0
  60. package/build/Prompt/Snackbar/useSnackbarSwipeDismiss.mjs +131 -0
  61. package/build/Prompt/Snackbar/useSnackbarSwipeDismiss.mjs.map +1 -0
  62. package/build/Section/Section.js.map +1 -1
  63. package/build/Section/Section.mjs.map +1 -1
  64. package/build/_deprecated/Select/Select.js +1 -1
  65. package/build/_deprecated/Select/Select.js.map +1 -1
  66. package/build/_deprecated/Select/Select.mjs +1 -1
  67. package/build/_deprecated/Select/Select.mjs.map +1 -1
  68. package/build/common/BottomSheet/BottomSheet.js +1 -3
  69. package/build/common/BottomSheet/BottomSheet.js.map +1 -1
  70. package/build/common/BottomSheet/BottomSheet.mjs +1 -3
  71. package/build/common/BottomSheet/BottomSheet.mjs.map +1 -1
  72. package/build/i18n/en.json +1 -0
  73. package/build/i18n/en.json.js +1 -0
  74. package/build/i18n/en.json.js.map +1 -1
  75. package/build/i18n/en.json.mjs +1 -0
  76. package/build/i18n/en.json.mjs.map +1 -1
  77. package/build/index.js +7 -3
  78. package/build/index.js.map +1 -1
  79. package/build/index.mjs +5 -3
  80. package/build/index.mjs.map +1 -1
  81. package/build/main.css +331 -75
  82. package/build/styles/CardContainer/CardContainer.css +108 -0
  83. package/build/styles/CardWidget/CardWidget.css +78 -0
  84. package/build/styles/IconButton/IconButton.css +3 -4
  85. package/build/styles/ListItem/ListItem.css +8 -0
  86. package/build/styles/Prompt/Snackbar/Snackbar.css +134 -0
  87. package/build/styles/main.css +331 -75
  88. package/build/types/Body/Body.d.ts +2 -2
  89. package/build/types/CardContainer/CardContainer.d.ts +8 -0
  90. package/build/types/CardContainer/CardContainer.d.ts.map +1 -0
  91. package/build/types/CardContainer/CardContainer.types.d.ts +55 -0
  92. package/build/types/CardContainer/CardContainer.types.d.ts.map +1 -0
  93. package/build/types/CardContainer/_stories/helpers.d.ts +3 -0
  94. package/build/types/CardContainer/_stories/helpers.d.ts.map +1 -0
  95. package/build/types/CardContainer/index.d.ts +3 -0
  96. package/build/types/CardContainer/index.d.ts.map +1 -0
  97. package/build/types/CardWidget/CardWidget.d.ts +10 -0
  98. package/build/types/CardWidget/CardWidget.d.ts.map +1 -0
  99. package/build/types/CardWidget/CardWidget.types.d.ts +55 -0
  100. package/build/types/CardWidget/CardWidget.types.d.ts.map +1 -0
  101. package/build/types/CardWidget/CardWidgetAction.d.ts +54 -0
  102. package/build/types/CardWidget/CardWidgetAction.d.ts.map +1 -0
  103. package/build/types/CardWidget/index.d.ts +4 -0
  104. package/build/types/CardWidget/index.d.ts.map +1 -0
  105. package/build/types/IconButton/IconButton.d.ts +1 -1
  106. package/build/types/Link/Link.d.ts +1 -1
  107. package/build/types/ListItem/ListItem.d.ts +1 -1
  108. package/build/types/ListItem/ListItem.d.ts.map +1 -1
  109. package/build/types/Loader/Loader.d.ts +1 -1
  110. package/build/types/MoneyInput/MoneyInput.d.ts +1 -1
  111. package/build/types/MoneyInput/MoneyInput.d.ts.map +1 -1
  112. package/build/types/Prompt/PrimitivePrompt/PrimitivePrompt.d.ts +11 -0
  113. package/build/types/Prompt/PrimitivePrompt/PrimitivePrompt.d.ts.map +1 -1
  114. package/build/types/Prompt/Snackbar/Snackbar.d.ts +62 -0
  115. package/build/types/Prompt/Snackbar/Snackbar.d.ts.map +1 -0
  116. package/build/types/Prompt/Snackbar/Snackbar.messages.d.ts +9 -0
  117. package/build/types/Prompt/Snackbar/Snackbar.messages.d.ts.map +1 -0
  118. package/build/types/Prompt/Snackbar/Snackbar.types.d.ts +12 -0
  119. package/build/types/Prompt/Snackbar/Snackbar.types.d.ts.map +1 -0
  120. package/build/types/{Snackbar → Prompt/Snackbar}/SnackbarContext.d.ts +2 -2
  121. package/build/types/Prompt/Snackbar/SnackbarContext.d.ts.map +1 -0
  122. package/build/types/Prompt/Snackbar/SnackbarPortal.d.ts +4 -0
  123. package/build/types/Prompt/Snackbar/SnackbarPortal.d.ts.map +1 -0
  124. package/build/types/Prompt/Snackbar/SnackbarProvider.d.ts +13 -0
  125. package/build/types/Prompt/Snackbar/SnackbarProvider.d.ts.map +1 -0
  126. package/build/types/Prompt/Snackbar/constants.d.ts +9 -0
  127. package/build/types/Prompt/Snackbar/constants.d.ts.map +1 -0
  128. package/build/types/{Snackbar → Prompt/Snackbar}/index.d.ts +1 -1
  129. package/build/types/Prompt/Snackbar/index.d.ts.map +1 -0
  130. package/build/types/Prompt/Snackbar/useSnackbar.d.ts +3 -0
  131. package/build/types/Prompt/Snackbar/useSnackbar.d.ts.map +1 -0
  132. package/build/types/Prompt/Snackbar/useSnackbarAutoDismiss.d.ts +13 -0
  133. package/build/types/Prompt/Snackbar/useSnackbarAutoDismiss.d.ts.map +1 -0
  134. package/build/types/Prompt/Snackbar/useSnackbarManager.d.ts +20 -0
  135. package/build/types/Prompt/Snackbar/useSnackbarManager.d.ts.map +1 -0
  136. package/build/types/Prompt/Snackbar/useSnackbarSwipeDismiss.d.ts +22 -0
  137. package/build/types/Prompt/Snackbar/useSnackbarSwipeDismiss.d.ts.map +1 -0
  138. package/build/types/Section/Section.d.ts +1 -1
  139. package/build/types/Title/Title.d.ts +2 -2
  140. package/build/types/Upload/Steps/UploadImageStep/UploadImageStep.d.ts +1 -1
  141. package/build/types/UploadInput/UploadItem/UploadItemLink.d.ts +1 -1
  142. package/build/types/_deprecated/Select/Select.d.ts +1 -1
  143. package/build/types/common/BottomSheet/BottomSheet.d.ts +1 -3
  144. package/build/types/common/BottomSheet/BottomSheet.d.ts.map +1 -1
  145. package/build/types/index.d.ts +9 -5
  146. package/build/types/index.d.ts.map +1 -1
  147. package/build/types/test-utils/index.d.ts +2 -0
  148. package/build/types/test-utils/index.d.ts.map +1 -1
  149. package/package.json +4 -4
  150. package/src/CardContainer/CardContainer.css +108 -0
  151. package/src/CardContainer/CardContainer.less +171 -0
  152. package/src/CardContainer/CardContainer.test.tsx +150 -0
  153. package/src/CardContainer/CardContainer.tsx +51 -0
  154. package/src/CardContainer/CardContainer.types.ts +62 -0
  155. package/src/CardContainer/_stories/CardContainer.story.tsx +167 -0
  156. package/src/CardContainer/_stories/CardContainer.test.story.tsx +103 -0
  157. package/src/CardContainer/_stories/helpers.tsx +50 -0
  158. package/src/CardContainer/index.ts +6 -0
  159. package/src/CardWidget/CardWidget.css +78 -0
  160. package/src/CardWidget/CardWidget.less +107 -0
  161. package/src/CardWidget/CardWidget.test.tsx +221 -0
  162. package/src/CardWidget/CardWidget.tsx +78 -0
  163. package/src/CardWidget/CardWidget.types.ts +63 -0
  164. package/src/CardWidget/CardWidgetAction.tsx +128 -0
  165. package/src/CardWidget/_stories/CardWidget.story.tsx +238 -0
  166. package/src/CardWidget/_stories/CardWidget.test.story.tsx +350 -0
  167. package/src/CardWidget/index.ts +3 -0
  168. package/src/IconButton/IconButton.css +3 -4
  169. package/src/IconButton/IconButton.less +14 -1
  170. package/src/Link/Link.tsx +1 -1
  171. package/src/ListItem/AdditionalInfo/_stories/ListItemAdditionalInfo.story.tsx +1 -1
  172. package/src/ListItem/AvatarView/_stories/ListItemAvatarView.story.tsx +3 -3
  173. package/src/ListItem/ListItem.css +8 -0
  174. package/src/ListItem/ListItem.less +8 -0
  175. package/src/ListItem/ListItem.test.tsx +20 -0
  176. package/src/ListItem/ListItem.tsx +3 -1
  177. package/src/ListItem/_stories/ListItem.disabled.story.tsx +1 -1
  178. package/src/ListItem/_stories/ListItem.layout.test.story.tsx +1 -1
  179. package/src/ListItem/_stories/ListItem.scenarios.story.tsx +2 -2
  180. package/src/ListItem/_stories/ListItem.story.tsx +1 -1
  181. package/src/Loader/Loader.tsx +1 -1
  182. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.docs.mdx +122 -0
  183. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.story.tsx +0 -2
  184. package/src/Prompt/PrimitivePrompt/PrimitivePrompt.test.tsx +24 -1
  185. package/src/Prompt/PrimitivePrompt/PrimitivePrompt.tsx +8 -2
  186. package/src/Prompt/Snackbar/Snackbar.css +134 -0
  187. package/src/Prompt/Snackbar/Snackbar.less +159 -0
  188. package/src/Prompt/Snackbar/Snackbar.messages.ts +9 -0
  189. package/src/Prompt/Snackbar/Snackbar.test.tsx +1079 -0
  190. package/src/Prompt/Snackbar/Snackbar.tsx +245 -0
  191. package/src/Prompt/Snackbar/Snackbar.types.ts +17 -0
  192. package/src/{Snackbar → Prompt/Snackbar}/SnackbarContext.ts +2 -2
  193. package/src/Prompt/Snackbar/SnackbarPortal.tsx +8 -0
  194. package/src/Prompt/Snackbar/SnackbarProvider.test.tsx +783 -0
  195. package/src/Prompt/Snackbar/SnackbarProvider.tsx +41 -0
  196. package/src/Prompt/Snackbar/_stories/Snackbar.accessibility.docs.mdx +58 -0
  197. package/src/{Snackbar → Prompt/Snackbar}/_stories/Snackbar.rtl.test.story.tsx +17 -9
  198. package/src/Prompt/Snackbar/_stories/Snackbar.story.tsx +416 -0
  199. package/src/Prompt/Snackbar/_stories/Snackbar.test.story.tsx +263 -0
  200. package/src/Prompt/Snackbar/constants.ts +10 -0
  201. package/src/{Snackbar → Prompt/Snackbar}/index.ts +1 -1
  202. package/src/Prompt/Snackbar/useSnackbarAutoDismiss.ts +74 -0
  203. package/src/Prompt/Snackbar/useSnackbarManager.ts +169 -0
  204. package/src/Prompt/Snackbar/useSnackbarSwipeDismiss.ts +169 -0
  205. package/src/Section/Section.tsx +1 -1
  206. package/src/_deprecated/Select/Select.tsx +1 -1
  207. package/src/_deprecated/Select/_stories/Select.story.tsx +1 -1
  208. package/src/common/BottomSheet/BottomSheet.tsx +1 -3
  209. package/src/i18n/en.json +1 -0
  210. package/src/index.ts +18 -5
  211. package/src/main.css +331 -75
  212. package/src/main.less +3 -1
  213. package/build/Snackbar/Snackbar.js +0 -128
  214. package/build/Snackbar/Snackbar.js.map +0 -1
  215. package/build/Snackbar/Snackbar.mjs +0 -123
  216. package/build/Snackbar/Snackbar.mjs.map +0 -1
  217. package/build/Snackbar/SnackbarContext.js.map +0 -1
  218. package/build/Snackbar/SnackbarContext.mjs.map +0 -1
  219. package/build/Snackbar/SnackbarProvider.js +0 -46
  220. package/build/Snackbar/SnackbarProvider.js.map +0 -1
  221. package/build/Snackbar/SnackbarProvider.mjs +0 -42
  222. package/build/Snackbar/SnackbarProvider.mjs.map +0 -1
  223. package/build/Snackbar/useSnackbar.js.map +0 -1
  224. package/build/Snackbar/useSnackbar.mjs.map +0 -1
  225. package/build/styles/Snackbar/Snackbar.css +0 -71
  226. package/build/types/Snackbar/Snackbar.d.ts +0 -16
  227. package/build/types/Snackbar/Snackbar.d.ts.map +0 -1
  228. package/build/types/Snackbar/SnackbarContext.d.ts.map +0 -1
  229. package/build/types/Snackbar/SnackbarProvider.d.ts +0 -6
  230. package/build/types/Snackbar/SnackbarProvider.d.ts.map +0 -1
  231. package/build/types/Snackbar/index.d.ts.map +0 -1
  232. package/build/types/Snackbar/useSnackbar.d.ts +0 -3
  233. package/build/types/Snackbar/useSnackbar.d.ts.map +0 -1
  234. package/src/FlowNavigation/_stories/FlowNavigation.CriticalBanner.docs.mdx +0 -66
  235. package/src/Snackbar/Snackbar.css +0 -71
  236. package/src/Snackbar/Snackbar.less +0 -80
  237. package/src/Snackbar/Snackbar.test.tsx +0 -206
  238. package/src/Snackbar/Snackbar.tsx +0 -129
  239. package/src/Snackbar/SnackbarProvider.tsx +0 -33
  240. package/src/Snackbar/_stories/Snackbar.story.tsx +0 -89
  241. package/src/Snackbar/_stories/Snackbar.test.story.tsx +0 -139
  242. /package/build/{Snackbar → Prompt/Snackbar}/SnackbarContext.js +0 -0
  243. /package/build/{Snackbar → Prompt/Snackbar}/SnackbarContext.mjs +0 -0
  244. /package/build/{Snackbar → Prompt/Snackbar}/useSnackbar.js +0 -0
  245. /package/build/{Snackbar → Prompt/Snackbar}/useSnackbar.mjs +0 -0
  246. /package/src/{Snackbar → Prompt/Snackbar}/useSnackbar.ts +0 -0
@@ -391,6 +391,14 @@
391
391
  padding-inline: 0;
392
392
  container-type: inline-size;
393
393
  }
394
+ .wds-list-item-paddingY-8 {
395
+ padding-block: var(--size-8);
396
+ padding-inline: 0;
397
+ }
398
+ .wds-list-item-paddingY-16 {
399
+ padding-block: var(--size-16);
400
+ padding-inline: 0;
401
+ }
394
402
  .wds-list-item-paddingY-24 {
395
403
  padding-block: var(--size-24);
396
404
  padding-inline: 0;
@@ -11,6 +11,14 @@
11
11
  padding: var(--size-12) 0;
12
12
  container-type: inline-size;
13
13
 
14
+ &-paddingY-8 {
15
+ padding: var(--size-8) 0;
16
+ }
17
+
18
+ &-paddingY-16 {
19
+ padding: var(--size-16) 0;
20
+ }
21
+
14
22
  &-paddingY-24 {
15
23
  padding: var(--size-24) 0;
16
24
  }
@@ -1516,16 +1516,36 @@ describe('ListItem', () => {
1516
1516
  describe('paddingY', () => {
1517
1517
  it('uses the default vertical padding when not set', () => {
1518
1518
  render(<ListItem title="Test Title" />);
1519
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-8');
1520
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-16');
1521
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-24');
1522
+ });
1523
+
1524
+ it('uses the smaller vertical padding when set to 8', () => {
1525
+ render(<ListItem title="Test Title" paddingY={8} />);
1526
+ expect(screen.getByRole('listitem')).toHaveClass('wds-list-item-paddingY-8');
1527
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-16');
1519
1528
  expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-24');
1520
1529
  });
1521
1530
 
1522
1531
  it('uses the default vertical padding when set to 12', () => {
1523
1532
  render(<ListItem title="Test Title" paddingY={12} />);
1533
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-8');
1534
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-16');
1535
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-24');
1536
+ });
1537
+
1538
+ it('uses the medium vertical padding when set to 16', () => {
1539
+ render(<ListItem title="Test Title" paddingY={16} />);
1540
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-8');
1541
+ expect(screen.getByRole('listitem')).toHaveClass('wds-list-item-paddingY-16');
1524
1542
  expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-24');
1525
1543
  });
1526
1544
 
1527
1545
  it('uses the larger vertical padding when set to 24', () => {
1528
1546
  render(<ListItem title="Test Title" paddingY={24} />);
1547
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-8');
1548
+ expect(screen.getByRole('listitem')).not.toHaveClass('wds-list-item-paddingY-16');
1529
1549
  expect(screen.getByRole('listitem')).toHaveClass('wds-list-item-paddingY-24');
1530
1550
  });
1531
1551
  });
@@ -63,7 +63,7 @@ export type ListItemProps = {
63
63
  * Vertical padding of the list item, in pixels.
64
64
  * @default 12
65
65
  */
66
- paddingY?: 12 | 24;
66
+ paddingY?: 8 | 12 | 16 | 24;
67
67
  title: ReactNode;
68
68
  subtitle?: ReactNode;
69
69
  /**
@@ -238,6 +238,8 @@ export const ListItem = ({
238
238
  'wds-list-item-partially-interactive': isPartiallyInteractive,
239
239
  [`wds-list-item-spotlight wds-list-item-spotlight-${spotlight}`]:
240
240
  isFullyInteractive && !!spotlight,
241
+ 'wds-list-item-paddingY-8': paddingY === 8,
242
+ 'wds-list-item-paddingY-16': paddingY === 16,
241
243
  'wds-list-item-paddingY-24': paddingY === 24,
242
244
  disabled: disabled && !isPartiallyInteractive,
243
245
  'disabled--has-prompt-reason':
@@ -42,7 +42,7 @@ const disabledPromptMessage = (
42
42
  );
43
43
 
44
44
  /**
45
- * Please refer to the [design documentation](https://docs.wise.design/components/list-item#accessibility:~:text=-,Disabled%20states,-) for more details
45
+ * Please refer to the [design documentation](https://docs.wise.design/components/list-item#disabled-states) for more details
46
46
  */
47
47
  export default {
48
48
  component: ListItem,
@@ -72,7 +72,7 @@ export const PaddingY: Story = {
72
72
  };
73
73
  return (
74
74
  <List>
75
- {([12, 24] as const).map((paddingY) => (
75
+ {([8, 12, 16, 24] as const).map((paddingY) => (
76
76
  <Fragment key={paddingY}>
77
77
  <ListItem {...props} paddingY={paddingY} />
78
78
  <ListItem {...props} paddingY={paddingY} spotlight="active" />
@@ -16,8 +16,8 @@ import Modal from '../../Modal';
16
16
  import Link from '../../Link';
17
17
  import List from '../../List';
18
18
  import Popover from '../../Popover';
19
- import { SnackbarConsumer, type SnackbarContextType } from '../../Snackbar/SnackbarContext';
20
- import SnackbarProvider from '../../Snackbar/SnackbarProvider';
19
+ import { SnackbarConsumer, type SnackbarContextType } from '../../Prompt/Snackbar/SnackbarContext';
20
+ import SnackbarProvider from '../../Prompt/Snackbar/SnackbarProvider';
21
21
  import Tooltip from '../../Tooltip';
22
22
  import { Position } from '../../common';
23
23
  import { ListItem, type ListItemProps } from '../ListItem';
@@ -76,7 +76,7 @@ export default {
76
76
  },
77
77
  paddingY: {
78
78
  control: 'radio',
79
- options: ['unset (undefined)', 12, 24],
79
+ options: ['unset (undefined)', 8, 12, 16, 24],
80
80
  mapping: {
81
81
  'unset (undefined)': undefined,
82
82
  },
@@ -32,7 +32,7 @@ export type LoaderProps = {
32
32
  /**
33
33
  * Loader component
34
34
  *
35
- * Docs link: https://transferwise.github.io/neptune-web/components/progress/Loader
35
+ * Docs link: https://storybook.wise.design/?path=/docs/loading-loader--docs
36
36
  *
37
37
  * @param root0
38
38
  * @param root0.small
@@ -0,0 +1,122 @@
1
+ import { Meta, Source } from '@storybook/addon-docs/blocks';
2
+
3
+ <Meta title="Prompts/CriticalBanner/Developer Guide" tags={['new']} />
4
+
5
+ # Developer Guide
6
+
7
+ **Note:** Any usages of `Layout`, `Flow` or `HashRouterFlow` rely on the `global-critical-banner` feature flag being enabled. Whilst this flag is currently disabled in production, it's recommended to test with this flag enabled in staging, to ensure the critical banner behaves as expected for your users.
8
+
9
+ Typically `CriticalBanner` should be used in one of three ways. Pick the one that matches the page or flow you're building and avoid using CriticalBanner as a standalone component.
10
+
11
+ - `Layout` via `@transferwise/navigation-ui` - Fetched automatically from navigation-service (for non-flow layouts)
12
+ - `Flow` / `HashRouterFlow` via `@transferwise/flow` - Fetched automatically from navigation-service (for flows)
13
+ - `FlowNavigation` via `@transferwise/components` - Passed in by you through the `banner` prop (for custom solutions)
14
+
15
+ If your page uses `Layout`, `Flow` or `HashRouterFlow`, you don't need to render `CriticalBanner` yourself. These components fetch the banner, cache it and render it for you automatically.
16
+
17
+ ## Layout from @transferwise/navigation-ui
18
+
19
+ `Layout` has no banner prop. It fetches the critical banner from navigation-service on the client and renders it above the page content.
20
+
21
+ Requirements:
22
+
23
+ - `@transferwise/navigation-ui` `4.46.0` or later
24
+ - The page must use the composable layout, and `global-critical-banner` feature flags in navigation-service control this. The legacy layout doesn't render the banner.
25
+
26
+ <Source
27
+ code={`import { Layout, fetchNavigationData, type NavigationData } from '@transferwise/navigation-ui';
28
+
29
+ // Optional: fetch initial navigation data server side, so the banner cache is scoped correctly.
30
+ export const getServerSideProps = async () => {
31
+ const navigationData = await fetchNavigationData({
32
+ httpClient,
33
+ navigationServiceUrl: process.env.NAVIGATION_SERVICE_URL,
34
+ });
35
+
36
+ return { props: { navigationData } };
37
+ };
38
+
39
+ const Page = ({ navigationData }: { navigationData: NavigationData }) => (
40
+ <Layout navigationData={navigationData} onMixpanelEvent={trackEvent}>
41
+ { /* Page content */ }
42
+ </Layout>
43
+ );
44
+ `}
45
+ language="typescript"
46
+ dark
47
+ />
48
+
49
+ `Layout` also handles:
50
+
51
+ - saving the collapsed or expanded state when the user toggles the banner
52
+ - caching the banner for the session, so the entry animation only plays for new or changed banners
53
+ - sending Mixpanel events for toggles and action clicks through `onMixpanelEvent`
54
+
55
+
56
+ ## Flow / HashRouterFlow from @transferwise/flow
57
+
58
+ `Flow` and `HashRouterFlow`, from `@transferwise/flow` render `FlowNavigationWrapper` from `@transferwise/navigation-ui`. It fetches, caches and renders the critical banner the same way `Layout` does. You don't need to pass a banner, but do require `@transferwise/navigation-ui` as a dependency.
59
+
60
+ Requirements:
61
+
62
+ - `@transferwise/flow` `13.0.0` or later
63
+ - `@transferwise/navigation-ui` `4.51.0` or later, which is a required peer dependency
64
+
65
+ You can pass two optional properties in the `navigation` options:
66
+
67
+ - `navigationData`: initial navigation data, usually fetched server side, so the banner cache is scoped correctly. If you leave it out, the banner is fetched on the client.
68
+ - `onMixpanelEvent`: called when the user toggles the banner or clicks its action.
69
+
70
+ <Source
71
+ code={`import { HashRouterFlow } from '@transferwise/flow';
72
+ import type { NavigationData } from '@transferwise/navigation-ui';
73
+
74
+ const SendFlow = ({ navigationData }: { navigationData?: NavigationData }) => (
75
+ <HashRouterFlow
76
+ steps={steps}
77
+ trackEvent={trackEvent}
78
+ navigation={{
79
+ profile,
80
+ onClose,
81
+ navigationData,
82
+ onMixpanelEvent: trackEvent,
83
+ }}
84
+ />
85
+ );
86
+ `}
87
+ language="typescript"
88
+ dark
89
+ />
90
+
91
+ ## FlowNavigation from @transferwise/components
92
+
93
+ `FlowNavigation` from `@transferwise/components` renders a critical banner above the navigation when you pass a `banner` prop. Use this if you build your flow with `FlowNavigation` directly. You're responsible for getting the banner data.
94
+
95
+ `banner` accepts either:
96
+
97
+ - `CriticalBannerProps`, the same props `CriticalBanner` takes
98
+ - the legacy `CriticalBannerData` shape returned by navigation-service. `FlowNavigation` maps it to `CriticalBannerProps` for you.
99
+
100
+ <Source
101
+ code={`import { FlowNavigation, type CriticalBannerProps } from '@transferwise/components';
102
+
103
+ const banner: CriticalBannerProps = {
104
+ sentiment: 'negative',
105
+ title: 'Action required',
106
+ description: 'Please verify your identity to continue with this transfer.',
107
+ action: { label: 'Verify now', onClick: handleVerify },
108
+ };
109
+
110
+ <FlowNavigation
111
+ banner={banner}
112
+ steps={steps}
113
+ activeStep={activeStep}
114
+ avatar={avatar}
115
+ onClose={onClose}
116
+ />;
117
+ `}
118
+ language="typescript"
119
+ dark
120
+ />
121
+
122
+ Requires `@transferwise/components` `46.162.0` or later. Support for the legacy `CriticalBannerData` shape was added in `46.164.0`.
@@ -14,8 +14,6 @@ import { CriticalBanner, type CriticalBannerProps } from '..';
14
14
  * **Design guidance**: <a href="https://docs.wise.design/components/critical-banner" target="_blank">wise.design/components/critical-banner</a>
15
15
  *
16
16
  * Can be controlled or uncontrolled. When `onToggle` is provided, the consumer manages the expanded state via `expanded` and the banner calls `onToggle` when the user clicks the chevron. When `onToggle` is not provided, the banner manages its own expanded state internally and toggles it when the user clicks the chevron.
17
- *
18
- * **Using with FlowNavigation**: See the [FlowNavigation Critical Banner Guide](?path=/docs/navigation-flownavigation-critical-banner-guide--docs) for integration patterns and data mapping examples.
19
17
  */
20
18
  const meta = {
21
19
  component: CriticalBanner,
@@ -74,7 +74,30 @@ describe('PrimitivePrompt', () => {
74
74
  const onDismiss = jest.fn();
75
75
  render(<PrimitivePrompt {...defaultProps} onDismiss={onDismiss} />);
76
76
 
77
- expect(screen.getByLabelText('Close')).toBeInTheDocument();
77
+ expect(screen.getByRole('button', { name: 'Close' })).toHaveClass(
78
+ 'np-icon-button-secondary-default',
79
+ );
80
+ });
81
+
82
+ it('supports a minimal dismiss button without changing its accessible name or handler', async () => {
83
+ const onDismiss = jest.fn();
84
+ const user = userEvent.setup();
85
+ render(
86
+ <PrimitivePrompt
87
+ {...defaultProps}
88
+ dismissButtonPriority="minimal"
89
+ data-testid="prompt"
90
+ onDismiss={onDismiss}
91
+ />,
92
+ );
93
+
94
+ const dismissButton = screen.getByRole('button', { name: 'Close' });
95
+ expect(dismissButton).toHaveClass('np-icon-button-minimal-default');
96
+ expect(screen.getByTestId('prompt')).not.toHaveAttribute('dismissButtonPriority');
97
+
98
+ await user.click(dismissButton);
99
+
100
+ expect(onDismiss).toHaveBeenCalledTimes(1);
78
101
  });
79
102
 
80
103
  it('calls onDismiss when dismiss button is clicked', async () => {
@@ -1,7 +1,7 @@
1
1
  import { Cross } from '@transferwise/icons';
2
2
  import { clsx } from 'clsx';
3
3
  import SentimentSurface, { Emphasis, Sentiment } from '../../SentimentSurface';
4
- import IconButton from '../../IconButton';
4
+ import IconButton, { type IconButtonProps } from '../../IconButton';
5
5
  import { useIntl } from 'react-intl';
6
6
  import closeBtnMessages from '../../common/CloseButton/CloseButton.messages';
7
7
  import { forwardRef, HTMLAttributes, ReactNode } from 'react';
@@ -29,6 +29,11 @@ export type PrimitivePromptProps = HTMLAttributes<HTMLDivElement> & {
29
29
  * Handler called when the close button is clicked. If not provided, then the close button is hidden.
30
30
  */
31
31
  onDismiss?: () => void;
32
+ /**
33
+ * The priority of the dismiss IconButton.
34
+ * @default 'secondary'
35
+ */
36
+ dismissButtonPriority?: IconButtonProps['priority'];
32
37
  /**
33
38
  * Test ID for testing tools
34
39
  */
@@ -46,6 +51,7 @@ export const PrimitivePrompt = forwardRef<HTMLDivElement, PrimitivePromptProps>(
46
51
  media,
47
52
  actions,
48
53
  onDismiss,
54
+ dismissButtonPriority = 'secondary',
49
55
  className,
50
56
  children,
51
57
  ...restProps
@@ -73,7 +79,7 @@ export const PrimitivePrompt = forwardRef<HTMLDivElement, PrimitivePromptProps>(
73
79
  {onDismiss && (
74
80
  <IconButton
75
81
  size={24}
76
- priority="secondary"
82
+ priority={dismissButtonPriority}
77
83
  aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}
78
84
  className="wds-prompt__dismiss"
79
85
  onClick={onDismiss}
@@ -0,0 +1,134 @@
1
+ .wds-Snackbar {
2
+ display: flex;
3
+ justify-content: center;
4
+ box-sizing: border-box;
5
+ padding-inline: var(--size-16);
6
+ padding-block-end: calc(var(--size-16) + env(safe-area-inset-bottom));
7
+ position: fixed;
8
+ inset-block-end: 0;
9
+ inset-inline: 0;
10
+ z-index: 1060;
11
+ }
12
+ @media (min-width: 600px) {
13
+ .wds-Snackbar {
14
+ padding-block-end: var(--size-24);
15
+ }
16
+ }
17
+ .wds-Snackbar--swipe-dismiss {
18
+ transition: transform var(--Snackbar-exit-duration) cubic-bezier(1, 0, 1, 1);
19
+ }
20
+ .wds-Snackbar--swipe-settle {
21
+ transition: transform var(--Snackbar-exit-duration) cubic-bezier(0, 0, 0, 1);
22
+ }
23
+ .wds-Snackbar-container {
24
+ --Prompt-border-radius: var(--radius-medium);
25
+ --Prompt-gap: var(--size-8);
26
+ --Prompt-padding-x: var(--size-12);
27
+ --Prompt-padding-y: var(--size-12);
28
+ box-sizing: border-box;
29
+ max-inline-size: 480px;
30
+ text-align: start;
31
+ cursor: grab;
32
+ touch-action: pan-x pinch-zoom;
33
+ }
34
+ .wds-Snackbar-container .wds-prompt__content-wrapper--with-dismiss {
35
+ grid-template-columns: auto minmax(0, 1fr);
36
+ }
37
+ @media (min-width: 600px) {
38
+ .wds-Snackbar-container .wds-prompt__content-wrapper--with-dismiss {
39
+ grid-template-columns: auto minmax(0, 1fr) auto;
40
+ }
41
+ }
42
+ .wds-Snackbar-container .wds-prompt__media-wrapper {
43
+ display: flex;
44
+ align-items: center;
45
+ min-block-size: max(var(--size-32), 1lh);
46
+ padding-block-start: 0;
47
+ color: var(--color-sentiment-content-primary);
48
+ }
49
+ .wds-Snackbar-container .wds-prompt__media-wrapper:has(+ .wds-Snackbar__content .wds-Snackbar__action) {
50
+ min-block-size: max(var(--size-32), calc(1lh + var(--size-5) * 2));
51
+ }
52
+ .wds-Snackbar__media-asset {
53
+ display: flex;
54
+ }
55
+ .wds-Snackbar__media-asset svg {
56
+ inline-size: var(--size-24);
57
+ block-size: var(--size-24);
58
+ }
59
+ .wds-Snackbar__process-indicator .process-circle {
60
+ stroke: currentColor;
61
+ }
62
+ .wds-Snackbar-container .wds-prompt__dismiss {
63
+ display: none;
64
+ align-self: flex-start;
65
+ margin-block-start: calc(var(--size-4) - 1px);
66
+ }
67
+ @media (min-width: 600px) {
68
+ .wds-Snackbar-container .wds-prompt__dismiss {
69
+ display: flex;
70
+ }
71
+ }
72
+ .wds-Snackbar__action {
73
+ flex-shrink: 0;
74
+ }
75
+ .wds-Snackbar__content {
76
+ display: flex;
77
+ align-items: flex-start;
78
+ gap: var(--size-8);
79
+ flex: 1 0 0;
80
+ min-block-size: var(--size-32);
81
+ min-inline-size: 0;
82
+ }
83
+ .wds-Snackbar__message {
84
+ display: flex;
85
+ flex-direction: column;
86
+ justify-content: center;
87
+ inline-size: auto;
88
+ flex: 1 0 0;
89
+ min-inline-size: 0;
90
+ align-self: stretch;
91
+ }
92
+ .wds-Snackbar__body {
93
+ display: block;
94
+ }
95
+ .wds-Snackbar-container-appear,
96
+ .wds-Snackbar-container-enter {
97
+ opacity: 0;
98
+ transform: translateY(80px) scale(0.5);
99
+ }
100
+ .wds-Snackbar-container-appear-active,
101
+ .wds-Snackbar-container-enter-active {
102
+ opacity: 1;
103
+ transform: translateY(0) scale(1);
104
+ transition: opacity 150ms linear, transform var(--Snackbar-enter-duration) cubic-bezier(0, 0, 0, 1);
105
+ }
106
+ .wds-Snackbar-container-exit {
107
+ opacity: 1;
108
+ transform: translateY(0) scale(1);
109
+ }
110
+ .wds-Snackbar-container-exit-active {
111
+ opacity: 0;
112
+ transform: translateY(80px) scale(0.5);
113
+ transition: opacity 50ms linear 50ms, transform var(--Snackbar-exit-duration) cubic-bezier(1, 0, 1, 1);
114
+ }
115
+ @media (prefers-reduced-motion: reduce) {
116
+ .wds-Snackbar--swipe-dismiss,
117
+ .wds-Snackbar--swipe-settle {
118
+ transition: none;
119
+ }
120
+ .wds-Snackbar-container-appear,
121
+ .wds-Snackbar-container-appear-active,
122
+ .wds-Snackbar-container-enter,
123
+ .wds-Snackbar-container-enter-active,
124
+ .wds-Snackbar-container-exit {
125
+ opacity: 1;
126
+ transform: none;
127
+ transition: none;
128
+ }
129
+ .wds-Snackbar-container-exit-active {
130
+ opacity: 0;
131
+ transform: none;
132
+ transition: none;
133
+ }
134
+ }
@@ -0,0 +1,159 @@
1
+ @import (reference) "./../../styles/variables/zindex.less";
2
+
3
+ .wds-Snackbar {
4
+ display: flex;
5
+ justify-content: center;
6
+ box-sizing: border-box;
7
+ padding-inline: var(--size-16);
8
+ padding-bottom: calc(var(--size-16) + env(safe-area-inset-bottom));
9
+ position: fixed;
10
+ bottom: 0;
11
+ inset-inline: 0;
12
+ z-index: @zindex-mobile-nav;
13
+
14
+ @media (--screen-sm) {
15
+ padding-bottom: var(--size-24);
16
+ }
17
+
18
+ &--swipe-dismiss {
19
+ transition: transform var(--Snackbar-exit-duration) cubic-bezier(1, 0, 1, 1);
20
+ }
21
+
22
+ &--swipe-settle {
23
+ transition: transform var(--Snackbar-exit-duration) cubic-bezier(0, 0, 0, 1);
24
+ }
25
+
26
+ &-container {
27
+ --Prompt-border-radius: var(--radius-medium);
28
+ --Prompt-gap: var(--size-8);
29
+ --Prompt-padding-x: var(--size-12);
30
+ --Prompt-padding-y: var(--size-12);
31
+ box-sizing: border-box;
32
+ max-width: 480px;
33
+ text-align: start;
34
+ cursor: grab;
35
+ touch-action: pan-x pinch-zoom;
36
+ }
37
+
38
+ &-container .wds-prompt__content-wrapper--with-dismiss {
39
+ grid-template-columns: auto minmax(0, 1fr);
40
+
41
+ @media (--screen-sm) {
42
+ grid-template-columns: auto minmax(0, 1fr) auto;
43
+ }
44
+ }
45
+
46
+ &-container .wds-prompt__media-wrapper {
47
+ display: flex;
48
+ align-items: center;
49
+ min-height: max(var(--size-32), 1lh);
50
+ padding-top: 0;
51
+ color: var(--color-sentiment-content-primary);
52
+
53
+ // At 400% reflow spacing shrinks, but the text's line height does not.
54
+ &:has(+ .wds-Snackbar__content .wds-Snackbar__action) {
55
+ min-height: max(var(--size-32), calc(1lh + var(--size-5) * 2));
56
+ }
57
+ }
58
+
59
+ &__media-asset {
60
+ display: flex;
61
+
62
+ svg {
63
+ width: var(--size-24);
64
+ height: var(--size-24);
65
+ }
66
+ }
67
+
68
+ &__process-indicator .process-circle {
69
+ stroke: currentColor;
70
+ }
71
+
72
+ &-container .wds-prompt__dismiss {
73
+ display: none;
74
+ align-self: flex-start;
75
+ margin-top: calc(var(--size-4) - 1px);
76
+
77
+ @media (--screen-sm) {
78
+ display: flex;
79
+ }
80
+ }
81
+
82
+ &__action {
83
+ flex-shrink: 0;
84
+ }
85
+
86
+ &__content {
87
+ display: flex;
88
+ align-items: flex-start;
89
+ gap: var(--size-8);
90
+ flex: 1 0 0;
91
+ min-height: var(--size-32);
92
+ min-width: 0;
93
+ }
94
+
95
+ &__message {
96
+ display: flex;
97
+ flex-direction: column;
98
+ justify-content: center;
99
+ width: auto;
100
+ flex: 1 0 0;
101
+ min-width: 0;
102
+ align-self: stretch;
103
+ }
104
+
105
+ &__body {
106
+ display: block;
107
+ }
108
+ }
109
+
110
+ .wds-Snackbar-container-appear,
111
+ .wds-Snackbar-container-enter {
112
+ opacity: 0;
113
+ transform: translateY(80px) scale(0.5);
114
+ }
115
+
116
+ .wds-Snackbar-container-appear-active,
117
+ .wds-Snackbar-container-enter-active {
118
+ opacity: 1;
119
+ transform: translateY(0) scale(1);
120
+ transition:
121
+ opacity 150ms linear,
122
+ transform var(--Snackbar-enter-duration) cubic-bezier(0, 0, 0, 1);
123
+ }
124
+
125
+ .wds-Snackbar-container-exit {
126
+ opacity: 1;
127
+ transform: translateY(0) scale(1);
128
+ }
129
+
130
+ .wds-Snackbar-container-exit-active {
131
+ opacity: 0;
132
+ transform: translateY(80px) scale(0.5);
133
+ transition:
134
+ opacity 50ms linear 50ms,
135
+ transform var(--Snackbar-exit-duration) cubic-bezier(1, 0, 1, 1);
136
+ }
137
+
138
+ @media (prefers-reduced-motion: reduce) {
139
+ .wds-Snackbar--swipe-dismiss,
140
+ .wds-Snackbar--swipe-settle {
141
+ transition: none;
142
+ }
143
+
144
+ .wds-Snackbar-container-appear,
145
+ .wds-Snackbar-container-appear-active,
146
+ .wds-Snackbar-container-enter,
147
+ .wds-Snackbar-container-enter-active,
148
+ .wds-Snackbar-container-exit {
149
+ opacity: 1;
150
+ transform: none;
151
+ transition: none;
152
+ }
153
+
154
+ .wds-Snackbar-container-exit-active {
155
+ opacity: 0;
156
+ transform: none;
157
+ transition: none;
158
+ }
159
+ }
@@ -0,0 +1,9 @@
1
+ import { defineMessages } from 'react-intl';
2
+
3
+ export default defineMessages({
4
+ escapeDismissHint: {
5
+ id: 'neptune.Snackbar.escapeDismissHint',
6
+ defaultMessage: 'Press Escape to dismiss.',
7
+ description: 'Screen-reader instruction for dismissing a Snackbar without moving focus',
8
+ },
9
+ });