@transferwise/components 0.0.0-experimental-29d0f94 → 0.0.0-experimental-4b1de0a

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 (319) hide show
  1. package/build/button/Button.js +1 -0
  2. package/build/button/Button.js.map +1 -1
  3. package/build/button/Button.mjs +1 -0
  4. package/build/button/Button.mjs.map +1 -1
  5. package/build/common/RadioButton/RadioButton.js +5 -2
  6. package/build/common/RadioButton/RadioButton.js.map +1 -1
  7. package/build/common/RadioButton/RadioButton.mjs +5 -2
  8. package/build/common/RadioButton/RadioButton.mjs.map +1 -1
  9. package/build/common/initials.js +1 -4
  10. package/build/common/initials.js.map +1 -1
  11. package/build/common/initials.mjs +1 -4
  12. package/build/common/initials.mjs.map +1 -1
  13. package/build/i18n/de.json +0 -2
  14. package/build/i18n/de.json.js +0 -2
  15. package/build/i18n/de.json.js.map +1 -1
  16. package/build/i18n/de.json.mjs +0 -2
  17. package/build/i18n/de.json.mjs.map +1 -1
  18. package/build/i18n/fr.json +0 -2
  19. package/build/i18n/fr.json.js +0 -2
  20. package/build/i18n/fr.json.js.map +1 -1
  21. package/build/i18n/fr.json.mjs +0 -2
  22. package/build/i18n/fr.json.mjs.map +1 -1
  23. package/build/i18n/hu.json +0 -2
  24. package/build/i18n/hu.json.js +0 -2
  25. package/build/i18n/hu.json.js.map +1 -1
  26. package/build/i18n/hu.json.mjs +0 -2
  27. package/build/i18n/hu.json.mjs.map +1 -1
  28. package/build/i18n/it.json +0 -2
  29. package/build/i18n/it.json.js +0 -2
  30. package/build/i18n/it.json.js.map +1 -1
  31. package/build/i18n/it.json.mjs +0 -2
  32. package/build/i18n/it.json.mjs.map +1 -1
  33. package/build/i18n/ja.json +0 -2
  34. package/build/i18n/ja.json.js +0 -2
  35. package/build/i18n/ja.json.js.map +1 -1
  36. package/build/i18n/ja.json.mjs +0 -2
  37. package/build/i18n/ja.json.mjs.map +1 -1
  38. package/build/i18n/pl.json +0 -2
  39. package/build/i18n/pl.json.js +0 -2
  40. package/build/i18n/pl.json.js.map +1 -1
  41. package/build/i18n/pl.json.mjs +0 -2
  42. package/build/i18n/pl.json.mjs.map +1 -1
  43. package/build/i18n/ro.json +0 -2
  44. package/build/i18n/ro.json.js +0 -2
  45. package/build/i18n/ro.json.js.map +1 -1
  46. package/build/i18n/ro.json.mjs +0 -2
  47. package/build/i18n/ro.json.mjs.map +1 -1
  48. package/build/i18n/ru.json +0 -2
  49. package/build/i18n/ru.json.js +0 -2
  50. package/build/i18n/ru.json.js.map +1 -1
  51. package/build/i18n/ru.json.mjs +0 -2
  52. package/build/i18n/ru.json.mjs.map +1 -1
  53. package/build/i18n/tr.json +0 -2
  54. package/build/i18n/tr.json.js +0 -2
  55. package/build/i18n/tr.json.js.map +1 -1
  56. package/build/i18n/tr.json.mjs +0 -2
  57. package/build/i18n/tr.json.mjs.map +1 -1
  58. package/build/i18n/zh-CN.json +0 -2
  59. package/build/i18n/zh-CN.json.js +0 -2
  60. package/build/i18n/zh-CN.json.js.map +1 -1
  61. package/build/i18n/zh-CN.json.mjs +0 -2
  62. package/build/i18n/zh-CN.json.mjs.map +1 -1
  63. package/build/i18n/zh-HK.json +0 -2
  64. package/build/i18n/zh-HK.json.js +0 -2
  65. package/build/i18n/zh-HK.json.js.map +1 -1
  66. package/build/i18n/zh-HK.json.mjs +0 -2
  67. package/build/i18n/zh-HK.json.mjs.map +1 -1
  68. package/build/iconButton/IconButton.js.map +1 -1
  69. package/build/iconButton/IconButton.mjs.map +1 -1
  70. package/build/image/Image.js.map +1 -1
  71. package/build/image/Image.mjs.map +1 -1
  72. package/build/index.js +2 -0
  73. package/build/index.js.map +1 -1
  74. package/build/index.mjs +1 -0
  75. package/build/index.mjs.map +1 -1
  76. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js +56 -0
  77. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js.map +1 -0
  78. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs +54 -0
  79. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs.map +1 -0
  80. package/build/listItem/AvatarLayout/ListItemAvatarLayout.js +23 -0
  81. package/build/listItem/AvatarLayout/ListItemAvatarLayout.js.map +1 -0
  82. package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs +21 -0
  83. package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs.map +1 -0
  84. package/build/listItem/AvatarView/ListItemAvatarView.js +23 -0
  85. package/build/listItem/AvatarView/ListItemAvatarView.js.map +1 -0
  86. package/build/listItem/AvatarView/ListItemAvatarView.mjs +21 -0
  87. package/build/listItem/AvatarView/ListItemAvatarView.mjs.map +1 -0
  88. package/build/listItem/Button/ListItemButton.js +43 -0
  89. package/build/listItem/Button/ListItemButton.js.map +1 -0
  90. package/build/listItem/Button/ListItemButton.mjs +41 -0
  91. package/build/listItem/Button/ListItemButton.mjs.map +1 -0
  92. package/build/listItem/Checkbox/ListItemCheckbox.js +30 -0
  93. package/build/listItem/Checkbox/ListItemCheckbox.js.map +1 -0
  94. package/build/listItem/Checkbox/ListItemCheckbox.mjs +28 -0
  95. package/build/listItem/Checkbox/ListItemCheckbox.mjs.map +1 -0
  96. package/build/listItem/IconButton/ListItemIconButton.js +42 -0
  97. package/build/listItem/IconButton/ListItemIconButton.js.map +1 -0
  98. package/build/listItem/IconButton/ListItemIconButton.mjs +40 -0
  99. package/build/listItem/IconButton/ListItemIconButton.mjs.map +1 -0
  100. package/build/listItem/Image/ListItemImage.js +31 -0
  101. package/build/listItem/Image/ListItemImage.js.map +1 -0
  102. package/build/listItem/Image/ListItemImage.mjs +29 -0
  103. package/build/listItem/Image/ListItemImage.mjs.map +1 -0
  104. package/build/listItem/ListItem.js +312 -0
  105. package/build/listItem/ListItem.js.map +1 -0
  106. package/build/listItem/ListItem.mjs +307 -0
  107. package/build/listItem/ListItem.mjs.map +1 -0
  108. package/build/listItem/ListItemContext.js +8 -0
  109. package/build/listItem/ListItemContext.js.map +1 -0
  110. package/build/listItem/ListItemContext.mjs +6 -0
  111. package/build/listItem/ListItemContext.mjs.map +1 -0
  112. package/build/listItem/Navigation/ListItemNavigation.js +45 -0
  113. package/build/listItem/Navigation/ListItemNavigation.js.map +1 -0
  114. package/build/listItem/Navigation/ListItemNavigation.mjs +43 -0
  115. package/build/listItem/Navigation/ListItemNavigation.mjs.map +1 -0
  116. package/build/listItem/Prompt/ListItemPrompt.js +59 -0
  117. package/build/listItem/Prompt/ListItemPrompt.js.map +1 -0
  118. package/build/listItem/Prompt/ListItemPrompt.mjs +54 -0
  119. package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -0
  120. package/build/listItem/Radio/ListItemRadio.js +30 -0
  121. package/build/listItem/Radio/ListItemRadio.js.map +1 -0
  122. package/build/listItem/Radio/ListItemRadio.mjs +28 -0
  123. package/build/listItem/Radio/ListItemRadio.mjs.map +1 -0
  124. package/build/listItem/Switch/ListItemSwitch.js +30 -0
  125. package/build/listItem/Switch/ListItemSwitch.js.map +1 -0
  126. package/build/listItem/Switch/ListItemSwitch.mjs +28 -0
  127. package/build/listItem/Switch/ListItemSwitch.mjs.map +1 -0
  128. package/build/listItem/useListItemControl.js +22 -0
  129. package/build/listItem/useListItemControl.js.map +1 -0
  130. package/build/listItem/useListItemControl.mjs +20 -0
  131. package/build/listItem/useListItemControl.mjs.map +1 -0
  132. package/build/listItem/useListItemMedia.js +21 -0
  133. package/build/listItem/useListItemMedia.js.map +1 -0
  134. package/build/listItem/useListItemMedia.mjs +19 -0
  135. package/build/listItem/useListItemMedia.mjs.map +1 -0
  136. package/build/main.css +773 -1
  137. package/build/styles/avatarView/AvatarView.css +3 -1
  138. package/build/styles/listItem/ListItem.css +770 -0
  139. package/build/styles/listItem/ListItem.grid.css +370 -0
  140. package/build/styles/main.css +773 -1
  141. package/build/switch/Switch.js +2 -0
  142. package/build/switch/Switch.js.map +1 -1
  143. package/build/switch/Switch.mjs +2 -0
  144. package/build/switch/Switch.mjs.map +1 -1
  145. package/build/test-utils/assets/placeholder-landscape.svg +1 -0
  146. package/build/test-utils/assets/placeholder-portrait.svg +1 -0
  147. package/build/types/button/Button.d.ts.map +1 -1
  148. package/build/types/button/Button.types.d.ts +1 -1
  149. package/build/types/button/Button.types.d.ts.map +1 -1
  150. package/build/types/button/index.d.ts +1 -1
  151. package/build/types/button/index.d.ts.map +1 -1
  152. package/build/types/common/RadioButton/RadioButton.d.ts +3 -1
  153. package/build/types/common/RadioButton/RadioButton.d.ts.map +1 -1
  154. package/build/types/common/initials.d.ts.map +1 -1
  155. package/build/types/iconButton/IconButton.d.ts +2 -2
  156. package/build/types/iconButton/IconButton.d.ts.map +1 -1
  157. package/build/types/image/Image.d.ts +3 -0
  158. package/build/types/image/Image.d.ts.map +1 -1
  159. package/build/types/image/index.d.ts +1 -0
  160. package/build/types/image/index.d.ts.map +1 -1
  161. package/build/types/index.d.ts +2 -0
  162. package/build/types/index.d.ts.map +1 -1
  163. package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts +15 -0
  164. package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts.map +1 -0
  165. package/build/types/listItem/AdditionalInfo/index.d.ts +3 -0
  166. package/build/types/listItem/AdditionalInfo/index.d.ts.map +1 -0
  167. package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts +18 -0
  168. package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts.map +1 -0
  169. package/build/types/listItem/AvatarLayout/index.d.ts +3 -0
  170. package/build/types/listItem/AvatarLayout/index.d.ts.map +1 -0
  171. package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts +16 -0
  172. package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts.map +1 -0
  173. package/build/types/listItem/AvatarView/index.d.ts +3 -0
  174. package/build/types/listItem/AvatarView/index.d.ts.map +1 -0
  175. package/build/types/listItem/Button/ListItemButton.d.ts +20 -0
  176. package/build/types/listItem/Button/ListItemButton.d.ts.map +1 -0
  177. package/build/types/listItem/Button/index.d.ts +3 -0
  178. package/build/types/listItem/Button/index.d.ts.map +1 -0
  179. package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts +14 -0
  180. package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts.map +1 -0
  181. package/build/types/listItem/Checkbox/index.d.ts +3 -0
  182. package/build/types/listItem/Checkbox/index.d.ts.map +1 -0
  183. package/build/types/listItem/IconButton/ListItemIconButton.d.ts +18 -0
  184. package/build/types/listItem/IconButton/ListItemIconButton.d.ts.map +1 -0
  185. package/build/types/listItem/IconButton/index.d.ts +3 -0
  186. package/build/types/listItem/IconButton/index.d.ts.map +1 -0
  187. package/build/types/listItem/Image/ListItemImage.d.ts +25 -0
  188. package/build/types/listItem/Image/ListItemImage.d.ts.map +1 -0
  189. package/build/types/listItem/Image/index.d.ts +3 -0
  190. package/build/types/listItem/Image/index.d.ts.map +1 -0
  191. package/build/types/listItem/ListItem.d.ts +113 -0
  192. package/build/types/listItem/ListItem.d.ts.map +1 -0
  193. package/build/types/listItem/ListItemContext.d.ts +22 -0
  194. package/build/types/listItem/ListItemContext.d.ts.map +1 -0
  195. package/build/types/listItem/Navigation/ListItemNavigation.d.ts +15 -0
  196. package/build/types/listItem/Navigation/ListItemNavigation.d.ts.map +1 -0
  197. package/build/types/listItem/Navigation/index.d.ts +3 -0
  198. package/build/types/listItem/Navigation/index.d.ts.map +1 -0
  199. package/build/types/listItem/Prompt/ListItemPrompt.d.ts +16 -0
  200. package/build/types/listItem/Prompt/ListItemPrompt.d.ts.map +1 -0
  201. package/build/types/listItem/Prompt/index.d.ts +3 -0
  202. package/build/types/listItem/Prompt/index.d.ts.map +1 -0
  203. package/build/types/listItem/Radio/ListItemRadio.d.ts +14 -0
  204. package/build/types/listItem/Radio/ListItemRadio.d.ts.map +1 -0
  205. package/build/types/listItem/Radio/index.d.ts +3 -0
  206. package/build/types/listItem/Radio/index.d.ts.map +1 -0
  207. package/build/types/listItem/Switch/ListItemSwitch.d.ts +14 -0
  208. package/build/types/listItem/Switch/ListItemSwitch.d.ts.map +1 -0
  209. package/build/types/listItem/Switch/index.d.ts +3 -0
  210. package/build/types/listItem/Switch/index.d.ts.map +1 -0
  211. package/build/types/listItem/_stories/helpers.d.ts +27 -0
  212. package/build/types/listItem/_stories/helpers.d.ts.map +1 -0
  213. package/build/types/listItem/_stories/subcomponents.d.ts +18 -0
  214. package/build/types/listItem/_stories/subcomponents.d.ts.map +1 -0
  215. package/build/types/listItem/index.d.ts +14 -0
  216. package/build/types/listItem/index.d.ts.map +1 -0
  217. package/build/types/listItem/test-utils.d.ts +7 -0
  218. package/build/types/listItem/test-utils.d.ts.map +1 -0
  219. package/build/types/listItem/useListItemControl.d.ts +5 -0
  220. package/build/types/listItem/useListItemControl.d.ts.map +1 -0
  221. package/build/types/listItem/useListItemMedia.d.ts +6 -0
  222. package/build/types/listItem/useListItemMedia.d.ts.map +1 -0
  223. package/build/types/switch/Switch.d.ts +3 -1
  224. package/build/types/switch/Switch.d.ts.map +1 -1
  225. package/package.json +4 -4
  226. package/src/avatarView/AvatarView.css +3 -1
  227. package/src/avatarView/AvatarView.less +2 -1
  228. package/src/button/Button.spec.tsx +18 -0
  229. package/src/button/Button.tsx +5 -1
  230. package/src/button/Button.types.ts +1 -1
  231. package/src/button/index.ts +1 -1
  232. package/src/checkboxButton/CheckboxButton.story.tsx +4 -4
  233. package/src/common/RadioButton/RadioButton.tsx +6 -1
  234. package/src/common/initials.spec.tsx +0 -13
  235. package/src/common/initials.ts +0 -5
  236. package/src/i18n/de.json +0 -2
  237. package/src/i18n/fr.json +0 -2
  238. package/src/i18n/hu.json +0 -2
  239. package/src/i18n/it.json +0 -2
  240. package/src/i18n/ja.json +0 -2
  241. package/src/i18n/pl.json +0 -2
  242. package/src/i18n/ro.json +0 -2
  243. package/src/i18n/ru.json +0 -2
  244. package/src/i18n/tr.json +0 -2
  245. package/src/i18n/zh-CN.json +0 -2
  246. package/src/i18n/zh-HK.json +0 -2
  247. package/src/iconButton/IconButton.story.tsx +1 -1
  248. package/src/iconButton/IconButton.tsx +1 -1
  249. package/src/image/Image.tsx +3 -0
  250. package/src/image/index.ts +1 -0
  251. package/src/index.ts +2 -0
  252. package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.spec.tsx +56 -0
  253. package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.story.tsx +195 -0
  254. package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.tsx +36 -0
  255. package/src/listItem/AdditionalInfo/index.ts +2 -0
  256. package/src/listItem/AvatarLayout/ListItemAvatarLayout.spec.tsx +59 -0
  257. package/src/listItem/AvatarLayout/ListItemAvatarLayout.story.tsx +121 -0
  258. package/src/listItem/AvatarLayout/ListItemAvatarLayout.tsx +27 -0
  259. package/src/listItem/AvatarLayout/index.ts +2 -0
  260. package/src/listItem/AvatarView/ListItemAvatarView.spec.tsx +75 -0
  261. package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +336 -0
  262. package/src/listItem/AvatarView/ListItemAvatarView.tsx +27 -0
  263. package/src/listItem/AvatarView/index.ts +2 -0
  264. package/src/listItem/Button/ListItemButton.spec.tsx +68 -0
  265. package/src/listItem/Button/ListItemButton.story.tsx +466 -0
  266. package/src/listItem/Button/ListItemButton.tsx +56 -0
  267. package/src/listItem/Button/index.ts +2 -0
  268. package/src/listItem/Checkbox/ListItemCheckbox.spec.tsx +82 -0
  269. package/src/listItem/Checkbox/ListItemCheckbox.story.tsx +125 -0
  270. package/src/listItem/Checkbox/ListItemCheckbox.tsx +33 -0
  271. package/src/listItem/Checkbox/index.ts +2 -0
  272. package/src/listItem/IconButton/ListItemIconButton.spec.tsx +119 -0
  273. package/src/listItem/IconButton/ListItemIconButton.story.tsx +249 -0
  274. package/src/listItem/IconButton/ListItemIconButton.tsx +56 -0
  275. package/src/listItem/IconButton/index.ts +2 -0
  276. package/src/listItem/Image/ListItemImage.spec.tsx +30 -0
  277. package/src/listItem/Image/ListItemImage.story.tsx +77 -0
  278. package/src/listItem/Image/ListItemImage.tsx +48 -0
  279. package/src/listItem/Image/index.ts +2 -0
  280. package/src/listItem/ListItem.css +770 -0
  281. package/src/listItem/ListItem.grid.css +370 -0
  282. package/src/listItem/ListItem.grid.less +622 -0
  283. package/src/listItem/ListItem.less +421 -0
  284. package/src/listItem/ListItem.spec.tsx +1496 -0
  285. package/src/listItem/ListItem.tsx +447 -0
  286. package/src/listItem/ListItemContext.tsx +27 -0
  287. package/src/listItem/Navigation/ListItemNavigation.spec.tsx +59 -0
  288. package/src/listItem/Navigation/ListItemNavigation.story.tsx +109 -0
  289. package/src/listItem/Navigation/ListItemNavigation.tsx +40 -0
  290. package/src/listItem/Navigation/index.ts +2 -0
  291. package/src/listItem/Prompt/ListItemPrompt.spec.tsx +36 -0
  292. package/src/listItem/Prompt/ListItemPrompt.story.tsx +201 -0
  293. package/src/listItem/Prompt/ListItemPrompt.tsx +32 -0
  294. package/src/listItem/Prompt/index.ts +2 -0
  295. package/src/listItem/Radio/ListItemRadio.spec.tsx +66 -0
  296. package/src/listItem/Radio/ListItemRadio.story.tsx +108 -0
  297. package/src/listItem/Radio/ListItemRadio.tsx +33 -0
  298. package/src/listItem/Radio/index.ts +2 -0
  299. package/src/listItem/Switch/ListItemSwitch.spec.tsx +47 -0
  300. package/src/listItem/Switch/ListItemSwitch.story.tsx +77 -0
  301. package/src/listItem/Switch/ListItemSwitch.tsx +33 -0
  302. package/src/listItem/Switch/index.ts +2 -0
  303. package/src/listItem/_stories/ListItem.focus.test.story.tsx +250 -0
  304. package/src/listItem/_stories/ListItem.layout.test.story.tsx +353 -0
  305. package/src/listItem/_stories/ListItem.scenarios.story.tsx +209 -0
  306. package/src/listItem/_stories/ListItem.story.tsx +772 -0
  307. package/src/listItem/_stories/ListItem.variants.test.story.tsx +271 -0
  308. package/src/listItem/_stories/helpers.tsx +53 -0
  309. package/src/listItem/_stories/subcomponents.tsx +139 -0
  310. package/src/listItem/index.ts +14 -0
  311. package/src/listItem/test-utils.tsx +33 -0
  312. package/src/listItem/useListItemControl.tsx +18 -0
  313. package/src/listItem/useListItemMedia.tsx +13 -0
  314. package/src/main.css +773 -1
  315. package/src/main.less +1 -0
  316. package/src/switch/Switch.tsx +5 -1
  317. package/src/test-utils/assets/placeholder-landscape.svg +1 -0
  318. package/src/test-utils/assets/placeholder-portrait.svg +1 -0
  319. package/src/test-utils/Parameters.d.ts +0 -77
@@ -0,0 +1,466 @@
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { fn } from 'storybook/test';
3
+ import { Freeze, ArrowRight } from '@transferwise/icons';
4
+ import { ListItem } from '../ListItem';
5
+ import {
6
+ SB_LIST_ITEM_ADDITIONAL_INFO as INFO,
7
+ SB_LIST_ITEM_MEDIA as MEDIA,
8
+ } from '../_stories/subcomponents';
9
+ import type { ListItemButtonProps } from './ListItemButton';
10
+ import { disableControls } from '../_stories/helpers';
11
+
12
+ const hideControls = disableControls([
13
+ 'onClick',
14
+ 'children',
15
+ 'className',
16
+ 'addonStart',
17
+ 'addonEnd',
18
+ ]);
19
+
20
+ /**
21
+ * Convenience controls for previewing rich markup,
22
+ * not otherwise possible via Storybook
23
+ */
24
+ type PreviewStoryArgs = ListItemButtonProps & {
25
+ previewAddonStart: boolean | ListItemButtonProps['addonStart'];
26
+ previewAddonEnd: boolean | ListItemButtonProps['addonEnd'];
27
+ };
28
+
29
+ const previewArgTypes = {
30
+ previewAddonStart: {
31
+ control: 'boolean',
32
+ name: 'Preview with `addonStart`',
33
+ mapping: {
34
+ true: { type: 'icon', value: <Freeze /> },
35
+ },
36
+ description: '**NB:** ListItem.Button only supports icon addons.',
37
+ table: {
38
+ category: 'Preview options',
39
+ type: {
40
+ summary: undefined,
41
+ },
42
+ },
43
+ },
44
+ previewAddonEnd: {
45
+ control: 'boolean',
46
+ name: 'Preview with `addonEnd`',
47
+ mapping: {
48
+ true: { type: 'icon', value: <ArrowRight /> },
49
+ },
50
+ description: '**NB:** ListItem.Button only supports icon addons.',
51
+ table: {
52
+ category: 'Preview options',
53
+ type: {
54
+ summary: undefined,
55
+ },
56
+ },
57
+ },
58
+ } as const;
59
+
60
+ const getPropsForPreview = (args: PreviewStoryArgs) => {
61
+ const { previewAddonStart, previewAddonEnd, ...props } = args as {
62
+ previewAddonStart: ListItemButtonProps['addonStart'];
63
+ previewAddonEnd: ListItemButtonProps['addonEnd'];
64
+ [key: string]: any;
65
+ };
66
+
67
+ return [
68
+ props,
69
+ {
70
+ addonStart: previewAddonStart,
71
+ addonEnd: previewAddonEnd,
72
+ },
73
+ ] as const;
74
+ };
75
+
76
+ const meta: Meta<typeof ListItem.Button> = {
77
+ component: ListItem.Button,
78
+ title: 'Content/ListItem/ListItem.Button',
79
+ parameters: {
80
+ docs: {
81
+ toc: true,
82
+ },
83
+ },
84
+ args: {
85
+ partiallyInteractive: false,
86
+ priority: 'secondary-neutral',
87
+ sentiment: undefined,
88
+ loading: undefined,
89
+ href: undefined,
90
+ target: undefined,
91
+ as: undefined,
92
+ addonStart: undefined,
93
+ addonEnd: undefined,
94
+ className: undefined,
95
+ children: 'Click me',
96
+ onClick: fn(),
97
+ },
98
+ argTypes: {
99
+ children: {
100
+ table: {
101
+ type: { summary: 'ReactNode' },
102
+ },
103
+ },
104
+ loading: {
105
+ control: 'boolean',
106
+ description: 'Toggles the loading state',
107
+ },
108
+ priority: {
109
+ control: 'radio',
110
+ options: ['unset (undefined)', 'primary', 'secondary', 'secondary-neutral', 'tertiary'],
111
+ mapping: {
112
+ 'unset (undefined)': undefined,
113
+ },
114
+ description: 'Sets a visual hierarchy amongst the buttons displayed on the screen',
115
+ },
116
+ sentiment: {
117
+ options: ['unset (undefined)', 'default', 'negative'],
118
+ mapping: {
119
+ 'unset (undefined)': undefined,
120
+ },
121
+ description:
122
+ 'Sets a visual hierarchy amongst the buttons displayed on the screen. <br /> **NB:** `negative` variant only affects the `primary` and `secondary` priorities.',
123
+ },
124
+ href: {
125
+ control: 'text',
126
+ description: 'If set, the component will render as an HTML anchor.',
127
+ },
128
+ target: {
129
+ control: 'select',
130
+ options: [undefined, '_blank', '_self', '_parent', '_top'],
131
+ description:
132
+ 'The `target` attribute for HTML anchor. If set to `_blank`, `rel="noopener noreferrer"` is automatically added to the rendered node.',
133
+ },
134
+ addonStart: {
135
+ description: 'Icon accessory to be displayed before the label',
136
+ },
137
+ addonEnd: {
138
+ description: 'Icon accessory to be displayed after the label',
139
+ },
140
+ onClick: {
141
+ table: {
142
+ type: { summary: '(event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void' },
143
+ },
144
+ },
145
+ },
146
+ } satisfies Meta<ListItemButtonProps>;
147
+
148
+ export default meta;
149
+
150
+ type Story = StoryObj<ListItemButtonProps>;
151
+
152
+ export const Playground: StoryObj<PreviewStoryArgs> = {
153
+ tags: ['!autodocs'],
154
+ render: (args: PreviewStoryArgs) => {
155
+ const [props, previewProps] = getPropsForPreview(args);
156
+
157
+ return (
158
+ <ListItem
159
+ title="List item title"
160
+ subtitle="Subtitle goes here"
161
+ media={MEDIA.avatarSingle}
162
+ control={<ListItem.Button {...props} {...previewProps} />}
163
+ additionalInfo={INFO.nonInteractive}
164
+ />
165
+ );
166
+ },
167
+ args: {
168
+ previewAddonStart: false,
169
+ previewAddonEnd: false,
170
+ },
171
+ argTypes: {
172
+ ...previewArgTypes,
173
+ },
174
+ };
175
+
176
+ /**
177
+ * By default, ListItem is fully interactive, which means its whole surface is clickable
178
+ * and triggers the control. To remain WCAG-compliant there can be no nested interactive
179
+ * elements inside the item.<br />
180
+ *
181
+ * To work around this limitation, this control also allows for a partially interactive mode,
182
+ * which can be enabled via `partiallyInteractive` prop. Once set, only the control will
183
+ * remain interactive, which allows for interactive element to be attached to the
184
+ * `ListItem.AdditionalInfo`. This allows for more complex layouts while still providing a
185
+ * clear, accessible action point for users. <br />
186
+ *
187
+ * If you still require a fully interactive ListItem, you can alternatively use `ListItem.Prompt`
188
+ * which allows for a single instance of a link or an inline button.
189
+ *
190
+ * Refer to the [design documentation](https://wise.design/components/list-item#interaction) for details.
191
+ */
192
+ export const Interactivity: StoryObj<PreviewStoryArgs> = {
193
+ args: {
194
+ children: 'Action',
195
+ previewAddonStart: false,
196
+ previewAddonEnd: false,
197
+ },
198
+ argTypes: {
199
+ ...hideControls(['partiallyInteractive']),
200
+ ...previewArgTypes,
201
+ },
202
+ render: (args: PreviewStoryArgs) => {
203
+ const [props, previewProps] = getPropsForPreview(args);
204
+
205
+ return (
206
+ <ol className="list-unstyled">
207
+ <ListItem
208
+ title="Fully interactive ListItem"
209
+ subtitle="Button in fully interactive context"
210
+ media={MEDIA.avatarSingle}
211
+ control={<ListItem.Button {...props} {...previewProps} />}
212
+ />
213
+
214
+ <ListItem
215
+ title="Partially interactive ListItem"
216
+ subtitle="Button in partially interactive context"
217
+ media={MEDIA.avatarSingle}
218
+ control={<ListItem.Button {...props} {...previewProps} partiallyInteractive />}
219
+ />
220
+ </ol>
221
+ );
222
+ },
223
+ };
224
+
225
+ /**
226
+ * If `href` prop is set, the component will be automatically rendered as an HTML anchor element.
227
+ */
228
+ export const AsAnchor: StoryObj<PreviewStoryArgs> = {
229
+ args: {
230
+ children: 'Visit link',
231
+ href: 'https://wise.com',
232
+ target: '_blank',
233
+ previewAddonStart: false,
234
+ previewAddonEnd: false,
235
+ },
236
+ argTypes: {
237
+ ...hideControls(['partiallyInteractive']),
238
+ ...previewArgTypes,
239
+ },
240
+ render: (args: PreviewStoryArgs) => {
241
+ const [props, previewProps] = getPropsForPreview(args);
242
+
243
+ return (
244
+ <ListItem
245
+ title="List item with a Button control"
246
+ subtitle="But it renders as HTML anchor element"
247
+ media={MEDIA.avatarSingle}
248
+ control={<ListItem.Button {...props} {...previewProps} />}
249
+ />
250
+ );
251
+ },
252
+ };
253
+
254
+ /**
255
+ * There are two different types of button – default and negative – designed to emphasise the nature of the action. <br />
256
+ * **NB:** Sentiment only applies to `primary` and `secondary` priorities. <br />
257
+ * [Design documentation](https://wise.design/components/button#types)
258
+ */
259
+ export const Sentiment: StoryObj<PreviewStoryArgs> = {
260
+ args: {
261
+ children: 'Button text',
262
+ previewAddonStart: false,
263
+ previewAddonEnd: false,
264
+ },
265
+ argTypes: {
266
+ ...hideControls(['sentiment', 'priority']),
267
+ ...previewArgTypes,
268
+ },
269
+ render: (args: PreviewStoryArgs) => {
270
+ const [props, previewProps] = getPropsForPreview(args);
271
+
272
+ return (
273
+ <ol className="list-unstyled">
274
+ <ListItem
275
+ title="Default Sentiment - Primary"
276
+ subtitle="Default sentiment with primary priority"
277
+ media={MEDIA.avatarSingle}
278
+ control={
279
+ <ListItem.Button {...props} {...previewProps} priority="primary">
280
+ Default Sentiment
281
+ </ListItem.Button>
282
+ }
283
+ />
284
+ <ListItem
285
+ title="Negative Sentiment - Primary"
286
+ subtitle="Negative sentiment with primary priority"
287
+ media={MEDIA.avatarSingle}
288
+ control={
289
+ <ListItem.Button {...props} {...previewProps} priority="primary" sentiment="negative">
290
+ Negative Sentiment
291
+ </ListItem.Button>
292
+ }
293
+ />
294
+ <ListItem
295
+ title="Default Sentiment - Secondary"
296
+ subtitle="Default sentiment with secondary priority"
297
+ media={MEDIA.avatarSingle}
298
+ control={
299
+ <ListItem.Button {...props} {...previewProps} priority="secondary">
300
+ Default Sentiment
301
+ </ListItem.Button>
302
+ }
303
+ />
304
+ <ListItem
305
+ title="Negative Sentiment - Secondary"
306
+ subtitle="Negative sentiment with secondary priority"
307
+ media={MEDIA.avatarSingle}
308
+ control={
309
+ <ListItem.Button {...props} {...previewProps} priority="secondary" sentiment="negative">
310
+ Negative Sentiment
311
+ </ListItem.Button>
312
+ }
313
+ />
314
+ </ol>
315
+ );
316
+ },
317
+ };
318
+
319
+ /**
320
+ * Priorities set a visual hierarchy amongst the buttons displayed on the
321
+ * screen to help more important buttons to take precedence over others. <br />
322
+ * [Design documentation](https://wise.design/components/button#priorities)
323
+ */
324
+ export const Priority: StoryObj<PreviewStoryArgs> = {
325
+ args: {
326
+ children: 'Button text',
327
+ previewAddonStart: false,
328
+ previewAddonEnd: false,
329
+ },
330
+ argTypes: {
331
+ ...hideControls(['priority']),
332
+ ...previewArgTypes,
333
+ },
334
+ render: (args: PreviewStoryArgs) => {
335
+ const [props, previewProps] = getPropsForPreview(args);
336
+
337
+ return (
338
+ <ol className="list-unstyled">
339
+ <ListItem
340
+ title="Primary Priority"
341
+ subtitle="Primary priority (default)"
342
+ media={MEDIA.avatarSingle}
343
+ control={
344
+ <ListItem.Button {...props} {...previewProps} priority="primary">
345
+ Primary Priority
346
+ </ListItem.Button>
347
+ }
348
+ />
349
+ <ListItem
350
+ title="Secondary Priority"
351
+ subtitle="Secondary priority"
352
+ media={MEDIA.avatarSingle}
353
+ control={
354
+ <ListItem.Button {...props} {...previewProps} priority="secondary">
355
+ Secondary Priority
356
+ </ListItem.Button>
357
+ }
358
+ />
359
+ <ListItem
360
+ title="Secondary Neutral Priority"
361
+ subtitle="Secondary neutral priority"
362
+ media={MEDIA.avatarSingle}
363
+ control={
364
+ <ListItem.Button {...props} {...previewProps} priority="secondary-neutral">
365
+ Secondary Neutral Priority
366
+ </ListItem.Button>
367
+ }
368
+ />
369
+ <ListItem
370
+ title="Tertiary Priority"
371
+ subtitle="Tertiary priority"
372
+ media={MEDIA.avatarSingle}
373
+ control={
374
+ <ListItem.Button {...props} {...previewProps} priority="tertiary">
375
+ Tertiary Priority
376
+ </ListItem.Button>
377
+ }
378
+ />
379
+ </ol>
380
+ );
381
+ },
382
+ };
383
+
384
+ /**
385
+ * Button in loading state.
386
+ */
387
+ export const Loading: StoryObj<PreviewStoryArgs> = {
388
+ args: {
389
+ loading: true,
390
+ previewAddonStart: false,
391
+ previewAddonEnd: false,
392
+ },
393
+ argTypes: {
394
+ ...hideControls(['loading']),
395
+ ...previewArgTypes,
396
+ },
397
+ render: (args: PreviewStoryArgs) => {
398
+ const [props, previewProps] = getPropsForPreview(args);
399
+
400
+ return (
401
+ <ListItem
402
+ title="Loading Button"
403
+ subtitle="Button in loading state"
404
+ media={MEDIA.avatarSingle}
405
+ control={
406
+ <ListItem.Button {...props} {...previewProps}>
407
+ Loading Button
408
+ </ListItem.Button>
409
+ }
410
+ additionalInfo={INFO.nonInteractive}
411
+ />
412
+ );
413
+ },
414
+ };
415
+
416
+ const addonProps = {
417
+ addonStart: { type: 'icon', value: <Freeze /> },
418
+ addonEnd: { type: 'icon', value: <ArrowRight /> },
419
+ } as const;
420
+
421
+ /**
422
+ * Icons can be displayed before and after the button label. <br />
423
+ * **NB:** ListItem.Button only supports icon addons.
424
+ */
425
+ export const WithIcons: Story = {
426
+ args: {
427
+ children: 'Button text',
428
+ },
429
+ argTypes: hideControls(),
430
+ render: (args: ListItemButtonProps) => {
431
+ return (
432
+ <ol className="list-unstyled">
433
+ <ListItem
434
+ title="With Start Icon"
435
+ subtitle="Button with icon before the label"
436
+ media={MEDIA.avatarSingle}
437
+ control={
438
+ <ListItem.Button {...args} addonStart={addonProps.addonStart}>
439
+ With start icon
440
+ </ListItem.Button>
441
+ }
442
+ />
443
+ <ListItem
444
+ title="With End Icon"
445
+ subtitle="Button with icon after the label"
446
+ media={MEDIA.avatarSingle}
447
+ control={
448
+ <ListItem.Button {...args} addonEnd={addonProps.addonEnd}>
449
+ With end icon
450
+ </ListItem.Button>
451
+ }
452
+ />
453
+ <ListItem
454
+ title="With Both Icons"
455
+ subtitle="Button with icons before and after the label"
456
+ media={MEDIA.avatarSingle}
457
+ control={
458
+ <ListItem.Button {...args} {...addonProps}>
459
+ With both icons
460
+ </ListItem.Button>
461
+ }
462
+ />
463
+ </ol>
464
+ );
465
+ },
466
+ };
@@ -0,0 +1,56 @@
1
+ import { useContext } from 'react';
2
+ import { clsx } from 'clsx';
3
+ import ButtonComp, { type ButtonAddonIcon, type NewButtonProps } from '../../button';
4
+ import { useListItemControl } from '../useListItemControl';
5
+ import { ListItemContext } from '../ListItemContext';
6
+
7
+ export type ListItemButtonProps = Omit<
8
+ NewButtonProps,
9
+ 'v2' | 'size' | 'disabled' | 'block' | 'addonStart'
10
+ > & {
11
+ /**
12
+ * Toggles the [interactivity strategy](https://storybook.wise.design/?path=/docs/content-listitem--docs#interactivity) for the whole ListItem.
13
+ */
14
+ partiallyInteractive?: boolean;
15
+ addonStart?: ButtonAddonIcon;
16
+ };
17
+
18
+ /**
19
+ * This component allows for rendering a Button control. It's a thin wrapper around the
20
+ * [Button component](https://storybook.wise.design/?path=/docs/content-button--docs), but offers only
21
+ * a subset of its features in line with the ListItem's constraints. <br />
22
+ * <br />
23
+ * Please refer to the [Design documentation](https://wise.design/components/list-item---button) for details.
24
+ */
25
+ export const Button = ({
26
+ priority = 'secondary-neutral',
27
+ partiallyInteractive,
28
+ ...props
29
+ }: ListItemButtonProps) => {
30
+ const { baseItemProps } = useListItemControl('button', { partiallyInteractive, ...props });
31
+ const { ids, describedByIds } = useContext(ListItemContext);
32
+
33
+ const commonProps = {
34
+ ...props,
35
+ className: clsx(
36
+ 'wds-list-item-control',
37
+ !partiallyInteractive && props.href && 'wds-list-item-control_pseudo-element',
38
+ ),
39
+ id: ids.control,
40
+ priority,
41
+ v2: true,
42
+ size: 'sm',
43
+ disabled: baseItemProps.disabled,
44
+ };
45
+
46
+ const buttonContentId = props.href || partiallyInteractive ? '' : `${ids.control}_content`;
47
+
48
+ return (
49
+ <ButtonComp
50
+ aria-describedby={`${buttonContentId} ${describedByIds}`}
51
+ {...(commonProps as NewButtonProps)}
52
+ />
53
+ );
54
+ };
55
+
56
+ Button.displayName = 'ListItem.Button';
@@ -0,0 +1,2 @@
1
+ export type { ListItemButtonProps } from './ListItemButton';
2
+ export { Button } from './ListItemButton';
@@ -0,0 +1,82 @@
1
+ import { render, screen } from '../../test-utils';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { ListItem, type Props as ListItemProps } from '../ListItem';
4
+
5
+ describe('ListItem.Checkbox', () => {
6
+ const renderWith = (overrides: Partial<ListItemProps> = {}) =>
7
+ render(<ListItem title="Test title" {...overrides} />);
8
+
9
+ it('renders checkbox', () => {
10
+ renderWith({ control: <ListItem.Checkbox /> });
11
+ expect(screen.getByRole('checkbox')).toBeInTheDocument();
12
+ });
13
+
14
+ describe('checked state', () => {
15
+ it('reflects checked state', () => {
16
+ renderWith({ control: <ListItem.Checkbox checked onChange={jest.fn()} /> });
17
+ expect(screen.getByRole('checkbox')).toBeChecked();
18
+ });
19
+
20
+ it('reflects unchecked state', () => {
21
+ renderWith({ control: <ListItem.Checkbox checked={false} onChange={jest.fn()} /> });
22
+ expect(screen.getByRole('checkbox')).not.toBeChecked();
23
+ });
24
+
25
+ it('supports indeterminate state', () => {
26
+ renderWith({ control: <ListItem.Checkbox indeterminate /> });
27
+ expect(screen.getByRole('checkbox')).toHaveProperty('indeterminate', true);
28
+ });
29
+ });
30
+
31
+ describe('interactivity', () => {
32
+ it('handles onChange events', async () => {
33
+ const handleChange = jest.fn();
34
+ renderWith({ control: <ListItem.Checkbox checked={false} onChange={handleChange} /> });
35
+
36
+ await userEvent.click(screen.getByRole('checkbox'));
37
+ expect(handleChange).toHaveBeenCalledTimes(1);
38
+ });
39
+
40
+ it('is disabled when ListItem is disabled', () => {
41
+ renderWith({
42
+ disabled: true,
43
+ control: <ListItem.Checkbox checked={false} onChange={jest.fn()} />,
44
+ });
45
+
46
+ expect(screen.getByRole('checkbox')).toBeDisabled();
47
+ });
48
+
49
+ it('handles onFocus events', async () => {
50
+ const handleFocus = jest.fn();
51
+ renderWith({
52
+ control: <ListItem.Checkbox checked={false} onFocus={handleFocus} onChange={() => {}} />,
53
+ });
54
+
55
+ await userEvent.tab();
56
+ expect(handleFocus).toHaveBeenCalledTimes(1);
57
+ });
58
+
59
+ it('handles onBlur events', async () => {
60
+ const handleBlur = jest.fn();
61
+ renderWith({
62
+ control: <ListItem.Checkbox checked={false} onBlur={handleBlur} onChange={() => {}} />,
63
+ });
64
+
65
+ const checkbox = screen.getByRole('checkbox');
66
+ await userEvent.click(checkbox);
67
+ await userEvent.tab();
68
+ expect(handleBlur).toHaveBeenCalledTimes(1);
69
+ });
70
+ });
71
+
72
+ it('supports name and value attributes', () => {
73
+ const checkboxName = 'test-checkbox';
74
+ const checkboxValue = 'test-value';
75
+ renderWith({ control: <ListItem.Checkbox name={checkboxName} value={checkboxValue} /> });
76
+
77
+ const checkbox = screen.getByRole('checkbox');
78
+ expect(checkbox).toHaveAttribute('name', checkboxName);
79
+ // eslint-disable-next-line jest-dom/prefer-to-have-value
80
+ expect(checkbox).toHaveAttribute('value', checkboxValue);
81
+ });
82
+ });