@transferwise/components 46.158.0 → 46.159.1

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 (201) hide show
  1. package/build/FlowNavigation/FlowNavigation.js +5 -14
  2. package/build/FlowNavigation/FlowNavigation.js.map +1 -1
  3. package/build/FlowNavigation/FlowNavigation.mjs +5 -14
  4. package/build/FlowNavigation/FlowNavigation.mjs.map +1 -1
  5. package/build/_deprecated/OverlayHeader/OverlayHeader.js +6 -41
  6. package/build/_deprecated/OverlayHeader/OverlayHeader.js.map +1 -1
  7. package/build/_deprecated/OverlayHeader/OverlayHeader.mjs +6 -41
  8. package/build/_deprecated/OverlayHeader/OverlayHeader.mjs.map +1 -1
  9. package/build/i18n/cs.json +5 -0
  10. package/build/i18n/cs.json.js +5 -0
  11. package/build/i18n/cs.json.js.map +1 -1
  12. package/build/i18n/cs.json.mjs +5 -0
  13. package/build/i18n/cs.json.mjs.map +1 -1
  14. package/build/i18n/de.json +5 -0
  15. package/build/i18n/de.json.js +5 -0
  16. package/build/i18n/de.json.js.map +1 -1
  17. package/build/i18n/de.json.mjs +5 -0
  18. package/build/i18n/de.json.mjs.map +1 -1
  19. package/build/i18n/es.json +5 -0
  20. package/build/i18n/es.json.js +5 -0
  21. package/build/i18n/es.json.js.map +1 -1
  22. package/build/i18n/es.json.mjs +5 -0
  23. package/build/i18n/es.json.mjs.map +1 -1
  24. package/build/i18n/fr.json +5 -0
  25. package/build/i18n/fr.json.js +5 -0
  26. package/build/i18n/fr.json.js.map +1 -1
  27. package/build/i18n/fr.json.mjs +5 -0
  28. package/build/i18n/fr.json.mjs.map +1 -1
  29. package/build/i18n/hu.json +5 -0
  30. package/build/i18n/hu.json.js +5 -0
  31. package/build/i18n/hu.json.js.map +1 -1
  32. package/build/i18n/hu.json.mjs +5 -0
  33. package/build/i18n/hu.json.mjs.map +1 -1
  34. package/build/i18n/id.json +5 -0
  35. package/build/i18n/id.json.js +5 -0
  36. package/build/i18n/id.json.js.map +1 -1
  37. package/build/i18n/id.json.mjs +5 -0
  38. package/build/i18n/id.json.mjs.map +1 -1
  39. package/build/i18n/it.json +5 -0
  40. package/build/i18n/it.json.js +5 -0
  41. package/build/i18n/it.json.js.map +1 -1
  42. package/build/i18n/it.json.mjs +5 -0
  43. package/build/i18n/it.json.mjs.map +1 -1
  44. package/build/i18n/ja.json +5 -0
  45. package/build/i18n/ja.json.js +5 -0
  46. package/build/i18n/ja.json.js.map +1 -1
  47. package/build/i18n/ja.json.mjs +5 -0
  48. package/build/i18n/ja.json.mjs.map +1 -1
  49. package/build/i18n/nl.json +5 -0
  50. package/build/i18n/nl.json.js +5 -0
  51. package/build/i18n/nl.json.js.map +1 -1
  52. package/build/i18n/nl.json.mjs +5 -0
  53. package/build/i18n/nl.json.mjs.map +1 -1
  54. package/build/i18n/pl.json +5 -0
  55. package/build/i18n/pl.json.js +5 -0
  56. package/build/i18n/pl.json.js.map +1 -1
  57. package/build/i18n/pl.json.mjs +5 -0
  58. package/build/i18n/pl.json.mjs.map +1 -1
  59. package/build/i18n/pt.json +5 -0
  60. package/build/i18n/pt.json.js +5 -0
  61. package/build/i18n/pt.json.js.map +1 -1
  62. package/build/i18n/pt.json.mjs +5 -0
  63. package/build/i18n/pt.json.mjs.map +1 -1
  64. package/build/i18n/ro.json +5 -0
  65. package/build/i18n/ro.json.js +5 -0
  66. package/build/i18n/ro.json.js.map +1 -1
  67. package/build/i18n/ro.json.mjs +5 -0
  68. package/build/i18n/ro.json.mjs.map +1 -1
  69. package/build/i18n/ru.json +5 -0
  70. package/build/i18n/ru.json.js +5 -0
  71. package/build/i18n/ru.json.js.map +1 -1
  72. package/build/i18n/ru.json.mjs +5 -0
  73. package/build/i18n/ru.json.mjs.map +1 -1
  74. package/build/i18n/th.json +5 -0
  75. package/build/i18n/th.json.js +5 -0
  76. package/build/i18n/th.json.js.map +1 -1
  77. package/build/i18n/th.json.mjs +5 -0
  78. package/build/i18n/th.json.mjs.map +1 -1
  79. package/build/i18n/uk.json +5 -0
  80. package/build/i18n/uk.json.js +5 -0
  81. package/build/i18n/uk.json.js.map +1 -1
  82. package/build/i18n/uk.json.mjs +5 -0
  83. package/build/i18n/uk.json.mjs.map +1 -1
  84. package/build/i18n/zh-HK.json +5 -0
  85. package/build/i18n/zh-HK.json.js +5 -0
  86. package/build/i18n/zh-HK.json.js.map +1 -1
  87. package/build/i18n/zh-HK.json.mjs +5 -0
  88. package/build/i18n/zh-HK.json.mjs.map +1 -1
  89. package/build/main.css +19 -4145
  90. package/build/styles/FlowNavigation/FlowNavigation.css +7 -13
  91. package/build/styles/ListItem/ListItem.css +1 -0
  92. package/build/styles/PocketSurface/PocketSurface.css +2 -11
  93. package/build/styles/SentimentSurface/SentimentSurface.css +0 -23
  94. package/build/styles/css/neptune.css +0 -2821
  95. package/build/styles/main.css +19 -4145
  96. package/build/styles/styles/less/neptune.css +0 -2821
  97. package/build/types/FlowNavigation/FlowNavigation.d.ts +2 -9
  98. package/build/types/FlowNavigation/FlowNavigation.d.ts.map +1 -1
  99. package/build/types/ListItem/_stories/variants/helpers.d.ts.map +1 -1
  100. package/build/types/_deprecated/OverlayHeader/OverlayHeader.d.ts.map +1 -1
  101. package/package.json +10 -10
  102. package/src/Accordion/_stories/Accordion.test.story.tsx +71 -0
  103. package/src/AvatarLayout/_stories/AvatarLayout.test.story.tsx +64 -0
  104. package/src/AvatarView/_stories/AvatarView.test.story.tsx +151 -0
  105. package/src/Button/LegacyButton/_stories/LegacyButton.test.story.tsx +22 -0
  106. package/src/Button/_stories/Button.test.story.tsx +65 -0
  107. package/src/Calendar/_stories/Calendar.test.story.tsx +73 -24
  108. package/src/Carousel/_stories/Carousel.test.story.tsx +59 -0
  109. package/src/Checkbox/_stories/Checkbox.test.story.tsx +20 -0
  110. package/src/CheckboxButton/_stories/CheckboxButton.test.story.tsx +17 -37
  111. package/src/Chevron/_stories/Chevron.test.story.tsx +26 -0
  112. package/src/Chips/_stories/Chips.test.story.tsx +39 -34
  113. package/src/CircularButton/_stories/CircularButton.test.story.tsx +0 -68
  114. package/src/DateInput/_stories/DateInput.test.story.tsx +13 -0
  115. package/src/DateLookup/_stories/DateLookup.rtl.test.story.tsx +88 -0
  116. package/src/Decision/_stories/Decision.test.story.tsx +79 -0
  117. package/src/DefinitionList/_stories/DefinitionList.test.story.tsx +54 -1
  118. package/src/Drawer/_stories/Drawer.rtl.test.story.tsx +58 -0
  119. package/src/ExpressiveMoneyInput/_stories/ExpressiveMoneyInput.rtl.test.story.tsx +118 -0
  120. package/src/Field/_stories/Field.test.story.tsx +46 -0
  121. package/src/FlowNavigation/FlowNavigation.css +7 -13
  122. package/src/FlowNavigation/FlowNavigation.less +6 -15
  123. package/src/FlowNavigation/FlowNavigation.tsx +6 -27
  124. package/src/FlowNavigation/_stories/FlowNavigation.story.tsx +0 -86
  125. package/src/FlowNavigation/_stories/FlowNavigation.test.story.tsx +44 -0
  126. package/src/Header/_stories/Header.test.story.tsx +27 -0
  127. package/src/Info/_stories/Info.rtl.test.story.tsx +64 -0
  128. package/src/Inputs/SelectInput/_stories/SelectInput.rtl.test.story.tsx +135 -0
  129. package/src/Inputs/_stories/InputGroup.test.story.tsx +69 -0
  130. package/src/Inputs/_stories/SearchInput.test.story.tsx +32 -0
  131. package/src/Inputs/_stories/TextArea.test.story.tsx +27 -0
  132. package/src/InstructionsList/_stories/InstructionsList.test.story.tsx +30 -0
  133. package/src/Label/_stories/Label.test.story.tsx +36 -0
  134. package/src/Link/_stories/Link.test.story.tsx +26 -0
  135. package/src/ListItem/ListItem.css +1 -0
  136. package/src/ListItem/_stories/{variants/ListItem.rtl.test.story.tsx → ListItem.rtl.test.story.tsx} +6 -10
  137. package/src/ListItem/_stories/variants/helpers.tsx +2 -6
  138. package/src/Logo/_stories/Logo.test.story.tsx +44 -0
  139. package/src/Modal/_stories/Modal.rtl.test.story.tsx +59 -0
  140. package/src/MoneyInput/_stories/MoneyInput.rtl.test.story.tsx +88 -0
  141. package/src/Nudge/_stories/Nudge.test.story.tsx +37 -0
  142. package/src/PhoneNumberInput/_stories/PhoneNumberInput.test.story.tsx +44 -0
  143. package/src/PocketSurface/PocketSurface.css +2 -11
  144. package/src/PocketSurface/PocketSurface.less +1 -1
  145. package/src/Popover/_stories/Popover.rtl.test.story.tsx +96 -0
  146. package/src/Progress/_stories/Progress.test.story.tsx +27 -0
  147. package/src/ProgressBar/_stories/ProgressBar.test.story.tsx +33 -0
  148. package/src/PromoCard/_stories/PromoCard.test.story.tsx +42 -0
  149. package/src/PromoCard/_stories/PromoCardGroup.test.story.tsx +51 -0
  150. package/src/Prompt/ActionPrompt/_stories/ActionPrompt.test.story.tsx +42 -1
  151. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.test.story.tsx +34 -31
  152. package/src/Prompt/InfoPrompt/_stories/InfoPrompt.test.story.tsx +25 -0
  153. package/src/Prompt/InlinePrompt/_stories/InlinePrompt.test.story.tsx +27 -0
  154. package/src/Radio/_stories/Radio.test.story.tsx +61 -0
  155. package/src/RadioGroup/_stories/RadioGroup.test.story.tsx +56 -0
  156. package/src/Section/_stories/Section.test.story.tsx +29 -0
  157. package/src/SegmentedControl/_stories/SegmentedControl.test.story.tsx +45 -0
  158. package/src/SentimentSurface/SentimentSurface.css +0 -23
  159. package/src/SlidingPanel/_stories/SlidingPanel.rtl.test.story.tsx +70 -0
  160. package/src/Snackbar/_stories/Snackbar.rtl.test.story.tsx +45 -0
  161. package/src/Snackbar/_stories/Snackbar.test.story.tsx +0 -31
  162. package/src/Stepper/_stories/Stepper.test.story.tsx +17 -0
  163. package/src/Switch/_stories/Switch.test.story.tsx +20 -26
  164. package/src/Table/_stories/Table.test.story.tsx +104 -0
  165. package/src/Tabs/_stories/Tabs.test.story.tsx +72 -0
  166. package/src/TextareaWithDisplayFormat/_stories/TextareaWithDisplayFormat.test.story.tsx +48 -0
  167. package/src/Tooltip/_stories/Tooltip.rtl.test.story.tsx +79 -0
  168. package/src/Typeahead/_stories/Typeahead.rtl.test.story.tsx +90 -0
  169. package/src/Upload/_stories/Upload.rtl.test.story.tsx +53 -0
  170. package/src/UploadInput/_stories/UploadInput.test.story.tsx +47 -0
  171. package/src/_deprecated/Alert/_stories/Alert.test.story.tsx +28 -1
  172. package/src/_deprecated/Card/_stories/Card.test.story.tsx +38 -0
  173. package/src/_deprecated/CriticalBanner/_stories/CriticalCommsBanner.test.story.tsx +18 -0
  174. package/src/_deprecated/InlineAlert/_stories/InlineAlert.test.story.tsx +26 -0
  175. package/src/_deprecated/OverlayHeader/OverlayHeader.tsx +2 -21
  176. package/src/_deprecated/OverlayHeader/_stories/OverlayHeader.test.story.tsx +42 -0
  177. package/src/_deprecated/Select/_stories/Select.rtl.test.story.tsx +71 -0
  178. package/src/common/BottomSheet/_stories/BottomSheet.test.story.tsx +23 -0
  179. package/src/common/Panel/_stories/Panel.story.tsx +107 -36
  180. package/src/i18n/cs.json +5 -0
  181. package/src/i18n/de.json +5 -0
  182. package/src/i18n/es.json +5 -0
  183. package/src/i18n/fr.json +5 -0
  184. package/src/i18n/hu.json +5 -0
  185. package/src/i18n/id.json +5 -0
  186. package/src/i18n/it.json +5 -0
  187. package/src/i18n/ja.json +5 -0
  188. package/src/i18n/nl.json +5 -0
  189. package/src/i18n/pl.json +5 -0
  190. package/src/i18n/pt.json +5 -0
  191. package/src/i18n/ro.json +5 -0
  192. package/src/i18n/ru.json +5 -0
  193. package/src/i18n/th.json +5 -0
  194. package/src/i18n/uk.json +5 -0
  195. package/src/i18n/zh-HK.json +5 -0
  196. package/src/main.css +19 -4145
  197. package/src/main.less +0 -1
  198. package/src/styles/less/neptune.css +0 -2821
  199. package/build/styles/_deprecated/OverlayHeader/OverlayHeader.css +0 -15
  200. package/src/_deprecated/OverlayHeader/OverlayHeader.css +0 -15
  201. package/src/_deprecated/OverlayHeader/OverlayHeader.less +0 -24
@@ -0,0 +1,72 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+
3
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
+ import { Width } from '../../common';
5
+ import Tabs from '..';
6
+
7
+ export default {
8
+ component: Tabs,
9
+ title: 'Navigation/Tabs/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Tabs>;
12
+
13
+ type Story = StoryObj<typeof Tabs>;
14
+
15
+ const defaultTabs = [
16
+ { title: 'First tab', disabled: false, content: <div className="p-a-2">First content</div> },
17
+ { title: 'Second tab', disabled: false, content: <div className="p-a-2">Second content</div> },
18
+ { title: 'Third tab', disabled: false, content: <div className="p-a-2">Third content</div> },
19
+ ];
20
+
21
+ /**
22
+ * The tab list is horizontal: tab order, the active indicator translateX, and
23
+ * swipe direction all flip between LTR and RTL. The indicator uses a negated
24
+ * translateX in RTL mode. This diff verifies the layout mirrors correctly.
25
+ */
26
+ export const RTLDiff: Story = {
27
+ render: () => (
28
+ <>
29
+ <div style={{ marginBottom: 32 }}>
30
+ <h4>Block width — first tab selected</h4>
31
+ <Tabs
32
+ name="rtl-block-first"
33
+ tabs={defaultTabs}
34
+ selected={0}
35
+ headerWidth={Width.BLOCK}
36
+ onTabSelect={() => {}}
37
+ />
38
+ </div>
39
+ <div style={{ marginBottom: 32 }}>
40
+ <h4>Block width — second tab selected</h4>
41
+ <Tabs
42
+ name="rtl-block-second"
43
+ tabs={defaultTabs}
44
+ selected={1}
45
+ headerWidth={Width.BLOCK}
46
+ onTabSelect={() => {}}
47
+ />
48
+ </div>
49
+ <div style={{ marginBottom: 32 }}>
50
+ <h4>Auto width — first tab selected</h4>
51
+ <Tabs
52
+ name="rtl-auto-first"
53
+ tabs={defaultTabs}
54
+ selected={0}
55
+ headerWidth={Width.AUTO}
56
+ onTabSelect={() => {}}
57
+ />
58
+ </div>
59
+ <div style={{ marginBottom: 32 }}>
60
+ <h4>Auto width — second tab selected</h4>
61
+ <Tabs
62
+ name="rtl-auto-second"
63
+ tabs={defaultTabs}
64
+ selected={1}
65
+ headerWidth={Width.AUTO}
66
+ onTabSelect={() => {}}
67
+ />
68
+ </div>
69
+ </>
70
+ ),
71
+ ...withRTLDiff(),
72
+ };
@@ -0,0 +1,48 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+
3
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
+ import TextareaWithDisplayFormat from '..';
5
+ import Field from '../../Field/Field';
6
+
7
+ export default {
8
+ component: TextareaWithDisplayFormat,
9
+ title: 'Forms/TextareaWithDisplayFormat/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof TextareaWithDisplayFormat>;
12
+
13
+ type Story = StoryObj<typeof TextareaWithDisplayFormat>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <>
18
+ <Field id="card-code" label="Gift card code">
19
+ <TextareaWithDisplayFormat
20
+ id="card-code"
21
+ value="1234567890123456"
22
+ maxLength={16}
23
+ displayPattern="**** - **** - ****"
24
+ onChange={() => {}}
25
+ />
26
+ </Field>
27
+ <Field id="iban" label="IBAN">
28
+ <TextareaWithDisplayFormat
29
+ id="iban"
30
+ value="GB29NWBK60161331926819"
31
+ maxLength={22}
32
+ displayPattern="** **** **** **** **** **"
33
+ onChange={() => {}}
34
+ />
35
+ </Field>
36
+ <Field id="empty" label="Empty with placeholder">
37
+ <TextareaWithDisplayFormat
38
+ id="empty"
39
+ value=""
40
+ displayPattern="**** - **** - ****"
41
+ placeholder="Enter code"
42
+ onChange={() => {}}
43
+ />
44
+ </Field>
45
+ </>
46
+ ),
47
+ ...withRTLDiff(),
48
+ };
@@ -0,0 +1,79 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { userEvent, within } from 'storybook/test';
3
+
4
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
5
+ import Button from '../../Button';
6
+ import Tooltip from '../Tooltip';
7
+
8
+ export default {
9
+ component: Tooltip,
10
+ title: 'Dialogs/Tooltip/Tests/RTL Diff',
11
+ tags: ['!autodocs', '!manifest'],
12
+ } satisfies Meta<typeof Tooltip>;
13
+
14
+ type Story = StoryObj<typeof Tooltip>;
15
+
16
+ const iframeDiff = withRTLDiff({ renderAs: 'iframe' });
17
+
18
+ const containerStyle: React.CSSProperties = {
19
+ display: 'flex',
20
+ justifyContent: 'center',
21
+ alignItems: 'center',
22
+ minHeight: '20rem',
23
+ width: '100%',
24
+ };
25
+
26
+ const hoverTrigger = async ({ canvasElement }: { canvasElement: HTMLElement }) => {
27
+ const canvas = within(canvasElement);
28
+ const button = canvas.queryByRole('button');
29
+ if (!button) return;
30
+ await userEvent.hover(button);
31
+ };
32
+
33
+ export const PositionTop: Story = {
34
+ render: () => (
35
+ <div style={containerStyle}>
36
+ <Tooltip label="Top positioned tooltip" position="top">
37
+ <Button>Top</Button>
38
+ </Tooltip>
39
+ </div>
40
+ ),
41
+ play: hoverTrigger,
42
+ ...iframeDiff,
43
+ };
44
+
45
+ export const PositionBottom: Story = {
46
+ render: () => (
47
+ <div style={containerStyle}>
48
+ <Tooltip label="Bottom positioned tooltip" position="bottom">
49
+ <Button>Bottom</Button>
50
+ </Tooltip>
51
+ </div>
52
+ ),
53
+ play: hoverTrigger,
54
+ ...iframeDiff,
55
+ };
56
+
57
+ export const PositionRight: Story = {
58
+ render: () => (
59
+ <div style={containerStyle}>
60
+ <Tooltip label="Right positioned tooltip" position="right">
61
+ <Button>Right</Button>
62
+ </Tooltip>
63
+ </div>
64
+ ),
65
+ play: hoverTrigger,
66
+ ...iframeDiff,
67
+ };
68
+
69
+ export const PositionLeft: Story = {
70
+ render: () => (
71
+ <div style={containerStyle}>
72
+ <Tooltip label="Left positioned tooltip" position="left">
73
+ <Button>Left</Button>
74
+ </Tooltip>
75
+ </div>
76
+ ),
77
+ play: hoverTrigger,
78
+ ...iframeDiff,
79
+ };
@@ -0,0 +1,90 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { userEvent, within } from 'storybook/test';
3
+ import { Search as SearchIcon } from '@transferwise/icons';
4
+
5
+ import { forEachColumn, withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
6
+ import { Size } from '../../common';
7
+ import Typeahead from '..';
8
+
9
+ export default {
10
+ component: Typeahead,
11
+ title: 'Forms/Typeahead/Tests/RTL Diff',
12
+ tags: ['!autodocs', '!manifest'],
13
+ } satisfies Meta<typeof Typeahead>;
14
+
15
+ type Story = StoryObj<typeof Typeahead>;
16
+
17
+ const baseOptions = [
18
+ { label: 'British pound', note: 'GBP' },
19
+ { label: 'Euro', note: 'EUR' },
20
+ { label: 'US Dollar', note: 'USD' },
21
+ ];
22
+
23
+ export const TriggerVariants: Story = {
24
+ render: () => (
25
+ <>
26
+ <Typeahead
27
+ id="rtl-addon-md"
28
+ name="rtl-addon-md"
29
+ placeholder="Search currencies…"
30
+ size={Size.MEDIUM}
31
+ addon={<SearchIcon size={24} />}
32
+ clearable
33
+ options={baseOptions}
34
+ initialValue={[{ label: 'British pound', note: 'GBP' }]}
35
+ onChange={() => {}}
36
+ />
37
+ <Typeahead
38
+ id="rtl-addon-lg"
39
+ name="rtl-addon-lg"
40
+ placeholder="Search currencies…"
41
+ size={Size.LARGE}
42
+ addon={<SearchIcon size={24} />}
43
+ clearable
44
+ options={baseOptions}
45
+ initialValue={[{ label: 'Euro', note: 'EUR' }]}
46
+ onChange={() => {}}
47
+ />
48
+ <Typeahead
49
+ id="rtl-multiple"
50
+ name="rtl-multiple"
51
+ placeholder="Search currencies…"
52
+ size={Size.MEDIUM}
53
+ addon={<SearchIcon size={24} />}
54
+ multiple
55
+ clearable
56
+ options={baseOptions}
57
+ initialValue={[
58
+ { label: 'British pound', note: 'GBP' },
59
+ { label: 'Euro', note: 'EUR' },
60
+ ]}
61
+ onChange={() => {}}
62
+ />
63
+ </>
64
+ ),
65
+ ...withRTLDiff({ width: '80%' }),
66
+ };
67
+
68
+ export const OpenDropdown: Story = {
69
+ render: () => (
70
+ <Typeahead
71
+ id="rtl-open"
72
+ name="rtl-open"
73
+ placeholder="Search currencies…"
74
+ size={Size.LARGE}
75
+ addon={<SearchIcon size={24} />}
76
+ clearable
77
+ options={baseOptions}
78
+ onChange={() => {}}
79
+ />
80
+ ),
81
+ play: async ({ canvasElement }) => {
82
+ await forEachColumn(canvasElement, async (column) => {
83
+ const scope = within(column);
84
+ const input = scope.getByRole('combobox');
85
+ await userEvent.click(input);
86
+ await userEvent.keyboard('Brit');
87
+ });
88
+ },
89
+ ...withRTLDiff({ width: '80%' }),
90
+ };
@@ -0,0 +1,53 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { userEvent, within } from 'storybook/test';
3
+
4
+ import { forEachColumn, withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
5
+ import Upload from '..';
6
+
7
+ export default {
8
+ component: Upload,
9
+ title: 'Forms/Upload/Tests/RTL Diff',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Upload>;
12
+
13
+ type Story = StoryObj<typeof Upload>;
14
+
15
+ export const Sizes: Story = {
16
+ render: () => (
17
+ <>
18
+ <Upload usLabel="Small upload" size="sm" />
19
+ <Upload usLabel="Medium upload" size="md" />
20
+ <Upload usLabel="Large upload" size="lg" />
21
+ </>
22
+ ),
23
+ ...withRTLDiff(),
24
+ };
25
+
26
+ export const WithError: Story = {
27
+ render: () => (
28
+ <Upload
29
+ usAccept="*"
30
+ usLabel="Upload a file"
31
+ usPlaceholder="Maximum filesize is 1B"
32
+ maxSize={1}
33
+ size="md"
34
+ httpOptions={{
35
+ url: 'https://httpbin.org/post',
36
+ method: 'POST',
37
+ }}
38
+ />
39
+ ),
40
+ play: async ({ canvasElement }) => {
41
+ await forEachColumn(canvasElement, async (column) => {
42
+ const fileInput = column.querySelector<HTMLInputElement>('input[type="file"]');
43
+ if (!fileInput) return;
44
+ const file = new File(['content larger than 1 byte'], 'test-file.txt', {
45
+ type: 'text/plain',
46
+ });
47
+ await userEvent.upload(fileInput, file);
48
+ const scope = within(column);
49
+ await scope.findByText(/Maximum filesize is/i, {}, { timeout: 3000 });
50
+ });
51
+ },
52
+ ...withRTLDiff(),
53
+ };
@@ -5,6 +5,7 @@ import { Status } from '../../common';
5
5
  import UploadInput, { UploadInputProps } from '../UploadInput';
6
6
  import { UploadedFile, UploadResponse } from '../types';
7
7
  import { userEvent } from 'storybook/test';
8
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
8
9
 
9
10
  const meta: Meta<typeof UploadInput> = {
10
11
  title: 'Forms/UploadInput/Tests',
@@ -300,3 +301,49 @@ export const DeletingBottom: Story = {
300
301
  await triggerModalAndConfirm();
301
302
  },
302
303
  };
304
+
305
+ const noOpUpload = async () => ({ id: 'upload-1' });
306
+ const noOpDelete = async () => {};
307
+
308
+ const mixedFiles = [
309
+ { id: 'file-1', filename: 'document-front.pdf', url: '#' },
310
+ { id: 'file-2', filename: 'succeeded-file.pdf', url: '#' },
311
+ { id: 'file-3', filename: 'failed-file.png', status: Status.FAILED },
312
+ { id: 'file-4', filename: 'valid-document.pdf', url: '#' },
313
+ {
314
+ id: 'file-5',
315
+ filename: 'too-large-image.png',
316
+ status: Status.FAILED,
317
+ errors: [
318
+ 'File size exceeds the 5MB limit',
319
+ 'Please compress the image or choose a smaller file',
320
+ 'Supported formats: JPG, PNG under 5MB',
321
+ ],
322
+ },
323
+ {
324
+ id: 'file-6',
325
+ filename: 'corrupted-file.pdf',
326
+ status: Status.FAILED,
327
+ error: 'File could not be processed',
328
+ },
329
+ ];
330
+
331
+ export const RTLDiff: Story = {
332
+ render: () => (
333
+ <>
334
+ <UploadInput onUploadFile={noOpUpload} />
335
+ <UploadInput
336
+ files={[{ id: 'file-s', filename: 'single-upload.pdf', url: '#' }]}
337
+ onUploadFile={noOpUpload}
338
+ onDeleteFile={noOpDelete}
339
+ />
340
+ <UploadInput
341
+ multiple
342
+ files={mixedFiles}
343
+ onUploadFile={noOpUpload}
344
+ onDeleteFile={noOpDelete}
345
+ />
346
+ </>
347
+ ),
348
+ ...withRTLDiff(),
349
+ };
@@ -2,7 +2,8 @@ import { useState } from 'react';
2
2
  import { Meta, StoryObj } from '@storybook/react-webpack5';
3
3
  import { userEvent, within, expect, waitFor } from 'storybook/test';
4
4
  import { Button, Field, SelectInput, Sentiment } from '../../..';
5
- import Alert, { type AlertProps } from '../Alert';
5
+ import Alert, { type AlertProps, AlertArrowPosition } from '../Alert';
6
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
6
7
 
7
8
  const meta = {
8
9
  title: 'Prompts/Alert/Tests',
@@ -131,3 +132,29 @@ export const MultipleDynamicAlerts: Story = {
131
132
  );
132
133
  },
133
134
  };
135
+
136
+ export const RTLDiff: Story = {
137
+ render: () => (
138
+ <>
139
+ <Alert message="Basic alert without dismiss button." />
140
+ <Alert message="Alert with dismiss button." onDismiss={() => {}} />
141
+ <Alert
142
+ title="With title and link action"
143
+ message="Alert with a link action and dismiss."
144
+ action={{ href: '#', text: 'Read more' }}
145
+ onDismiss={() => {}}
146
+ />
147
+ <Alert
148
+ title="With title and button action"
149
+ message="Alert with a button action."
150
+ action={{ onClick: () => {}, text: 'Open', as: 'button' }}
151
+ onDismiss={() => {}}
152
+ />
153
+ <Alert message="Arrow top left." arrow={AlertArrowPosition.TOP_LEFT} />
154
+ <Alert message="Arrow top right." arrow={AlertArrowPosition.TOP_RIGHT} />
155
+ <Alert message="Arrow bottom left." arrow={AlertArrowPosition.BOTTOM_LEFT} />
156
+ <Alert message="Arrow bottom right." arrow={AlertArrowPosition.BOTTOM_RIGHT} />
157
+ </>
158
+ ),
159
+ ...withRTLDiff(),
160
+ };
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { FastFlag as FastFlagIcon } from '@transferwise/icons';
3
+
4
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
5
+ import Card from '..';
6
+
7
+ export default {
8
+ component: Card,
9
+ title: 'Layouts/Card/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Card>;
12
+
13
+ type Story = StoryObj<typeof Card>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <>
18
+ <Card title="Basic card" details="Some details about this card" />
19
+ <Card
20
+ title="Card with icon"
21
+ details="Details with an icon on the side"
22
+ icon={<FastFlagIcon />}
23
+ />
24
+ <Card
25
+ title="Expanded card with icon"
26
+ details="Expanded card showing content area"
27
+ icon={<FastFlagIcon />}
28
+ isExpanded
29
+ >
30
+ Expanded content with padding affected by icon presence.
31
+ </Card>
32
+ <Card title="Expanded card without icon" details="No icon variant" isExpanded>
33
+ Expanded content without icon padding.
34
+ </Card>
35
+ </>
36
+ ),
37
+ ...withRTLDiff(),
38
+ };
@@ -2,6 +2,7 @@ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
 
3
3
  import CriticalCommsBanner from '..';
4
4
  import { withVariantConfig } from '../../../../.storybook/helpers';
5
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
5
6
 
6
7
  export default {
7
8
  component: CriticalCommsBanner,
@@ -83,3 +84,20 @@ export const WithoutAction: Story = {
83
84
  },
84
85
  ...withVariantConfig(['default']),
85
86
  };
87
+
88
+ export const RTLDiff: Story = {
89
+ render: () => (
90
+ <>
91
+ <CriticalCommsBanner
92
+ title="Your account is overdrawn"
93
+ subtitle="Add money within the next 30 days"
94
+ action={{ label: 'Take action', href: 'https://wise.com' }}
95
+ />
96
+ <CriticalCommsBanner
97
+ title="Your account is overdrawn"
98
+ subtitle="Add money within the next 30 days"
99
+ />
100
+ </>
101
+ ),
102
+ ...withRTLDiff(),
103
+ };
@@ -0,0 +1,26 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+
3
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
4
+ import InlineAlert from '..';
5
+
6
+ export default {
7
+ component: InlineAlert,
8
+ title: 'Prompts/InlineAlert/Tests',
9
+ tags: ['!autodocs', '!manifest'],
10
+ } satisfies Meta<typeof InlineAlert>;
11
+
12
+ type Story = StoryObj<typeof InlineAlert>;
13
+
14
+ export const RTLDiff: Story = {
15
+ render: () => (
16
+ <>
17
+ <InlineAlert type="neutral">Neutral alert without icon</InlineAlert>
18
+ <InlineAlert type="warning">Warning alert with icon</InlineAlert>
19
+ <InlineAlert type="negative">Negative alert with icon</InlineAlert>
20
+ <InlineAlert type="positive">
21
+ Positive alert with icon and longer content that may wrap to multiple lines
22
+ </InlineAlert>
23
+ </>
24
+ ),
25
+ ...withRTLDiff(),
26
+ };
@@ -1,9 +1,5 @@
1
- import { clsx } from 'clsx';
2
-
3
- import { Size } from '../../common';
4
- import { CloseButton } from '../../common/CloseButton';
5
- import FlowHeader from '../../common/FlowHeader';
6
1
  import Logo from '../../Logo';
2
+ import FlowNavigation from '../../FlowNavigation';
7
3
 
8
4
  /**
9
5
  * @deprecated Use `FlowNavigation` component instead, with `steps={[]}`
@@ -22,20 +18,5 @@ const defaultLogo = <Logo />;
22
18
  * @deprecated Use `FlowNavigation` component instead
23
19
  */
24
20
  export default function OverlayHeader({ avatar, onClose, logo = defaultLogo }: OverlayHeaderProps) {
25
- const closeButton = onClose && <CloseButton size={Size.LARGE} onClick={onClose} />;
26
- return (
27
- <div className="np-overlay-header d-flex justify-content-center">
28
- <FlowHeader
29
- className="np-overlay-header__content p-a-3"
30
- leftContent={logo}
31
- rightContent={
32
- <div className={clsx('d-flex', 'align-items-center', 'order-2')}>
33
- {avatar}
34
- {avatar && closeButton && <span className={clsx('m-x-1')} />}
35
- {closeButton}
36
- </div>
37
- }
38
- />
39
- </div>
40
- );
21
+ return <FlowNavigation {...{ avatar, onClose, logo }} />;
41
22
  }
@@ -0,0 +1,42 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Person } from '@transferwise/icons';
3
+
4
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
5
+ import AvatarView from '../../../AvatarView';
6
+ import Logo from '../../../Logo';
7
+ import OverlayHeader from '..';
8
+
9
+ export default {
10
+ component: OverlayHeader,
11
+ title: 'Navigation/OverlayHeader/Tests',
12
+ tags: ['!autodocs', '!manifest'],
13
+ } satisfies Meta<typeof OverlayHeader>;
14
+
15
+ type Story = StoryObj<typeof OverlayHeader>;
16
+
17
+ export const RTLDiff: Story = {
18
+ render: () => (
19
+ <>
20
+ <OverlayHeader logo={<Logo />} onClose={() => {}} />
21
+ <OverlayHeader
22
+ logo={<Logo />}
23
+ avatar={
24
+ <AvatarView>
25
+ <Person size="24" />
26
+ </AvatarView>
27
+ }
28
+ onClose={() => {}}
29
+ />
30
+ <OverlayHeader
31
+ logo={<Logo />}
32
+ avatar={
33
+ <AvatarView>
34
+ <Person size="24" />
35
+ </AvatarView>
36
+ }
37
+ />
38
+ <OverlayHeader logo={<Logo />} />
39
+ </>
40
+ ),
41
+ ...withRTLDiff(),
42
+ };
@@ -0,0 +1,71 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { userEvent, within } from 'storybook/test';
3
+ import { Person } from '@transferwise/icons';
4
+
5
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
6
+ import Select from '..';
7
+
8
+ export default {
9
+ component: Select,
10
+ title: 'Forms/Select/Tests/RTL Diff',
11
+ tags: ['!autodocs', '!manifest'],
12
+ } satisfies Meta<typeof Select>;
13
+
14
+ type Story = StoryObj<typeof Select>;
15
+
16
+ const options = [
17
+ { header: 'Popular' },
18
+ { value: 'gbp', label: 'British pound', currency: 'gbp', icon: <Person /> },
19
+ { value: 'eur', label: 'Euro', currency: 'eur', icon: <Person /> },
20
+ { value: 'usd', label: 'US Dollar', currency: 'usd', note: 'United States dollar' },
21
+ { separator: true },
22
+ { header: 'Other' },
23
+ { value: 'cad', label: 'Canadian dollar', currency: 'cad' },
24
+ { value: 'aud', label: 'Australian dollar', currency: 'aud' },
25
+ ];
26
+
27
+ const selected = { value: 'gbp', label: 'British pound', currency: 'gbp', icon: <Person /> };
28
+
29
+ export const TriggerVariants: Story = {
30
+ render: () => (
31
+ <>
32
+ <Select
33
+ size="lg"
34
+ placeholder="Select currency"
35
+ selected={selected}
36
+ options={options}
37
+ onChange={() => {}}
38
+ />
39
+ <Select
40
+ size="md"
41
+ placeholder="Select currency"
42
+ selected={selected}
43
+ options={options}
44
+ onChange={() => {}}
45
+ />
46
+ <Select size="sm" placeholder="Select currency" options={options} onChange={() => {}} />
47
+ </>
48
+ ),
49
+ ...withRTLDiff(),
50
+ };
51
+
52
+ export const OpenDropdown: Story = {
53
+ render: () => (
54
+ <Select
55
+ size="lg"
56
+ search
57
+ searchPlaceholder="Type a currency"
58
+ placeholder="Select currency"
59
+ selected={selected}
60
+ options={options}
61
+ onChange={() => {}}
62
+ />
63
+ ),
64
+ play: async ({ canvasElement }) => {
65
+ const canvas = within(canvasElement);
66
+ const trigger = canvas.queryByRole('button');
67
+ if (!trigger) return;
68
+ await userEvent.click(trigger);
69
+ },
70
+ ...withRTLDiff({ renderAs: 'iframe', width: '80%' }),
71
+ };