@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,125 @@
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { useState } from 'react';
3
+ import { ListItem } from '../ListItem';
4
+ import {
5
+ SB_LIST_ITEM_ADDITIONAL_INFO as INFO,
6
+ SB_LIST_ITEM_MEDIA as MEDIA,
7
+ } from '../_stories/subcomponents';
8
+ import type { ListItemCheckboxProps } from './ListItemCheckbox';
9
+ import { fn } from 'storybook/test';
10
+
11
+ const meta: Meta<ListItemCheckboxProps> = {
12
+ component: ListItem.Checkbox,
13
+ title: 'Content/ListItem/ListItem.Checkbox',
14
+ parameters: {
15
+ docs: {
16
+ toc: true,
17
+ },
18
+ },
19
+ args: {
20
+ checked: false,
21
+ indeterminate: false,
22
+ value: 'checkbox',
23
+ name: 'checkbox',
24
+ onChange: fn(),
25
+ onFocus: fn(),
26
+ onBlur: fn(),
27
+ },
28
+ argTypes: {
29
+ checked: {
30
+ control: 'boolean',
31
+ },
32
+ indeterminate: {
33
+ control: 'boolean',
34
+ },
35
+ onChange: {
36
+ table: {
37
+ type: { summary: '(event: ChangeEvent<HTMLInputElement>) => void' },
38
+ },
39
+ },
40
+ onFocus: {
41
+ table: {
42
+ type: { summary: '(event: FocusEvent<HTMLInputElement>) => void' },
43
+ },
44
+ },
45
+ onBlur: {
46
+ table: {
47
+ type: { summary: '(event: FocusEvent<HTMLInputElement>) => void' },
48
+ },
49
+ },
50
+ },
51
+ } satisfies Meta<ListItemCheckboxProps>;
52
+
53
+ export default meta;
54
+
55
+ type Story = StoryObj<ListItemCheckboxProps>;
56
+
57
+ export const Playground: Story = {
58
+ tags: ['!autodocs'],
59
+ render: (args: ListItemCheckboxProps) => {
60
+ return (
61
+ <ListItem
62
+ title="List item with checkbox"
63
+ subtitle="Select this option"
64
+ media={MEDIA.avatarSingle}
65
+ control={<ListItem.Checkbox {...args} />}
66
+ additionalInfo={INFO.nonInteractive}
67
+ />
68
+ );
69
+ },
70
+ };
71
+
72
+ /**
73
+ * Checkbox controls demonstrate different states including checked, unchecked, and indeterminate.
74
+ */
75
+ export const States: Story = {
76
+ parameters: {
77
+ controls: { disable: true },
78
+ },
79
+ render: function Render() {
80
+ const [isChecked0, setisChecked0] = useState(false);
81
+ const [isChecked1, setisChecked1] = useState(true);
82
+ const [isChecked2, setisChecked2] = useState(false);
83
+
84
+ return (
85
+ <ol className="list-unstyled">
86
+ <ListItem
87
+ control={
88
+ <ListItem.Checkbox
89
+ checked={isChecked0}
90
+ onChange={() => setisChecked0((current) => !current)}
91
+ />
92
+ }
93
+ title="Unchecked option"
94
+ subtitle="This option is not selected"
95
+ media={MEDIA.avatarSingle}
96
+ />
97
+
98
+ <ListItem
99
+ control={
100
+ <ListItem.Checkbox
101
+ checked={isChecked1}
102
+ onChange={() => setisChecked1((current) => !current)}
103
+ />
104
+ }
105
+ title="Checked option"
106
+ subtitle="This option is selected"
107
+ media={MEDIA.avatarSingle}
108
+ />
109
+
110
+ <ListItem
111
+ control={
112
+ <ListItem.Checkbox
113
+ checked={isChecked2}
114
+ indeterminate
115
+ onChange={() => setisChecked2((current) => !current)}
116
+ />
117
+ }
118
+ title="Indeterminate option"
119
+ subtitle="This option is partially selected"
120
+ media={MEDIA.avatarSingle}
121
+ />
122
+ </ol>
123
+ );
124
+ },
125
+ };
@@ -0,0 +1,33 @@
1
+ import { useContext } from 'react';
2
+ import CheckboxButton, { type CheckboxButtonProps } from '../../checkboxButton/CheckboxButton';
3
+ import { useListItemControl } from '../useListItemControl';
4
+ import { ListItemContext } from '../ListItemContext';
5
+
6
+ export type ListItemCheckboxProps = Pick<
7
+ CheckboxButtonProps,
8
+ 'checked' | 'indeterminate' | 'onChange' | 'onBlur' | 'onFocus' | 'value' | 'name'
9
+ >;
10
+
11
+ /**
12
+ * This component allows for rendering a checkbox control within a fully interactive ListItem. <br />It's a thin wrapper around the
13
+ * [CheckboxButton component](https://storybook.wise.design/?path=/docs/actions-checkboxbutton--docs),
14
+ * but offers only a subset of its features in line with the ListItem's constraints. <br />
15
+ *
16
+ * Please refer to the [Design documentation](https://wise.design/components/list-item---checkbox) for details.
17
+ */
18
+ export const Checkbox = function (props: ListItemCheckboxProps) {
19
+ const { baseItemProps } = useListItemControl('checkbox', { ...props });
20
+ const { ids, describedByIds } = useContext(ListItemContext);
21
+
22
+ return (
23
+ <CheckboxButton
24
+ {...props}
25
+ className="wds-list-item-control"
26
+ disabled={baseItemProps.disabled}
27
+ id={ids.control}
28
+ aria-describedby={describedByIds}
29
+ />
30
+ );
31
+ };
32
+
33
+ Checkbox.displayName = 'ListItem.Checkbox';
@@ -0,0 +1,2 @@
1
+ export type { ListItemCheckboxProps } from './ListItemCheckbox';
2
+ export { Checkbox } from './ListItemCheckbox';
@@ -0,0 +1,119 @@
1
+ import { Edit } from '@transferwise/icons';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { mockMatchMedia, render, screen } from '../../test-utils';
4
+ import { ListItem, type Props as ListItemProps } from '../ListItem';
5
+
6
+ mockMatchMedia();
7
+
8
+ describe('ListItem.IconButton', () => {
9
+ const renderWith = (overrides: Partial<ListItemProps> = {}) =>
10
+ render(<ListItem title="Test title" {...overrides} />);
11
+
12
+ describe('as button', () => {
13
+ it('renders as button by default', () => {
14
+ renderWith({
15
+ control: (
16
+ <ListItem.IconButton>
17
+ <Edit />
18
+ </ListItem.IconButton>
19
+ ),
20
+ });
21
+ expect(screen.getByRole('button')).toBeInTheDocument();
22
+ });
23
+
24
+ it('renders as button if onClick is provided', () => {
25
+ renderWith({
26
+ control: (
27
+ <ListItem.IconButton onClick={() => {}}>
28
+ <Edit />
29
+ </ListItem.IconButton>
30
+ ),
31
+ });
32
+
33
+ expect(screen.getByRole('button')).toBeInTheDocument();
34
+ });
35
+
36
+ it('handles onClick events', async () => {
37
+ const handleClick = jest.fn();
38
+ renderWith({
39
+ control: (
40
+ <ListItem.IconButton onClick={handleClick}>
41
+ <Edit />
42
+ </ListItem.IconButton>
43
+ ),
44
+ });
45
+
46
+ await userEvent.click(screen.getByRole('button'));
47
+ expect(handleClick).toHaveBeenCalledTimes(1);
48
+ });
49
+
50
+ it('is disabled when ListItem is disabled', async () => {
51
+ const handleClick = jest.fn();
52
+ renderWith({
53
+ disabled: true,
54
+ control: (
55
+ <ListItem.IconButton onClick={handleClick}>
56
+ <Edit />
57
+ </ListItem.IconButton>
58
+ ),
59
+ });
60
+
61
+ const button = screen.getByRole('button');
62
+ expect(button).toBeDisabled();
63
+ await userEvent.click(button);
64
+ expect(handleClick).not.toHaveBeenCalled();
65
+ });
66
+ });
67
+
68
+ describe('as link', () => {
69
+ it('renders as link when href is provided', () => {
70
+ renderWith({
71
+ control: (
72
+ <ListItem.IconButton href="/test">
73
+ <Edit />
74
+ </ListItem.IconButton>
75
+ ),
76
+ });
77
+
78
+ expect(screen.getByRole('link')).toHaveAttribute('href', '/test');
79
+ });
80
+
81
+ it('supports target attribute for links', () => {
82
+ renderWith({
83
+ control: (
84
+ <ListItem.IconButton href="/test" target="_blank">
85
+ <Edit />
86
+ </ListItem.IconButton>
87
+ ),
88
+ });
89
+
90
+ const link = screen.getByRole('link');
91
+ expect(link).toHaveAttribute('target', '_blank');
92
+ expect(link).toHaveAttribute('rel', 'noopener noreferrer');
93
+ });
94
+
95
+ it('is disabled when ListItem is disabled', async () => {
96
+ renderWith({
97
+ disabled: true,
98
+ control: (
99
+ <ListItem.IconButton href="/test">
100
+ <Edit />
101
+ </ListItem.IconButton>
102
+ ),
103
+ });
104
+ expect(screen.getByRole('link')).toHaveAttribute('aria-disabled', 'true');
105
+ });
106
+ });
107
+
108
+ it('renders children content', () => {
109
+ renderWith({
110
+ control: (
111
+ <ListItem.IconButton>
112
+ <Edit />
113
+ </ListItem.IconButton>
114
+ ),
115
+ });
116
+
117
+ expect(screen.getByTestId('edit-icon')).toBeInTheDocument();
118
+ });
119
+ });
@@ -0,0 +1,249 @@
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Edit } from '@transferwise/icons';
3
+ import { fn } from 'storybook/test';
4
+ import { ListItem } from '../ListItem';
5
+ import {
6
+ SB_LIST_ITEM_ADDITIONAL_INFO as INFO,
7
+ SB_LIST_ITEM_MEDIA as MEDIA,
8
+ SB_LIST_ITEM_PROMPTS as PROMPTS,
9
+ } from '../_stories/subcomponents';
10
+ import { disableControls } from '../_stories/helpers';
11
+ import type { ListItemIconButtonProps } from './ListItemIconButton';
12
+
13
+ const hideControls = disableControls([
14
+ 'onClick',
15
+ 'children',
16
+ 'className',
17
+ 'addonStart',
18
+ 'addonEnd',
19
+ ]);
20
+
21
+ /**
22
+ * Use IconButton to provide compact action controls within a ListItem context using iconography.
23
+ *
24
+ * Refer to the [design documentation](https://wise.design/components/list-item) for more details.
25
+ */
26
+ const meta: Meta<ListItemIconButtonProps> = {
27
+ component: ListItem.IconButton,
28
+ title: 'Content/ListItem/ListItem.IconButton',
29
+ parameters: {
30
+ docs: {
31
+ toc: true,
32
+ },
33
+ },
34
+ args: {
35
+ partiallyInteractive: false,
36
+ priority: undefined,
37
+ type: undefined,
38
+ children: <Edit />,
39
+ href: undefined,
40
+ target: undefined,
41
+ onClick: fn(),
42
+ },
43
+ argTypes: {
44
+ children: {
45
+ description: 'Once of the [Icon components](https://transferwise.github.io/icons/).',
46
+ table: {
47
+ type: { summary: 'ReactNode' },
48
+ },
49
+ control: false,
50
+ },
51
+ priority: {
52
+ control: 'radio',
53
+ options: ['unset (undefined)', 'primary', 'secondary', 'tertiary', 'minimal'],
54
+ mapping: {
55
+ 'unset (undefined)': undefined,
56
+ },
57
+ description: 'IconButton priority/style variant',
58
+ },
59
+ type: {
60
+ control: 'radio',
61
+ options: ['unset (undefined)', 'default', 'negative'],
62
+ mapping: {
63
+ 'unset (undefined)': undefined,
64
+ },
65
+ description:
66
+ 'Sets a visual hierarchy amongst the buttons displayed on the screen. <br /> **NB:** `negative` sentiment only affects the `primary` and `secondary` priorities.',
67
+ },
68
+ partiallyInteractive: {
69
+ control: 'boolean',
70
+ description: 'Whether the icon button allows partial interactivity in the ListItem',
71
+ },
72
+ href: {
73
+ control: 'text',
74
+ description: 'URL for icon button rendered as link',
75
+ },
76
+ target: {
77
+ control: 'select',
78
+ options: [undefined, '_blank', '_self', '_parent', '_top'],
79
+ description:
80
+ 'The `target` attribute for HTML anchor. If set to `_blank`, `rel="noopener noreferrer"` is automatically added to the rendered node.',
81
+ },
82
+ },
83
+ } satisfies Meta<ListItemIconButtonProps>;
84
+
85
+ export default meta;
86
+
87
+ type Story = StoryObj<ListItemIconButtonProps>;
88
+
89
+ export const Playground: Story = {
90
+ tags: ['!autodocs'],
91
+ render: (args: ListItemIconButtonProps) => {
92
+ return (
93
+ <ListItem
94
+ title="List item title"
95
+ subtitle="Subtitle goes here"
96
+ media={MEDIA.avatarSingle}
97
+ control={<ListItem.IconButton {...args} />}
98
+ additionalInfo={INFO.nonInteractive}
99
+ />
100
+ );
101
+ },
102
+ };
103
+
104
+ /**
105
+ * By default, ListItem is fully interactive, which means its whole surface is clickable
106
+ * and triggers the control. To remain WCAG-compliant there can be no nested interactive
107
+ * elements inside the item.<br />
108
+ *
109
+ * To work around this limitation, this control also allows for a partially interactive mode,
110
+ * which can be enabled via `partiallyInteractive` prop. Once set, only the control will
111
+ * remain interactive, which allows for interactive element to be attached to the
112
+ * `ListItem.AdditionalInfo`. This allows for more complex layouts while still providing a
113
+ * clear, accessible action point for users. <br />
114
+ *
115
+ * If you still require a fully interactive ListItem, you can alternatively use `ListItem.Prompt`
116
+ * which allows for a single instance of a link or an inline button.
117
+ *
118
+ * Refer to the [design documentation](https://wise.design/components/list-item#interaction) for details.
119
+ */
120
+ export const Interactivity: Story = {
121
+ args: {
122
+ children: <Edit />,
123
+ },
124
+ argTypes: hideControls(['partiallyInteractive']),
125
+ render: (args: ListItemIconButtonProps) => {
126
+ return (
127
+ <ol className="list-unstyled">
128
+ <ListItem
129
+ control={<ListItem.IconButton {...args} />}
130
+ title="Fully interactive ListItem"
131
+ subtitle="IconButton in fully interactive context"
132
+ media={MEDIA.avatarSingle}
133
+ additionalInfo={INFO.nonInteractive}
134
+ prompt={PROMPTS.interactive}
135
+ />
136
+
137
+ <ListItem
138
+ control={<ListItem.IconButton {...args} partiallyInteractive />}
139
+ title="Partially interactive ListItem"
140
+ subtitle="IconButton in partially interactive context"
141
+ media={MEDIA.avatarSingle}
142
+ additionalInfo={INFO.interactive}
143
+ prompt={PROMPTS.interactive}
144
+ />
145
+ </ol>
146
+ );
147
+ },
148
+ };
149
+
150
+ /**
151
+ * There are two different types of icon button – default and negative – designed to emphasise the nature of the action. <br />
152
+ * **NB:** Sentiment only applies to `primary` and `secondary` priorities. <br />
153
+ * [Design documentation](https://wise.design/components/icon-button#types)
154
+ */
155
+ export const Sentiment: Story = {
156
+ argTypes: hideControls(['sentiment', 'priority']),
157
+ render: (args) => {
158
+ return (
159
+ <ol className="list-unstyled">
160
+ <ListItem
161
+ control={<ListItem.IconButton {...args} priority="primary" type="default" />}
162
+ title="Default Sentiment - Primary"
163
+ subtitle="Default sentiment with primary priority"
164
+ media={MEDIA.avatarSingle}
165
+ />
166
+ <ListItem
167
+ control={<ListItem.IconButton {...args} priority="secondary" type="default" />}
168
+ title="Default Sentiment - Secondary"
169
+ subtitle="Default sentiment with secondary priority"
170
+ media={MEDIA.avatarSingle}
171
+ />
172
+ <ListItem
173
+ control={<ListItem.IconButton {...args} priority="primary" type="negative" />}
174
+ title="Negative Sentiment - Primary"
175
+ subtitle="Negative sentiment with primary priority"
176
+ media={MEDIA.avatarSingle}
177
+ />
178
+ <ListItem
179
+ control={<ListItem.IconButton {...args} priority="secondary" type="negative" />}
180
+ title="Negative Sentiment - Secondary"
181
+ subtitle="Negative sentiment with secondary priority"
182
+ media={MEDIA.avatarSingle}
183
+ />
184
+ </ol>
185
+ );
186
+ },
187
+ };
188
+
189
+ /**
190
+ * Priorities set a visual hierarchy amongst the buttons displayed on the
191
+ * screen to help more important buttons to take precedence over others. <br />
192
+ * [Design documentation](https://wise.design/components/icon-button#priorities)
193
+ */
194
+ export const Priority: Story = {
195
+ argTypes: hideControls(['sentiment', 'priority']),
196
+ render: (args) => {
197
+ return (
198
+ <ol className="list-unstyled">
199
+ <ListItem
200
+ title="Primary Priority"
201
+ subtitle="Primary priority (default)"
202
+ media={MEDIA.avatarSingle}
203
+ control={<ListItem.IconButton {...args} priority="primary" />}
204
+ />
205
+ <ListItem
206
+ title="Secondary Priority"
207
+ subtitle="Secondary priority"
208
+ media={MEDIA.avatarSingle}
209
+ control={<ListItem.IconButton {...args} priority="secondary" />}
210
+ />
211
+ <ListItem
212
+ title="Secondary Neutral Priority"
213
+ subtitle="Secondary neutral priority"
214
+ media={MEDIA.avatarSingle}
215
+ control={<ListItem.IconButton {...args} priority="tertiary" />}
216
+ />
217
+ <ListItem
218
+ title="Tertiary Priority"
219
+ subtitle="Tertiary priority"
220
+ media={MEDIA.avatarSingle}
221
+ control={<ListItem.IconButton {...args} priority="minimal" />}
222
+ />
223
+ </ol>
224
+ );
225
+ },
226
+ };
227
+
228
+ /**
229
+ * If `href` prop is set, the component will be automatically rendered as an HTML anchor element.
230
+ */
231
+ export const AsAnchor: Story = {
232
+ args: {
233
+ children: <Edit />,
234
+ href: 'https://wise.com',
235
+ target: '_blank',
236
+ onClick: undefined,
237
+ },
238
+ argTypes: hideControls(),
239
+ render: (args: ListItemIconButtonProps) => {
240
+ return (
241
+ <ListItem
242
+ control={<ListItem.IconButton {...args} />}
243
+ title="List item with icon button link"
244
+ subtitle="IconButton rendered as anchor element"
245
+ media={MEDIA.avatarSingle}
246
+ />
247
+ );
248
+ },
249
+ };
@@ -0,0 +1,56 @@
1
+ import { clsx } from 'clsx';
2
+ import { useContext, type ReactNode } from 'react';
3
+ import IconButtonComp, { type IconButtonProps } from '../../iconButton';
4
+ import { useListItemControl } from '../useListItemControl';
5
+ import { ListItemContext } from '../ListItemContext';
6
+
7
+ export type ListItemIconButtonProps = Pick<
8
+ IconButtonProps,
9
+ 'priority' | 'type' | 'onClick' | 'href' | 'target' | 'aria-label'
10
+ > & {
11
+ children: ReactNode;
12
+ partiallyInteractive?: boolean;
13
+ };
14
+
15
+ /**
16
+ * This component allows for rendering a IconButton control. It's a thin wrapper around the
17
+ * [IconButton component](https://storybook.wise.design/?path=/docs/actions-iconbutton--docs), but offers only
18
+ * a subset of its features in line with the ListItem's constraints. <br />
19
+ * <br />
20
+ * Please refer to the [Design documentation](https://wise.design/components/list-item---icon-button) for details.
21
+ */
22
+ export const IconButton = function ({ priority = 'minimal', ...props }: ListItemIconButtonProps) {
23
+ const { partiallyInteractive, ...restProps } = props;
24
+
25
+ const { ids, props: itemProps } = useContext(ListItemContext);
26
+ const { baseItemProps } = useListItemControl('icon-button', {
27
+ partiallyInteractive,
28
+ ...restProps,
29
+ });
30
+
31
+ const descriptorIds = [
32
+ itemProps.inverted ? ids.subtitle : ids.title,
33
+ itemProps.inverted ? ids.title : ids.subtitle,
34
+ itemProps.inverted ? ids.valueSubtitle : ids.valueTitle,
35
+ itemProps.inverted ? ids.valueTitle : ids.valueSubtitle,
36
+ ids.additionalInfo,
37
+ ids.prompt,
38
+ ].join(' ');
39
+
40
+ return (
41
+ <IconButtonComp
42
+ {...restProps}
43
+ aria-describedby={descriptorIds}
44
+ className={clsx(
45
+ 'wds-list-item-control',
46
+ !partiallyInteractive && props.href && 'wds-list-item-control_pseudo-element',
47
+ )}
48
+ id={ids.control}
49
+ size={40}
50
+ priority={priority}
51
+ disabled={baseItemProps.disabled}
52
+ />
53
+ );
54
+ };
55
+
56
+ IconButton.displayName = 'ListItem.IconButton';
@@ -0,0 +1,2 @@
1
+ export type { ListItemIconButtonProps } from './ListItemIconButton';
2
+ export { IconButton } from './ListItemIconButton';
@@ -0,0 +1,30 @@
1
+ import { render, screen } from '../../test-utils';
2
+ import { ListItem, type Props as ListItemProps } from '../ListItem';
3
+
4
+ const renderWithMedia = (media: ListItemProps['media']) =>
5
+ render(<ListItem title="Test Title" media={media} />);
6
+
7
+ describe('ListItem.Image', () => {
8
+ it('renders image with presentation role when no alt text', () => {
9
+ renderWithMedia(<ListItem.Image src="test-image.jpg" />);
10
+ expect(screen.getByRole('presentation')).toHaveAttribute('src', 'test-image.jpg');
11
+ });
12
+
13
+ it('renders image with graphics-symbol role when alt text provided', () => {
14
+ renderWithMedia(<ListItem.Image src="test-image.jpg" alt="Test image description" />);
15
+
16
+ const image = screen.getByRole('graphics-symbol');
17
+ expect(image).toHaveAttribute('alt', 'Test image description');
18
+ expect(image).toHaveAttribute('src', 'test-image.jpg');
19
+ });
20
+
21
+ it('renders image with loading prop', () => {
22
+ renderWithMedia(<ListItem.Image src="test-image.jpg" loading="lazy" />);
23
+ expect(screen.getByRole('presentation')).toHaveAttribute('loading', 'lazy');
24
+ });
25
+
26
+ it('renders image with className prop', () => {
27
+ renderWithMedia(<ListItem.Image src="test-image.jpg" className="custom-image-class" />);
28
+ expect(screen.getByRole('presentation')).toHaveClass('custom-image-class');
29
+ });
30
+ });