@transferwise/components 0.0.0-experimental-5f7dae1 → 0.0.0-experimental-20085a3

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 (81) hide show
  1. package/build/types/Body/Body.d.ts +2 -2
  2. package/build/types/IconButton/IconButton.d.ts +1 -1
  3. package/build/types/ListItem/_stories/variants/helpers.d.ts.map +1 -1
  4. package/build/types/MoneyInput/MoneyInput.d.ts +1 -1
  5. package/build/types/MoneyInput/MoneyInput.d.ts.map +1 -1
  6. package/build/types/Title/Title.d.ts +2 -2
  7. package/build/types/Upload/Steps/UploadImageStep/UploadImageStep.d.ts +1 -1
  8. package/build/types/UploadInput/UploadItem/UploadItemLink.d.ts +1 -1
  9. package/package.json +1 -1
  10. package/src/Accordion/_stories/Accordion.rtl.test.story.tsx +71 -0
  11. package/src/AvatarLayout/_stories/AvatarLayout.rtl.test.story.tsx +77 -0
  12. package/src/AvatarView/_stories/AvatarView.rtl.test.story.tsx +162 -0
  13. package/src/Button/LegacyButton/_stories/LegacyButton.rtl.test.story.tsx +32 -0
  14. package/src/Calendar/_stories/Calendar.rtl.test.story.tsx +52 -0
  15. package/src/Calendar/_stories/Calendar.test.story.tsx +28 -24
  16. package/src/Carousel/_stories/Carousel.rtl.test.story.tsx +61 -0
  17. package/src/Checkbox/_stories/Checkbox.rtl.test.story.tsx +31 -0
  18. package/src/CheckboxButton/_stories/CheckboxButton.rtl.test.story.tsx +27 -0
  19. package/src/CheckboxButton/_stories/CheckboxButton.test.story.tsx +0 -37
  20. package/src/Chevron/_stories/Chevron.rtl.test.story.tsx +26 -0
  21. package/src/Chips/_stories/Chips.rtl.test.story.tsx +49 -0
  22. package/src/Chips/_stories/Chips.test.story.tsx +0 -34
  23. package/src/CircularButton/_stories/CircularButton.test.story.tsx +0 -68
  24. package/src/DateInput/_stories/DateInput.rtl.test.story.tsx +25 -0
  25. package/src/DateLookup/_stories/DateLookup.rtl.test.story.tsx +88 -0
  26. package/src/Decision/_stories/Decision.rtl.test.story.tsx +79 -0
  27. package/src/DefinitionList/_stories/DefinitionList.rtl.test.story.tsx +63 -0
  28. package/src/Drawer/_stories/Drawer.rtl.test.story.tsx +58 -0
  29. package/src/ExpressiveMoneyInput/_stories/ExpressiveMoneyInput.rtl.test.story.tsx +118 -0
  30. package/src/Field/_stories/Field.rtl.test.story.tsx +58 -0
  31. package/src/FlowNavigation/_stories/FlowNavigation.rtl.test.story.tsx +70 -0
  32. package/src/Header/_stories/Header.rtl.test.story.tsx +37 -0
  33. package/src/Info/_stories/Info.rtl.test.story.tsx +64 -0
  34. package/src/Inputs/SelectInput/_stories/SelectInput.rtl.test.story.tsx +135 -0
  35. package/src/Inputs/_stories/InputGroup.rtl.test.story.tsx +69 -0
  36. package/src/Inputs/_stories/SearchInput.rtl.test.story.tsx +32 -0
  37. package/src/Inputs/_stories/TextArea.rtl.test.story.tsx +38 -0
  38. package/src/InstructionsList/_stories/InstructionsList.rtl.test.story.tsx +30 -0
  39. package/src/Label/_stories/Label.rtl.test.story.tsx +36 -0
  40. package/src/Link/_stories/Link.rtl.test.story.tsx +26 -0
  41. package/src/ListItem/_stories/{variants/ListItem.rtl.test.story.tsx → ListItem.rtl.test.story.tsx} +6 -10
  42. package/src/ListItem/_stories/variants/helpers.tsx +2 -6
  43. package/src/Logo/_stories/Logo.rtl.test.story.tsx +56 -0
  44. package/src/Modal/_stories/Modal.rtl.test.story.tsx +59 -0
  45. package/src/MoneyInput/_stories/MoneyInput.rtl.test.story.tsx +88 -0
  46. package/src/Nudge/_stories/Nudge.rtl.test.story.tsx +37 -0
  47. package/src/PhoneNumberInput/_stories/PhoneNumberInput.rtl.test.story.tsx +44 -0
  48. package/src/Popover/_stories/Popover.rtl.test.story.tsx +96 -0
  49. package/src/Progress/_stories/Progress.rtl.test.story.tsx +27 -0
  50. package/src/ProgressBar/_stories/ProgressBar.rtl.test.story.tsx +33 -0
  51. package/src/PromoCard/_stories/PromoCard.rtl.test.story.tsx +42 -0
  52. package/src/PromoCard/_stories/PromoCardGroup.rtl.test.story.tsx +51 -0
  53. package/src/Prompt/ActionPrompt/_stories/ActionPrompt.rtl.test.story.tsx +53 -0
  54. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.rtl.test.story.tsx +46 -0
  55. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.test.story.tsx +0 -30
  56. package/src/Prompt/InfoPrompt/_stories/InfoPrompt.rtl.test.story.tsx +36 -0
  57. package/src/Prompt/InlinePrompt/_stories/InlinePrompt.rtl.test.story.tsx +38 -0
  58. package/src/Radio/_stories/Radio.rtl.test.story.tsx +61 -0
  59. package/src/RadioGroup/_stories/RadioGroup.rtl.test.story.tsx +66 -0
  60. package/src/Section/_stories/Section.rtl.test.story.tsx +29 -0
  61. package/src/SegmentedControl/_stories/SegmentedControl.rtl.test.story.tsx +45 -0
  62. package/src/SlidingPanel/_stories/SlidingPanel.rtl.test.story.tsx +70 -0
  63. package/src/Snackbar/_stories/Snackbar.rtl.test.story.tsx +45 -0
  64. package/src/Snackbar/_stories/Snackbar.test.story.tsx +0 -31
  65. package/src/Stepper/_stories/Stepper.rtl.test.story.tsx +24 -0
  66. package/src/Switch/_stories/Switch.rtl.test.story.tsx +32 -0
  67. package/src/Switch/_stories/Switch.test.story.tsx +0 -26
  68. package/src/Table/_stories/Table.rtl.test.story.tsx +104 -0
  69. package/src/Tabs/_stories/Tabs.rtl.test.story.tsx +72 -0
  70. package/src/TextareaWithDisplayFormat/_stories/TextareaWithDisplayFormat.rtl.test.story.tsx +48 -0
  71. package/src/Tooltip/_stories/Tooltip.rtl.test.story.tsx +79 -0
  72. package/src/Typeahead/_stories/Typeahead.rtl.test.story.tsx +90 -0
  73. package/src/Upload/_stories/Upload.rtl.test.story.tsx +53 -0
  74. package/src/UploadInput/_stories/UploadInput.rtl.test.story.tsx +59 -0
  75. package/src/_deprecated/Alert/_stories/Alert.rtl.test.story.tsx +37 -0
  76. package/src/_deprecated/Card/_stories/Card.rtl.test.story.tsx +38 -0
  77. package/src/_deprecated/CriticalBanner/_stories/CriticalCommsBanner.rtl.test.story.tsx +28 -0
  78. package/src/_deprecated/InlineAlert/_stories/InlineAlert.rtl.test.story.tsx +26 -0
  79. package/src/_deprecated/OverlayHeader/_stories/OverlayHeader.rtl.test.story.tsx +42 -0
  80. package/src/_deprecated/Select/_stories/Select.rtl.test.story.tsx +71 -0
  81. package/src/common/BottomSheet/_stories/BottomSheet.rtl.test.story.tsx +39 -0
@@ -0,0 +1,53 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Bank } from '@transferwise/icons';
3
+
4
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
5
+ import ActionPrompt from '../ActionPrompt';
6
+
7
+ export default {
8
+ component: ActionPrompt,
9
+ title: 'Prompts/ActionPrompt/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof ActionPrompt>;
12
+
13
+ type Story = StoryObj<typeof ActionPrompt>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <>
18
+ <ActionPrompt
19
+ title="Default status icon"
20
+ description="No media provided, uses default sentiment icon."
21
+ action={{ label: 'Continue' }}
22
+ />
23
+ <ActionPrompt
24
+ title="Custom image"
25
+ description="Media with a custom image source."
26
+ media={{ imgSrc: '../../wise-card.svg' }}
27
+ action={{ label: 'View card' }}
28
+ />
29
+ <ActionPrompt
30
+ title="Avatar with icon"
31
+ description="Media with an avatar containing a custom icon."
32
+ media={{ avatar: { asset: <Bank /> } }}
33
+ action={{ label: 'Connect bank' }}
34
+ />
35
+ <ActionPrompt
36
+ title="Primary and secondary actions"
37
+ description="Both action buttons present."
38
+ media={{ avatar: { asset: <Bank /> } }}
39
+ action={{ label: 'Confirm' }}
40
+ actionSecondary={{ label: 'Cancel' }}
41
+ />
42
+ <ActionPrompt
43
+ title="Dismissible with two actions"
44
+ description="Close button and both action buttons."
45
+ media={{ avatar: { asset: <Bank /> } }}
46
+ action={{ label: 'Confirm' }}
47
+ actionSecondary={{ label: 'Cancel' }}
48
+ onDismiss={() => {}}
49
+ />
50
+ </>
51
+ ),
52
+ ...withRTLDiff(),
53
+ };
@@ -0,0 +1,46 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Bank } from '@transferwise/icons';
3
+
4
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
5
+ import CriticalBanner from '../CriticalBanner';
6
+
7
+ export default {
8
+ component: CriticalBanner,
9
+ title: 'Prompts/CriticalBanner/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof CriticalBanner>;
12
+
13
+ type Story = StoryObj<typeof CriticalBanner>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <>
18
+ <CriticalBanner title="Title only" description="Description without actions or media." />
19
+ <CriticalBanner
20
+ title="With primary action"
21
+ description="Banner with a single action button."
22
+ action={{ label: 'Verify now' }}
23
+ />
24
+ <CriticalBanner
25
+ title="With both actions"
26
+ description="Banner with primary and secondary actions."
27
+ action={{ label: 'Verify now' }}
28
+ actionSecondary={{ label: 'Learn more' }}
29
+ />
30
+ <CriticalBanner
31
+ title="With media image"
32
+ description="Banner with a custom image."
33
+ media={{ imgSrc: '../../wise-card.svg', 'aria-label': 'Wise card' }}
34
+ action={{ label: 'Take action' }}
35
+ />
36
+ <CriticalBanner
37
+ title="With avatar media"
38
+ description="Banner with an avatar icon."
39
+ media={{ avatar: { asset: <Bank /> } }}
40
+ action={{ label: 'Connect bank' }}
41
+ actionSecondary={{ label: 'Learn more' }}
42
+ />
43
+ </>
44
+ ),
45
+ ...withRTLDiff(),
46
+ };
@@ -325,36 +325,6 @@ export const LiveRegionAnnouncements: Story = {
325
325
  },
326
326
  };
327
327
 
328
- /** Right-to-left layout regression test. */
329
- export const RTL: Story = {
330
- render: function Render() {
331
- const [expanded, setExpanded] = useState(true);
332
- const [collapsed, setCollapsed] = useState(false);
333
-
334
- return (
335
- <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', width: '100%' }}>
336
- <CriticalBanner
337
- sentiment="negative"
338
- title="Your account requires verification"
339
- description="Please verify your identity to continue using all features."
340
- action={{ label: 'Verify now', onClick: fn() }}
341
- actionSecondary={{ label: 'Learn more', onClick: fn() }}
342
- expanded={expanded}
343
- onToggle={() => setExpanded(!expanded)}
344
- />
345
- <CriticalBanner
346
- sentiment="warning"
347
- title="Collapsed state"
348
- description="This banner is collapsed."
349
- action={{ label: 'Take action', onClick: fn() }}
350
- expanded={collapsed}
351
- onToggle={() => setCollapsed(!collapsed)}
352
- />
353
- </div>
354
- );
355
- },
356
- ...withVariantConfig(['rtl']),
357
- };
358
328
 
359
329
  /** 400% zoom regression test with all variants. */
360
330
  export const Zoom400: Story = {
@@ -0,0 +1,36 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Star } from '@transferwise/icons';
3
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
4
+ import { InfoPrompt } from '..';
5
+
6
+ export default {
7
+ component: InfoPrompt,
8
+ title: 'Prompts/InfoPrompt/Tests',
9
+ tags: ['!autodocs', '!manifest'],
10
+ } satisfies Meta<typeof InfoPrompt>;
11
+
12
+ type Story = StoryObj<typeof InfoPrompt>;
13
+
14
+ export const RTLDiff: Story = {
15
+ render: () => (
16
+ <>
17
+ <InfoPrompt description="Basic description only." />
18
+ <InfoPrompt title="With Title" description="Description with a title above it." />
19
+ <InfoPrompt description="Dismissible prompt." onDismiss={() => {}} />
20
+ <InfoPrompt
21
+ title="With Action"
22
+ description="Description with an action link below."
23
+ action={{ label: 'Learn more', href: '#' }}
24
+ />
25
+ <InfoPrompt description="Custom media icon." media={{ asset: <Star title="Starred" /> }} />
26
+ <InfoPrompt
27
+ title="All Options"
28
+ description="Title, action, dismiss, and custom media combined."
29
+ media={{ asset: <Star title="Starred" /> }}
30
+ action={{ label: 'View details', href: '#' }}
31
+ onDismiss={() => {}}
32
+ />
33
+ </>
34
+ ),
35
+ ...withRTLDiff(),
36
+ };
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Suitcase } from '@transferwise/icons';
3
+ import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
4
+ import { InlinePrompt } from '../..';
5
+
6
+ export default {
7
+ component: InlinePrompt,
8
+ title: 'Prompts/InlinePrompt/Tests',
9
+ tags: ['!autodocs', '!manifest'],
10
+ } satisfies Meta<typeof InlinePrompt>;
11
+
12
+ type Story = StoryObj<typeof InlinePrompt>;
13
+
14
+ export const RTLDiff: Story = {
15
+ render: () => (
16
+ <>
17
+ {/* default icon at inline-start, auto width */}
18
+ <InlinePrompt sentiment="positive">Short content with default icon.</InlinePrompt>
19
+
20
+ {/* custom media icon, auto width */}
21
+ <InlinePrompt sentiment="positive" media={<Suitcase />}>
22
+ Custom icon with auto width.
23
+ </InlinePrompt>
24
+
25
+ {/* full width — icon position flips */}
26
+ <InlinePrompt sentiment="positive" media={<Suitcase />} width="full">
27
+ Custom icon with full width.
28
+ </InlinePrompt>
29
+
30
+ {/* multi-line content — verifies wrapping alignment */}
31
+ <InlinePrompt sentiment="warning" width="full">
32
+ This prompt has longer content that may wrap to multiple lines to verify that the icon
33
+ alignment remains correct in RTL layout.
34
+ </InlinePrompt>
35
+ </>
36
+ ),
37
+ ...withRTLDiff(),
38
+ };
@@ -0,0 +1,61 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Flag } from '@wise/art';
3
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
+ import AvatarView from '../../AvatarView';
5
+ import Radio from '../Radio';
6
+
7
+ export default {
8
+ component: Radio,
9
+ title: 'Forms/Radio/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Radio>;
12
+
13
+ type Story = StoryObj<typeof Radio>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <>
18
+ <Radio
19
+ label="Standard option"
20
+ name="radio-rtl"
21
+ id="radio-rtl-basic"
22
+ value="basic"
23
+ onChange={() => {}}
24
+ />
25
+ <Radio
26
+ label="Option with secondary text"
27
+ secondary="Secondary description"
28
+ name="radio-rtl"
29
+ id="radio-rtl-secondary"
30
+ value="secondary"
31
+ onChange={() => {}}
32
+ />
33
+ <Radio
34
+ label="Option with avatar"
35
+ name="radio-rtl"
36
+ id="radio-rtl-avatar"
37
+ value="avatar"
38
+ avatar={
39
+ <AvatarView size={40}>
40
+ <Flag code="IM" />
41
+ </AvatarView>
42
+ }
43
+ onChange={() => {}}
44
+ />
45
+ <Radio
46
+ label="Option with secondary text and avatar"
47
+ secondary="Secondary description"
48
+ name="radio-rtl"
49
+ id="radio-rtl-secondary-avatar"
50
+ value="secondary-avatar"
51
+ avatar={
52
+ <AvatarView size={40}>
53
+ <Flag code="IM" />
54
+ </AvatarView>
55
+ }
56
+ onChange={() => {}}
57
+ />
58
+ </>
59
+ ),
60
+ ...withRTLDiff(),
61
+ };
@@ -0,0 +1,66 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { Flag } from '@wise/art';
3
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
+ import AvatarView from '../../AvatarView';
5
+ import RadioGroup from '../RadioGroup';
6
+
7
+ export default {
8
+ component: RadioGroup,
9
+ title: 'Forms/RadioGroup/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof RadioGroup>;
12
+
13
+ type Story = StoryObj<typeof RadioGroup>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <>
18
+ <RadioGroup
19
+ name="radio-group-rtl-basic"
20
+ selectedValue="option-1"
21
+ radios={[
22
+ { value: 'option-1', label: 'Option one' },
23
+ { value: 'option-2', label: 'Option two' },
24
+ { value: 'option-3', label: 'Option three' },
25
+ ]}
26
+ onChange={() => {}}
27
+ />
28
+ <RadioGroup
29
+ name="radio-group-rtl-secondary"
30
+ selectedValue="option-a"
31
+ radios={[
32
+ { value: 'option-a', label: 'Option A', secondary: 'Secondary text for A' },
33
+ { value: 'option-b', label: 'Option B', secondary: 'Secondary text for B' },
34
+ ]}
35
+ onChange={() => {}}
36
+ />
37
+ <RadioGroup
38
+ name="radio-group-rtl-avatar"
39
+ selectedValue="option-x"
40
+ radios={[
41
+ {
42
+ value: 'option-x',
43
+ label: 'Option X',
44
+ avatar: (
45
+ <AvatarView size={40}>
46
+ <Flag code="IM" />
47
+ </AvatarView>
48
+ ),
49
+ },
50
+ {
51
+ value: 'option-y',
52
+ label: 'Option Y',
53
+ secondary: 'With secondary and avatar',
54
+ avatar: (
55
+ <AvatarView size={40}>
56
+ <Flag code="IM" />
57
+ </AvatarView>
58
+ ),
59
+ },
60
+ ]}
61
+ onChange={() => {}}
62
+ />
63
+ </>
64
+ ),
65
+ ...withRTLDiff(),
66
+ };
@@ -0,0 +1,29 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+
3
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
+ import Header from '../../Header';
5
+ import Section from '..';
6
+
7
+ export default {
8
+ component: Section,
9
+ title: 'Content/Section/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Section>;
12
+
13
+ type Story = StoryObj<typeof Section>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <>
18
+ <Section>
19
+ <Header title="Default section" />
20
+ Section content without horizontal padding.
21
+ </Section>
22
+ <Section withHorizontalPadding>
23
+ <Header title="With horizontal padding" />
24
+ Section content with horizontal padding applied.
25
+ </Section>
26
+ </>
27
+ ),
28
+ ...withRTLDiff(),
29
+ };
@@ -0,0 +1,45 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
3
+ import SegmentedControl from '../SegmentedControl';
4
+
5
+ export default {
6
+ component: SegmentedControl,
7
+ title: 'Forms/SegmentedControl/Tests',
8
+ tags: ['!autodocs', '!manifest'],
9
+ } satisfies Meta<typeof SegmentedControl>;
10
+
11
+ type Story = StoryObj<typeof SegmentedControl>;
12
+
13
+ const inputSegments = [
14
+ { id: 'seg-one', label: 'One', value: 'one' },
15
+ { id: 'seg-two', label: 'Two', value: 'two' },
16
+ { id: 'seg-three', label: 'Three', value: 'three' },
17
+ ] as const;
18
+
19
+ const viewSegments = [
20
+ { id: 'seg-alpha', label: 'Alpha', value: 'alpha', controls: 'panel-alpha' },
21
+ { id: 'seg-beta', label: 'Beta', value: 'beta', controls: 'panel-beta' },
22
+ { id: 'seg-gamma', label: 'Gamma', value: 'gamma', controls: 'panel-gamma' },
23
+ ] as const;
24
+
25
+ export const RTLDiff: Story = {
26
+ render: () => (
27
+ <>
28
+ <SegmentedControl
29
+ name="rtl-input"
30
+ mode="input"
31
+ segments={inputSegments}
32
+ value="one"
33
+ onChange={() => {}}
34
+ />
35
+ <SegmentedControl
36
+ name="rtl-view"
37
+ mode="view"
38
+ segments={viewSegments}
39
+ value="alpha"
40
+ onChange={() => {}}
41
+ />
42
+ </>
43
+ ),
44
+ ...withRTLDiff(),
45
+ };
@@ -0,0 +1,70 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+
3
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
+ import SlidingPanel from '../SlidingPanel';
5
+
6
+ export default {
7
+ component: SlidingPanel,
8
+ title: 'Dialogs/SlidingPanel/Tests/RTL Diff',
9
+ tags: ['!autodocs', '!manifest'],
10
+ } satisfies Meta<typeof SlidingPanel>;
11
+
12
+ type Story = StoryObj<typeof SlidingPanel>;
13
+
14
+ const iframeDiff = withRTLDiff({ renderAs: 'iframe' });
15
+
16
+ const containerStyle: React.CSSProperties = {
17
+ position: 'relative',
18
+ width: 300,
19
+ height: 120,
20
+ overflow: 'hidden',
21
+ border: '1px dashed #ccc',
22
+ };
23
+
24
+ const panelContentStyle: React.CSSProperties = {
25
+ padding: '16px',
26
+ };
27
+
28
+ export const PositionLeft: Story = {
29
+ render: () => (
30
+ <div style={containerStyle}>
31
+ <SlidingPanel open position="left">
32
+ <div style={panelContentStyle}>Left panel content</div>
33
+ </SlidingPanel>
34
+ </div>
35
+ ),
36
+ ...iframeDiff,
37
+ };
38
+
39
+ export const PositionRight: Story = {
40
+ render: () => (
41
+ <div style={containerStyle}>
42
+ <SlidingPanel open position="right">
43
+ <div style={panelContentStyle}>Right panel content</div>
44
+ </SlidingPanel>
45
+ </div>
46
+ ),
47
+ ...iframeDiff,
48
+ };
49
+
50
+ export const PositionLeftWithBorder: Story = {
51
+ render: () => (
52
+ <div style={containerStyle}>
53
+ <SlidingPanel open position="left" showSlidingPanelBorder>
54
+ <div style={panelContentStyle}>Left panel with border</div>
55
+ </SlidingPanel>
56
+ </div>
57
+ ),
58
+ ...iframeDiff,
59
+ };
60
+
61
+ export const PositionRightWithBorder: Story = {
62
+ render: () => (
63
+ <div style={containerStyle}>
64
+ <SlidingPanel open position="right" showSlidingPanelBorder>
65
+ <div style={panelContentStyle}>Right panel with border</div>
66
+ </SlidingPanel>
67
+ </div>
68
+ ),
69
+ ...iframeDiff,
70
+ };
@@ -0,0 +1,45 @@
1
+ import { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
3
+
4
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
5
+ import { Snackbar } from '../Snackbar';
6
+
7
+ export default {
8
+ component: Snackbar,
9
+ title: 'Dialogs/Snackbar/Tests/RTL Diff',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Snackbar>;
12
+
13
+ type Story = StoryObj<typeof Snackbar>;
14
+
15
+ const TIMEOUT = 10_000_000;
16
+ const iframeDiff = withRTLDiff({ renderAs: 'iframe' });
17
+
18
+ function RenderWithAction() {
19
+ const [timestamp] = useState(() => Date.now());
20
+
21
+ return (
22
+ <Snackbar
23
+ text={<span>Transfer completed successfully</span>}
24
+ timestamp={timestamp}
25
+ timeout={TIMEOUT}
26
+ action={{ label: 'View' }}
27
+ />
28
+ );
29
+ }
30
+
31
+ function RenderWithoutAction() {
32
+ const [timestamp] = useState(() => Date.now());
33
+
34
+ return <Snackbar text={<span>Settings saved</span>} timestamp={timestamp} timeout={TIMEOUT} />;
35
+ }
36
+
37
+ export const WithAction: Story = {
38
+ render: () => <RenderWithAction />,
39
+ ...iframeDiff,
40
+ };
41
+
42
+ export const WithoutAction: Story = {
43
+ render: () => <RenderWithoutAction />,
44
+ ...iframeDiff,
45
+ };
@@ -103,37 +103,6 @@ export const DarkMode = {
103
103
  ...withVariantConfig(['dark'], Default),
104
104
  };
105
105
 
106
- const switchToRTL = async (context: { canvasElement: HTMLElement }) => {
107
- await Default.play(context);
108
- // the snackbar is outside the storybook dom so the RTL variant doesn't apply
109
- const body = document.querySelector('div.storybook-container');
110
- if (body) {
111
- body.setAttribute('dir', 'rtl');
112
- }
113
- const snackbar = document.querySelector('div.snackbar');
114
- if (snackbar) {
115
- snackbar.setAttribute('dir', 'rtl');
116
- }
117
- };
118
-
119
- export const RTL = {
120
- ...Default,
121
- args: {
122
- ...Default.args,
123
- },
124
- play: switchToRTL,
125
- ...withVariantConfig(['rtl'], Default),
126
- };
127
-
128
- export const RTLMobile = {
129
- ...Default,
130
- args: {
131
- ...RTL.args,
132
- },
133
- play: switchToRTL,
134
- ...withVariantConfig(['rtl', 'mobile'], Default),
135
- };
136
-
137
106
  export const Zoom400 = {
138
107
  ...Default,
139
108
  args: {
@@ -0,0 +1,24 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
3
+ import Stepper from '../Stepper';
4
+
5
+ const STEPS = [{ label: 'Amount' }, { label: 'You' }, { label: 'Review' }, { label: 'Pay' }];
6
+
7
+ export default {
8
+ component: Stepper,
9
+ title: 'Navigation/Stepper/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Stepper>;
12
+
13
+ type Story = StoryObj<typeof Stepper>;
14
+
15
+ export const RTLDiff: Story = {
16
+ render: () => (
17
+ <div style={{ width: '80%', marginLeft: 'auto', marginRight: 'auto' }}>
18
+ <Stepper steps={STEPS} activeStep={0} />
19
+ <Stepper steps={STEPS} activeStep={2} />
20
+ <Stepper steps={STEPS} activeStep={4} />
21
+ </div>
22
+ ),
23
+ ...withRTLDiff(),
24
+ };
@@ -0,0 +1,32 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+
3
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
+ import Field from '../../Field/Field';
5
+ import Switch from '..';
6
+
7
+ export default {
8
+ component: Switch,
9
+ title: 'Actions/Switch/Tests',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof Switch>;
12
+
13
+ type Story = StoryObj<typeof Switch>;
14
+
15
+ /**
16
+ * The switch thumb translates horizontally: in LTR checked state it moves right,
17
+ * in RTL checked state it moves left (via [dir="rtl"] CSS). This diff verifies
18
+ * the thumb direction flips correctly between writing modes.
19
+ */
20
+ export const RTLDiff: Story = {
21
+ render: () => (
22
+ <>
23
+ <Field label="Unchecked">
24
+ <Switch checked={false} onClick={() => {}} />
25
+ </Field>
26
+ <Field label="Checked">
27
+ <Switch checked onClick={() => {}} />
28
+ </Field>
29
+ </>
30
+ ),
31
+ ...withRTLDiff(),
32
+ };
@@ -83,32 +83,6 @@ export const KeyboardInteraction: Story = {
83
83
  },
84
84
  };
85
85
 
86
- /** Switch rendered in RTL mode. */
87
- export const RTL: Story = {
88
- render: function Render() {
89
- const [unchecked, setUnchecked] = useState(false);
90
- const [checked, setChecked] = useState(true);
91
-
92
- return (
93
- <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px' }}>
94
- <Field label="Unchecked">
95
- <Switch checked={unchecked} onClick={() => setUnchecked((v) => !v)} />
96
- </Field>
97
- <Field label="Checked">
98
- <Switch checked={checked} onClick={() => setChecked((v) => !v)} />
99
- </Field>
100
- <Field label="Disabled (off)">
101
- <Switch checked={false} disabled onClick={() => {}} />
102
- </Field>
103
- <Field label="Disabled (on)">
104
- <Switch checked disabled onClick={() => {}} />
105
- </Field>
106
- </div>
107
- );
108
- },
109
- ...withVariantConfig(['rtl']),
110
- };
111
-
112
86
  /** Switch at 400% zoom for accessibility testing. */
113
87
  export const Zoom400: Story = {
114
88
  render: function Render() {