@transferwise/components 46.165.0 → 46.165.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 (86) hide show
  1. package/build/Snackbar/Snackbar.js +98 -101
  2. package/build/Snackbar/Snackbar.js.map +1 -1
  3. package/build/Snackbar/Snackbar.mjs +99 -102
  4. package/build/Snackbar/Snackbar.mjs.map +1 -1
  5. package/build/types/Body/Body.d.ts +2 -2
  6. package/build/types/Carousel/_stories/constants.d.ts +25 -0
  7. package/build/types/Carousel/_stories/constants.d.ts.map +1 -1
  8. package/build/types/IconButton/IconButton.d.ts +1 -1
  9. package/build/types/ListItem/_stories/variants/helpers.d.ts +38 -1
  10. package/build/types/ListItem/_stories/variants/helpers.d.ts.map +1 -1
  11. package/build/types/MoneyInput/MoneyInput.d.ts +1 -1
  12. package/build/types/MoneyInput/MoneyInput.d.ts.map +1 -1
  13. package/build/types/Snackbar/Snackbar.d.ts +1 -15
  14. package/build/types/Snackbar/Snackbar.d.ts.map +1 -1
  15. package/build/types/Title/Title.d.ts +2 -2
  16. package/build/types/Upload/Steps/UploadImageStep/UploadImageStep.d.ts +1 -1
  17. package/build/types/UploadInput/UploadItem/UploadItemLink.d.ts +1 -1
  18. package/package.json +1 -1
  19. package/src/Accordion/_stories/Accordion.test.story.tsx +74 -48
  20. package/src/AvatarLayout/_stories/AvatarLayout.test.story.tsx +46 -30
  21. package/src/Button/LegacyButton/_stories/LegacyButton.test.story.tsx +29 -19
  22. package/src/Button/_stories/Button.test.story.tsx +96 -62
  23. package/src/Calendar/_stories/Calendar.test.story.tsx +34 -21
  24. package/src/Carousel/_stories/Carousel.test.story.tsx +18 -8
  25. package/src/Carousel/_stories/constants.tsx +29 -4
  26. package/src/Checkbox/_stories/Checkbox.test.story.tsx +22 -13
  27. package/src/CheckboxButton/_stories/CheckboxButton.test.story.tsx +23 -14
  28. package/src/Chips/_stories/Chips.test.story.tsx +51 -36
  29. package/src/DateInput/_stories/DateInput.rtl.test.story.tsx +62 -12
  30. package/src/DateLookup/_stories/DateLookup.rtl.test.story.tsx +2 -2
  31. package/src/Decision/_stories/Decision.test.story.tsx +74 -58
  32. package/src/DefinitionList/_stories/DefinitionList.test.story.tsx +58 -42
  33. package/src/Drawer/_stories/Drawer.rtl.test.story.tsx +65 -38
  34. package/src/ExpressiveMoneyInput/_stories/ExpressiveMoneyInput.rtl.test.story.tsx +107 -74
  35. package/src/Field/_stories/Field.test.story.tsx +18 -18
  36. package/src/FlowNavigation/_stories/FlowNavigation.rtl.test.story.tsx +81 -51
  37. package/src/Header/_stories/Header.test.story.tsx +30 -18
  38. package/src/Info/_stories/Info.rtl.test.story.tsx +124 -50
  39. package/src/InputWithDisplayFormat/_stories/InputWithDisplayFormat.test.story.tsx +4 -4
  40. package/src/Inputs/InputGroup/_stories/InputGroup.test.story.tsx +9 -8
  41. package/src/Inputs/SearchInput/_stories/SearchInput.test.story.tsx +5 -3
  42. package/src/Inputs/SelectInput/_stories/SelectInput.rtl.test.story.tsx +108 -79
  43. package/src/Inputs/TextArea/_stories/TextArea.test.story.tsx +10 -10
  44. package/src/InstructionsList/_stories/InstructionsList.test.story.tsx +43 -16
  45. package/src/Label/_stories/Label.test.story.tsx +7 -7
  46. package/src/Link/_stories/Link.test.story.tsx +27 -13
  47. package/src/ListItem/_stories/ListItem.rtl.test.story.tsx +126 -6
  48. package/src/ListItem/_stories/variants/helpers.tsx +174 -126
  49. package/src/Loader/_stories/Loader.test.story.tsx +17 -10
  50. package/src/Modal/_stories/Modal.rtl.test.story.tsx +58 -39
  51. package/src/MoneyInput/_stories/MoneyInput.rtl.test.story.tsx +21 -3
  52. package/src/Nudge/_stories/Nudge.test.story.tsx +70 -21
  53. package/src/PhoneNumberInput/_stories/PhoneNumberInput.rtl.test.story.tsx +1 -1
  54. package/src/Popover/_stories/Popover.rtl.test.story.tsx +92 -49
  55. package/src/ProgressBar/_stories/ProgressBar.test.story.tsx +6 -6
  56. package/src/PromoCard/_stories/PromoCard.test.story.tsx +53 -29
  57. package/src/PromoCard/_stories/PromoCardGroup.test.story.tsx +60 -36
  58. package/src/Prompt/ActionPrompt/_stories/ActionPrompt.test.story.tsx +74 -38
  59. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.test.story.tsx +68 -31
  60. package/src/Prompt/InfoPrompt/_stories/InfoPrompt.test.story.tsx +52 -22
  61. package/src/Prompt/InlinePrompt/_stories/InlinePrompt.test.story.tsx +36 -21
  62. package/src/Radio/_stories/Radio.test.story.tsx +60 -46
  63. package/src/RadioGroup/_stories/RadioGroup.test.story.tsx +70 -51
  64. package/src/Section/_stories/Section.test.story.tsx +30 -14
  65. package/src/SegmentedControl/_stories/SegmentedControl.test.story.tsx +38 -15
  66. package/src/SlidingPanel/_stories/SlidingPanel.rtl.test.story.tsx +58 -34
  67. package/src/Snackbar/Snackbar.test.tsx +16 -0
  68. package/src/Snackbar/Snackbar.tsx +91 -88
  69. package/src/Snackbar/_stories/Snackbar.rtl.test.story.tsx +24 -12
  70. package/src/Stepper/_stories/Stepper.test.story.tsx +27 -9
  71. package/src/Switch/_stories/Switch.test.story.tsx +20 -12
  72. package/src/Table/_stories/Table.test.story.tsx +107 -86
  73. package/src/Tabs/_stories/Tabs.test.story.tsx +92 -52
  74. package/src/Tag/_stories/Tag.test.story.tsx +27 -16
  75. package/src/TextareaWithDisplayFormat/_stories/TextareaWithDisplayFormat.test.story.tsx +4 -4
  76. package/src/Tooltip/_stories/Tooltip.rtl.test.story.tsx +68 -25
  77. package/src/Typeahead/_stories/Typeahead.rtl.test.story.tsx +4 -4
  78. package/src/Upload/_stories/Upload.rtl.test.story.tsx +49 -26
  79. package/src/UploadInput/_stories/UploadInput.test.story.tsx +63 -41
  80. package/src/_deprecated/Alert/_stories/Alert.test.story.tsx +45 -24
  81. package/src/_deprecated/Card/_stories/Card.test.story.tsx +47 -23
  82. package/src/_deprecated/CriticalBanner/_stories/CriticalCommsBanner.test.story.tsx +21 -15
  83. package/src/_deprecated/InlineAlert/_stories/InlineAlert.test.story.tsx +23 -12
  84. package/src/_deprecated/Select/_stories/Select.rtl.test.story.tsx +78 -42
  85. package/src/common/BottomSheet/_stories/BottomSheet.test.story.tsx +38 -20
  86. package/src/common/Panel/_stories/Panel.rtl.test.story.tsx +135 -51
@@ -6,7 +6,7 @@ import { ActionPrompt } from '../ActionPrompt';
6
6
  import { Body, Title } from '../../..';
7
7
  import { StoryObj } from '@storybook/react-webpack5';
8
8
  import { allModes } from '../../../../.storybook/modes';
9
- import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
9
+ import { useRtlDiffI18n, withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
10
10
  import { withVariantConfig } from '../../../../.storybook/helpers';
11
11
  import { lorem10 } from '../../../test-utils';
12
12
 
@@ -275,41 +275,77 @@ export const Responsiveness: Story = {
275
275
  };
276
276
 
277
277
  export const RTLDiff: Story = {
278
- render: () => (
279
- <>
280
- <ActionPrompt
281
- title="Default status icon"
282
- description="No media provided, uses default sentiment icon."
283
- action={{ label: 'Continue' }}
284
- />
285
- <ActionPrompt
286
- title="Custom image"
287
- description="Media with a custom image source."
288
- media={{ imgSrc: '../../wise-card.svg' }}
289
- action={{ label: 'View card' }}
290
- />
291
- <ActionPrompt
292
- title="Avatar with icon"
293
- description="Media with an avatar containing a custom icon."
294
- media={{ avatar: { asset: <Bank /> } }}
295
- action={{ label: 'Connect bank' }}
296
- />
297
- <ActionPrompt
298
- title="Primary and secondary actions"
299
- description="Both action buttons present."
300
- media={{ avatar: { asset: <Bank /> } }}
301
- action={{ label: 'Confirm' }}
302
- actionSecondary={{ label: 'Cancel' }}
303
- />
304
- <ActionPrompt
305
- title="Dismissible with two actions"
306
- description="Close button and both action buttons."
307
- media={{ avatar: { asset: <Bank /> } }}
308
- action={{ label: 'Confirm' }}
309
- actionSecondary={{ label: 'Cancel' }}
310
- onDismiss={() => {}}
311
- />
312
- </>
313
- ),
314
- ...withRTLDiff(),
278
+ render: () => {
279
+ const i18n = useRtlDiffI18n();
280
+ return (
281
+ <>
282
+ <ActionPrompt
283
+ title={i18n.defaultIconTitle}
284
+ description={i18n.defaultIconDescription}
285
+ action={{ label: i18n.continueAction }}
286
+ />
287
+ <ActionPrompt
288
+ title={i18n.customImageTitle}
289
+ description={i18n.customImageDescription}
290
+ media={{ imgSrc: '../../wise-card.svg' }}
291
+ action={{ label: i18n.viewCardAction }}
292
+ />
293
+ <ActionPrompt
294
+ title={i18n.avatarIconTitle}
295
+ description={i18n.avatarIconDescription}
296
+ media={{ avatar: { asset: <Bank /> } }}
297
+ action={{ label: i18n.connectBankAction }}
298
+ />
299
+ <ActionPrompt
300
+ title={i18n.twoActionsTitle}
301
+ description={i18n.twoActionsDescription}
302
+ media={{ avatar: { asset: <Bank /> } }}
303
+ action={{ label: i18n.confirmAction }}
304
+ actionSecondary={{ label: i18n.cancelAction }}
305
+ />
306
+ <ActionPrompt
307
+ title={i18n.dismissibleTitle}
308
+ description={i18n.dismissibleDescription}
309
+ media={{ avatar: { asset: <Bank /> } }}
310
+ action={{ label: i18n.confirmAction }}
311
+ actionSecondary={{ label: i18n.cancelAction }}
312
+ onDismiss={() => {}}
313
+ />
314
+ </>
315
+ );
316
+ },
317
+ ...withRTLDiff({
318
+ i18n: {
319
+ defaultIconTitle: { en: 'Default status icon', ar: 'أيقونة الحالة الافتراضية' },
320
+ defaultIconDescription: {
321
+ en: 'No media provided, uses default sentiment icon.',
322
+ ar: 'لا توجد وسائط، يتم استخدام أيقونة الحالة الافتراضية.',
323
+ },
324
+ continueAction: { en: 'Continue', ar: 'متابعة' },
325
+ customImageTitle: { en: 'Custom image', ar: 'صورة مخصصة' },
326
+ customImageDescription: {
327
+ en: 'Media with a custom image source.',
328
+ ar: 'وسائط مع مصدر صورة مخصص.',
329
+ },
330
+ viewCardAction: { en: 'View card', ar: 'عرض البطاقة' },
331
+ avatarIconTitle: { en: 'Avatar with icon', ar: 'صورة رمزية مع أيقونة' },
332
+ avatarIconDescription: {
333
+ en: 'Media with an avatar containing a custom icon.',
334
+ ar: 'وسائط مع صورة رمزية تحتوي على أيقونة مخصصة.',
335
+ },
336
+ connectBankAction: { en: 'Connect bank', ar: 'ربط البنك' },
337
+ twoActionsTitle: { en: 'Primary and secondary actions', ar: 'إجراءات أساسية وثانوية' },
338
+ twoActionsDescription: {
339
+ en: 'Both action buttons present.',
340
+ ar: 'زرّا الإجراء موجودان معًا.',
341
+ },
342
+ confirmAction: { en: 'Confirm', ar: 'تأكيد' },
343
+ cancelAction: { en: 'Cancel', ar: 'إلغاء' },
344
+ dismissibleTitle: { en: 'Dismissible with two actions', ar: 'قابل للإغلاق مع إجراءين' },
345
+ dismissibleDescription: {
346
+ en: 'Close button and both action buttons.',
347
+ ar: 'زر الإغلاق وزرّا الإجراء.',
348
+ },
349
+ },
350
+ }),
315
351
  };
@@ -3,7 +3,7 @@ import { Meta, StoryObj } from '@storybook/react-webpack5';
3
3
  import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
4
4
  import { Bank } from '@transferwise/icons';
5
5
  import Button from '../../../Button';
6
- import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
6
+ import { useRtlDiffI18n, withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
7
7
  import { withVariantConfig } from '../../../../.storybook/helpers';
8
8
  import { CriticalBanner } from '../CriticalBanner';
9
9
 
@@ -482,34 +482,71 @@ export const UncontrolledStateInteraction: Story = {
482
482
  };
483
483
 
484
484
  export const RTLDiff: Story = {
485
- render: () => (
486
- <>
487
- <CriticalBanner title="Title only" description="Description without actions or media." />
488
- <CriticalBanner
489
- title="With primary action"
490
- description="Banner with a single action button."
491
- action={{ label: 'Verify now' }}
492
- />
493
- <CriticalBanner
494
- title="With both actions"
495
- description="Banner with primary and secondary actions."
496
- action={{ label: 'Verify now' }}
497
- actionSecondary={{ label: 'Learn more' }}
498
- />
499
- <CriticalBanner
500
- title="With media image"
501
- description="Banner with a custom image."
502
- media={{ imgSrc: '../../wise-card.svg', 'aria-label': 'Wise card' }}
503
- action={{ label: 'Take action' }}
504
- />
505
- <CriticalBanner
506
- title="With avatar media"
507
- description="Banner with an avatar icon."
508
- media={{ avatar: { asset: <Bank /> } }}
509
- action={{ label: 'Connect bank' }}
510
- actionSecondary={{ label: 'Learn more' }}
511
- />
512
- </>
513
- ),
514
- ...withRTLDiff({ renderAs: 'iframe' }),
485
+ render: () => {
486
+ const i18n = useRtlDiffI18n();
487
+ return (
488
+ <>
489
+ <CriticalBanner title={i18n.titleOnly} description={i18n.titleOnlyDescription} />
490
+ <CriticalBanner
491
+ title={i18n.withPrimaryAction}
492
+ description={i18n.withPrimaryActionDescription}
493
+ action={{ label: i18n.verifyNow }}
494
+ />
495
+ <CriticalBanner
496
+ title={i18n.withBothActions}
497
+ description={i18n.withBothActionsDescription}
498
+ action={{ label: i18n.verifyNow }}
499
+ actionSecondary={{ label: i18n.learnMore }}
500
+ />
501
+ <CriticalBanner
502
+ title={i18n.withMediaImage}
503
+ description={i18n.withMediaImageDescription}
504
+ media={{ imgSrc: '../../wise-card.svg', 'aria-label': i18n.cardImage }}
505
+ action={{ label: i18n.takeAction }}
506
+ />
507
+ <CriticalBanner
508
+ title={i18n.withAvatarMedia}
509
+ description={i18n.withAvatarMediaDescription}
510
+ media={{ avatar: { asset: <Bank /> } }}
511
+ action={{ label: i18n.connectBank }}
512
+ actionSecondary={{ label: i18n.learnMore }}
513
+ />
514
+ </>
515
+ );
516
+ },
517
+ ...withRTLDiff({
518
+ renderAs: 'iframe',
519
+ i18n: {
520
+ titleOnly: { en: 'Title only', ar: 'العنوان فقط' },
521
+ titleOnlyDescription: {
522
+ en: 'Description without actions or media.',
523
+ ar: 'وصف بدون إجراءات أو وسائط.',
524
+ },
525
+ withPrimaryAction: { en: 'With primary action', ar: 'مع إجراء رئيسي' },
526
+ withPrimaryActionDescription: {
527
+ en: 'Banner with a single action button.',
528
+ ar: 'لافتة تحتوي على زر إجراء واحد.',
529
+ },
530
+ withBothActions: { en: 'With both actions', ar: 'مع كلا الإجراءين' },
531
+ withBothActionsDescription: {
532
+ en: 'Banner with primary and secondary actions.',
533
+ ar: 'لافتة تحتوي على إجراء رئيسي وإجراء ثانوي.',
534
+ },
535
+ withMediaImage: { en: 'With media image', ar: 'مع صورة' },
536
+ withMediaImageDescription: {
537
+ en: 'Banner with a custom image.',
538
+ ar: 'لافتة تحتوي على صورة مخصصة.',
539
+ },
540
+ withAvatarMedia: { en: 'With avatar media', ar: 'مع صورة رمزية' },
541
+ withAvatarMediaDescription: {
542
+ en: 'Banner with an avatar icon.',
543
+ ar: 'لافتة تحتوي على أيقونة رمزية.',
544
+ },
545
+ verifyNow: { en: 'Verify now', ar: 'تحقّق الآن' },
546
+ learnMore: { en: 'Learn more', ar: 'اعرف المزيد' },
547
+ takeAction: { en: 'Take action', ar: 'اتخذ إجراءً' },
548
+ connectBank: { en: 'Connect bank', ar: 'ربط البنك' },
549
+ cardImage: { en: 'Wise card', ar: 'بطاقة Wise' },
550
+ },
551
+ }),
515
552
  };
@@ -5,7 +5,7 @@ import { action } from 'storybook/actions';
5
5
  import { Star } from '@transferwise/icons';
6
6
  import { InfoPrompt, type InfoPromptProps } from '../InfoPrompt';
7
7
  import { allModes } from '../../../../.storybook/modes';
8
- import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
8
+ import { useRtlDiffI18n, withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
9
9
  import { withVariantConfig } from '../../../../.storybook/helpers';
10
10
 
11
11
  const withComponentGrid =
@@ -556,25 +556,55 @@ export const LiveRegionDismiss: Story = {
556
556
  };
557
557
 
558
558
  export const RTLDiff: Story = {
559
- render: () => (
560
- <>
561
- <InfoPrompt description="Basic description only." />
562
- <InfoPrompt title="With Title" description="Description with a title above it." />
563
- <InfoPrompt description="Dismissible prompt." onDismiss={() => {}} />
564
- <InfoPrompt
565
- title="With Action"
566
- description="Description with an action link below."
567
- action={{ label: 'Learn more', href: '#' }}
568
- />
569
- <InfoPrompt description="Custom media icon." media={{ asset: <Star title="Starred" /> }} />
570
- <InfoPrompt
571
- title="All Options"
572
- description="Title, action, dismiss, and custom media combined."
573
- media={{ asset: <Star title="Starred" /> }}
574
- action={{ label: 'View details', href: '#' }}
575
- onDismiss={() => {}}
576
- />
577
- </>
578
- ),
579
- ...withRTLDiff(),
559
+ render: () => {
560
+ const i18n = useRtlDiffI18n();
561
+ return (
562
+ <>
563
+ <InfoPrompt description={i18n.basicDescription} />
564
+ <InfoPrompt title={i18n.withTitleHeading} description={i18n.withTitleDescription} />
565
+ <InfoPrompt description={i18n.dismissibleDescription} onDismiss={() => {}} />
566
+ <InfoPrompt
567
+ title={i18n.withActionHeading}
568
+ description={i18n.withActionDescription}
569
+ action={{ label: i18n.learnMore, href: '#' }}
570
+ />
571
+ <InfoPrompt
572
+ description={i18n.customMediaDescription}
573
+ media={{ asset: <Star title={i18n.starredMedia} /> }}
574
+ />
575
+ <InfoPrompt
576
+ title={i18n.allOptionsHeading}
577
+ description={i18n.allOptionsDescription}
578
+ media={{ asset: <Star title={i18n.starredMedia} /> }}
579
+ action={{ label: i18n.viewDetails, href: '#' }}
580
+ onDismiss={() => {}}
581
+ />
582
+ </>
583
+ );
584
+ },
585
+ ...withRTLDiff({
586
+ i18n: {
587
+ basicDescription: { en: 'Basic description only.', ar: 'الوصف الأساسي فقط.' },
588
+ withTitleHeading: { en: 'With Title', ar: 'مع عنوان' },
589
+ withTitleDescription: {
590
+ en: 'Description with a title above it.',
591
+ ar: 'وصف مع عنوان في الأعلى.',
592
+ },
593
+ dismissibleDescription: { en: 'Dismissible prompt.', ar: 'تنبيه قابل للإغلاق.' },
594
+ withActionHeading: { en: 'With Action', ar: 'مع إجراء' },
595
+ withActionDescription: {
596
+ en: 'Description with an action link below.',
597
+ ar: 'وصف مع رابط إجراء في الأسفل.',
598
+ },
599
+ learnMore: { en: 'Learn more', ar: 'اعرف المزيد' },
600
+ customMediaDescription: { en: 'Custom media icon.', ar: 'أيقونة وسائط مخصصة.' },
601
+ starredMedia: { en: 'Starred', ar: 'مميز بنجمة' },
602
+ allOptionsHeading: { en: 'All Options', ar: 'جميع الخيارات' },
603
+ allOptionsDescription: {
604
+ en: 'Title, action, dismiss, and custom media combined.',
605
+ ar: 'عنوان وإجراء وإغلاق ووسائط مخصصة مجتمعة.',
606
+ },
607
+ viewDetails: { en: 'View details', ar: 'عرض التفاصيل' },
608
+ },
609
+ }),
580
610
  };
@@ -2,7 +2,7 @@ import { StoryObj } from '@storybook/react-webpack5';
2
2
  import { Suitcase } from '@transferwise/icons';
3
3
  import { InlinePrompt } from '../InlinePrompt';
4
4
  import { withVariantConfig } from '../../../../.storybook/helpers';
5
- import { withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
5
+ import { useRtlDiffI18n, withRTLDiff } from '../../../../.storybook/decorators/RtlDiffDecorator';
6
6
 
7
7
  export default {
8
8
  title: 'Prompts/InlinePrompt/Tests',
@@ -22,27 +22,42 @@ export const TinyScreen: Story = {
22
22
  };
23
23
 
24
24
  export const RTLDiff: Story = {
25
- render: () => (
26
- <>
27
- {/* default icon at inline-start, auto width */}
28
- <InlinePrompt sentiment="positive">Short content with default icon.</InlinePrompt>
25
+ render: () => {
26
+ const i18n = useRtlDiffI18n();
27
+ return (
28
+ <>
29
+ {/* default icon at inline-start, auto width */}
30
+ <InlinePrompt sentiment="positive">{i18n.defaultIcon}</InlinePrompt>
29
31
 
30
- {/* custom media icon, auto width */}
31
- <InlinePrompt sentiment="positive" media={<Suitcase />}>
32
- Custom icon with auto width.
33
- </InlinePrompt>
32
+ {/* custom media icon, auto width */}
33
+ <InlinePrompt sentiment="positive" media={<Suitcase />}>
34
+ {i18n.customIcon}
35
+ </InlinePrompt>
34
36
 
35
- {/* full width — icon position flips */}
36
- <InlinePrompt sentiment="positive" media={<Suitcase />} width="full">
37
- Custom icon with full width.
38
- </InlinePrompt>
37
+ {/* full width — icon position flips */}
38
+ <InlinePrompt sentiment="positive" media={<Suitcase />} width="full">
39
+ {i18n.fullWidth}
40
+ </InlinePrompt>
39
41
 
40
- {/* multi-line content — verifies wrapping alignment */}
41
- <InlinePrompt sentiment="warning" width="full">
42
- This prompt has longer content that may wrap to multiple lines to verify that the icon
43
- alignment remains correct in RTL layout.
44
- </InlinePrompt>
45
- </>
46
- ),
47
- ...withRTLDiff(),
42
+ {/* multi-line content — verifies wrapping alignment */}
43
+ <InlinePrompt sentiment="warning" width="full">
44
+ {i18n.multiLine}
45
+ </InlinePrompt>
46
+ </>
47
+ );
48
+ },
49
+ ...withRTLDiff({
50
+ i18n: {
51
+ defaultIcon: {
52
+ en: 'Short content with default icon.',
53
+ ar: 'محتوى قصير مع الأيقونة الافتراضية.',
54
+ },
55
+ customIcon: { en: 'Custom icon with auto width.', ar: 'أيقونة مخصصة بعرض تلقائي.' },
56
+ fullWidth: { en: 'Custom icon with full width.', ar: 'أيقونة مخصصة بعرض كامل.' },
57
+ multiLine: {
58
+ en: 'This prompt has longer content that may wrap to multiple lines to verify that the icon alignment remains correct in RTL layout.',
59
+ ar: 'يحتوي هذا التنبيه على محتوى أطول قد يمتد على عدة أسطر للتحقق من أن محاذاة الأيقونة تظل صحيحة في التصميم من اليمين إلى اليسار.',
60
+ },
61
+ },
62
+ }),
48
63
  };
@@ -1,6 +1,6 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
2
  import { Flag } from '@wise/art';
3
- import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
3
+ import { useRtlDiffI18n, withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
4
  import AvatarView from '../../AvatarView';
5
5
  import Radio from '../Radio';
6
6
 
@@ -13,49 +13,63 @@ export default {
13
13
  type Story = StoryObj<typeof Radio>;
14
14
 
15
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(),
16
+ render: () => {
17
+ const i18n = useRtlDiffI18n();
18
+ return (
19
+ <>
20
+ <Radio
21
+ label={i18n.standardOption}
22
+ name="radio-rtl"
23
+ id="radio-rtl-basic"
24
+ value="basic"
25
+ onChange={() => {}}
26
+ />
27
+ <Radio
28
+ label={i18n.withSecondary}
29
+ secondary={i18n.secondaryDescription}
30
+ name="radio-rtl"
31
+ id="radio-rtl-secondary"
32
+ value="secondary"
33
+ onChange={() => {}}
34
+ />
35
+ <Radio
36
+ label={i18n.withAvatar}
37
+ name="radio-rtl"
38
+ id="radio-rtl-avatar"
39
+ value="avatar"
40
+ avatar={
41
+ <AvatarView size={40}>
42
+ <Flag code="IM" />
43
+ </AvatarView>
44
+ }
45
+ onChange={() => {}}
46
+ />
47
+ <Radio
48
+ label={i18n.withSecondaryAndAvatar}
49
+ secondary={i18n.secondaryDescription}
50
+ name="radio-rtl"
51
+ id="radio-rtl-secondary-avatar"
52
+ value="secondary-avatar"
53
+ avatar={
54
+ <AvatarView size={40}>
55
+ <Flag code="IM" />
56
+ </AvatarView>
57
+ }
58
+ onChange={() => {}}
59
+ />
60
+ </>
61
+ );
62
+ },
63
+ ...withRTLDiff({
64
+ i18n: {
65
+ standardOption: { en: 'Standard option', ar: 'خيار عادي' },
66
+ withSecondary: { en: 'Option with secondary text', ar: 'خيار مع نص ثانوي' },
67
+ withAvatar: { en: 'Option with avatar', ar: 'خيار مع صورة رمزية' },
68
+ withSecondaryAndAvatar: {
69
+ en: 'Option with secondary text and avatar',
70
+ ar: 'خيار مع نص ثانوي وصورة رمزية',
71
+ },
72
+ secondaryDescription: { en: 'Secondary description', ar: 'وصف ثانوي' },
73
+ },
74
+ }),
61
75
  };
@@ -3,7 +3,7 @@ import Field from '../../Field/Field';
3
3
  import { Meta, StoryObj } from '@storybook/react-webpack5';
4
4
  import { fn } from 'storybook/test';
5
5
  import { Flag } from '@wise/art';
6
- import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
6
+ import { useRtlDiffI18n, withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
7
7
  import AvatarView from '../../AvatarView';
8
8
 
9
9
  const meta = {
@@ -65,54 +65,73 @@ export const FieldsWithoutPrompt = {
65
65
  } satisfies Story;
66
66
 
67
67
  export const RTLDiff: Story<string> = {
68
- render: () => (
69
- <>
70
- <RadioGroup
71
- name="radio-group-rtl-basic"
72
- selectedValue="option-1"
73
- radios={[
74
- { value: 'option-1', label: 'Option one' },
75
- { value: 'option-2', label: 'Option two' },
76
- { value: 'option-3', label: 'Option three' },
77
- ]}
78
- onChange={() => {}}
79
- />
80
- <RadioGroup
81
- name="radio-group-rtl-secondary"
82
- selectedValue="option-a"
83
- radios={[
84
- { value: 'option-a', label: 'Option A', secondary: 'Secondary text for A' },
85
- { value: 'option-b', label: 'Option B', secondary: 'Secondary text for B' },
86
- ]}
87
- onChange={() => {}}
88
- />
89
- <RadioGroup
90
- name="radio-group-rtl-avatar"
91
- selectedValue="option-x"
92
- radios={[
93
- {
94
- value: 'option-x',
95
- label: 'Option X',
96
- avatar: (
97
- <AvatarView size={40}>
98
- <Flag code="IM" />
99
- </AvatarView>
100
- ),
101
- },
102
- {
103
- value: 'option-y',
104
- label: 'Option Y',
105
- secondary: 'With secondary and avatar',
106
- avatar: (
107
- <AvatarView size={40}>
108
- <Flag code="IM" />
109
- </AvatarView>
110
- ),
111
- },
112
- ]}
113
- onChange={() => {}}
114
- />
115
- </>
116
- ),
117
- ...withRTLDiff(),
68
+ render: () => {
69
+ const i18n = useRtlDiffI18n();
70
+ return (
71
+ <>
72
+ <RadioGroup
73
+ name="radio-group-rtl-basic"
74
+ selectedValue="option-1"
75
+ radios={[
76
+ { value: 'option-1', label: i18n.optionOne },
77
+ { value: 'option-2', label: i18n.optionTwo },
78
+ { value: 'option-3', label: i18n.optionThree },
79
+ ]}
80
+ onChange={() => {}}
81
+ />
82
+ <RadioGroup
83
+ name="radio-group-rtl-secondary"
84
+ selectedValue="option-a"
85
+ radios={[
86
+ { value: 'option-a', label: i18n.optionA, secondary: i18n.secondaryA },
87
+ { value: 'option-b', label: i18n.optionB, secondary: i18n.secondaryB },
88
+ ]}
89
+ onChange={() => {}}
90
+ />
91
+ <RadioGroup
92
+ name="radio-group-rtl-avatar"
93
+ selectedValue="option-x"
94
+ radios={[
95
+ {
96
+ value: 'option-x',
97
+ label: i18n.optionX,
98
+ avatar: (
99
+ <AvatarView size={40}>
100
+ <Flag code="IM" />
101
+ </AvatarView>
102
+ ),
103
+ },
104
+ {
105
+ value: 'option-y',
106
+ label: i18n.optionY,
107
+ secondary: i18n.secondaryWithAvatar,
108
+ avatar: (
109
+ <AvatarView size={40}>
110
+ <Flag code="IM" />
111
+ </AvatarView>
112
+ ),
113
+ },
114
+ ]}
115
+ onChange={() => {}}
116
+ />
117
+ </>
118
+ );
119
+ },
120
+ ...withRTLDiff({
121
+ i18n: {
122
+ optionOne: { en: 'Option one', ar: 'الخيار الأول' },
123
+ optionTwo: { en: 'Option two', ar: 'الخيار الثاني' },
124
+ optionThree: { en: 'Option three', ar: 'الخيار الثالث' },
125
+ optionA: { en: 'Option A', ar: 'الخيار أ' },
126
+ optionB: { en: 'Option B', ar: 'الخيار ب' },
127
+ secondaryA: { en: 'Secondary text for A', ar: 'نص ثانوي للخيار أ' },
128
+ secondaryB: { en: 'Secondary text for B', ar: 'نص ثانوي للخيار ب' },
129
+ optionX: { en: 'Option X', ar: 'الخيار س' },
130
+ optionY: { en: 'Option Y', ar: 'الخيار ص' },
131
+ secondaryWithAvatar: {
132
+ en: 'With secondary and avatar',
133
+ ar: 'مع نص ثانوي وصورة رمزية',
134
+ },
135
+ },
136
+ }),
118
137
  };