@transferwise/components 46.162.1 → 46.162.2

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 (69) hide show
  1. package/build/Calendar/DateHeader/DateHeader.js +2 -6
  2. package/build/Calendar/DateHeader/DateHeader.js.map +1 -1
  3. package/build/Calendar/DateHeader/DateHeader.mjs +3 -7
  4. package/build/Calendar/DateHeader/DateHeader.mjs.map +1 -1
  5. package/build/Carousel/Carousel.js +2 -2
  6. package/build/Carousel/Carousel.js.map +1 -1
  7. package/build/Carousel/Carousel.mjs +3 -3
  8. package/build/Carousel/Carousel.mjs.map +1 -1
  9. package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.js +4 -3
  10. package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.js.map +1 -1
  11. package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.mjs +4 -3
  12. package/build/Inputs/SelectInput/OptionContent/SelectInputOptionContent.mjs.map +1 -1
  13. package/build/ListItem/Navigation/ListItemNavigation.js +1 -1
  14. package/build/ListItem/Navigation/ListItemNavigation.js.map +1 -1
  15. package/build/ListItem/Navigation/ListItemNavigation.mjs +2 -2
  16. package/build/ListItem/Navigation/ListItemNavigation.mjs.map +1 -1
  17. package/build/PhoneNumberInput/PhoneNumberInput.js +2 -1
  18. package/build/PhoneNumberInput/PhoneNumberInput.js.map +1 -1
  19. package/build/PhoneNumberInput/PhoneNumberInput.mjs +2 -1
  20. package/build/PhoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  21. package/build/PromoCard/Indicator/PromoCardIndicator.js +1 -1
  22. package/build/PromoCard/Indicator/PromoCardIndicator.js.map +1 -1
  23. package/build/PromoCard/Indicator/PromoCardIndicator.mjs +2 -2
  24. package/build/PromoCard/Indicator/PromoCardIndicator.mjs.map +1 -1
  25. package/build/main.css +17 -7
  26. package/build/styles/Button/Button.css +0 -3
  27. package/build/styles/DateInput/DateInput.css +13 -0
  28. package/build/styles/ListItem/ListItem.css +1 -1
  29. package/build/styles/PhoneNumberInput/PhoneNumberInput.css +3 -0
  30. package/build/styles/PromoCard/PromoCard.css +0 -3
  31. package/build/styles/main.css +17 -7
  32. package/build/types/Body/Body.d.ts +2 -2
  33. package/build/types/IconButton/IconButton.d.ts +1 -1
  34. package/build/types/Inputs/SelectInput/OptionContent/SelectInputOptionContent.d.ts +2 -1
  35. package/build/types/Inputs/SelectInput/OptionContent/SelectInputOptionContent.d.ts.map +1 -1
  36. package/build/types/MoneyInput/MoneyInput.d.ts +1 -1
  37. package/build/types/MoneyInput/MoneyInput.d.ts.map +1 -1
  38. package/build/types/PhoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
  39. package/build/types/Title/Title.d.ts +2 -2
  40. package/build/types/Upload/Steps/UploadImageStep/UploadImageStep.d.ts +1 -1
  41. package/build/types/UploadInput/UploadItem/UploadItemLink.d.ts +1 -1
  42. package/package.json +2 -2
  43. package/src/Button/Button.css +0 -3
  44. package/src/Button/Button.less +0 -16
  45. package/src/Button/_stories/Button.test.story.tsx +12 -12
  46. package/src/Calendar/DateHeader/DateHeader.tsx +3 -3
  47. package/src/Carousel/Carousel.tsx +3 -3
  48. package/src/DateInput/DateInput.css +13 -0
  49. package/src/DateInput/DateInput.less +10 -2
  50. package/src/DateInput/_stories/DateInput.rtl.test.story.tsx +36 -0
  51. package/src/DateInput/_stories/DateInput.test.story.tsx +0 -13
  52. package/src/ExpressiveMoneyInput/_stories/ExpressiveMoneyInput.rtl.test.story.tsx +1 -1
  53. package/src/InputWithDisplayFormat/_stories/InputWithDisplayFormat.test.story.tsx +52 -0
  54. package/src/Inputs/SelectInput/OptionContent/SelectInputOptionContent.tsx +4 -1
  55. package/src/Inputs/SelectInput/SelectInput.test.tsx +74 -0
  56. package/src/ListItem/ListItem.css +1 -1
  57. package/src/ListItem/ListItem.grid.less +4 -4
  58. package/src/ListItem/ListItem.less +1 -1
  59. package/src/ListItem/Navigation/ListItemNavigation.tsx +2 -2
  60. package/src/PhoneNumberInput/PhoneNumberInput.css +3 -0
  61. package/src/PhoneNumberInput/PhoneNumberInput.less +10 -2
  62. package/src/PhoneNumberInput/PhoneNumberInput.tsx +1 -0
  63. package/src/PhoneNumberInput/_stories/PhoneNumberInput.rtl.test.story.tsx +1 -1
  64. package/src/PromoCard/Indicator/PromoCardIndicator.tsx +2 -2
  65. package/src/PromoCard/PromoCard.css +0 -3
  66. package/src/PromoCard/PromoCard.less +0 -5
  67. package/src/Prompt/CriticalBanner/_stories/CriticalBanner.test.story.tsx +1 -1
  68. package/src/i18n/en.json +1 -0
  69. package/src/main.css +17 -7
@@ -244,19 +244,3 @@
244
244
  }
245
245
  }
246
246
  }
247
-
248
-
249
- :dir(rtl) {
250
- .wds-Button {
251
- .tw-icon-chevron-right,
252
- .tw-icon-arrow-right,
253
- .tw-icon-chevron-left,
254
- .tw-icon-arrow-left,
255
- .tw-icon-arrow-diagonal-down,
256
- .tw-icon-arrow-diagonal-up,
257
- .tw-icon-list,
258
- .tw-icon-activity {
259
- scale: -1 1;
260
- }
261
- }
262
- }
@@ -1,5 +1,5 @@
1
1
  import { Meta, StoryObj } from '@storybook/react-webpack5';
2
- import { ArrowRight, ChevronRight, Freeze } from '@transferwise/icons';
2
+ import { ArrowEnd, ChevronEnd, Freeze } from '@transferwise/icons';
3
3
  import { Flag } from '@wise/art';
4
4
  import { expect, userEvent, within } from 'storybook/test';
5
5
  import Button from '../Button.resolver';
@@ -55,7 +55,7 @@ export const AllVariants: Story = {
55
55
  priority={priority}
56
56
  size={size}
57
57
  addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
58
- addonEnd={{ type: 'icon', value: <ArrowRight /> }}
58
+ addonEnd={{ type: 'icon', value: <ArrowEnd /> }}
59
59
  block
60
60
  >
61
61
  {`${priority} default ${size}`}
@@ -69,7 +69,7 @@ export const AllVariants: Story = {
69
69
  type: 'avatar',
70
70
  value: [{ asset: <Freeze /> }, { asset: <Freeze /> }],
71
71
  }}
72
- addonEnd={{ type: 'icon', value: <ArrowRight /> }}
72
+ addonEnd={{ type: 'icon', value: <ArrowEnd /> }}
73
73
  block
74
74
  disabled
75
75
  >
@@ -80,7 +80,7 @@ export const AllVariants: Story = {
80
80
  priority={priority}
81
81
  size={size}
82
82
  addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
83
- addonEnd={{ type: 'icon', value: <ArrowRight /> }}
83
+ addonEnd={{ type: 'icon', value: <ArrowEnd /> }}
84
84
  block
85
85
  loading
86
86
  >
@@ -100,7 +100,7 @@ export const AllVariants: Story = {
100
100
  sentiment="negative"
101
101
  priority={priority as ButtonPriority}
102
102
  size={size}
103
- addonEnd={{ type: 'icon', value: <ChevronRight /> }}
103
+ addonEnd={{ type: 'icon', value: <ChevronEnd /> }}
104
104
  addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
105
105
  block
106
106
  >
@@ -112,7 +112,7 @@ export const AllVariants: Story = {
112
112
  sentiment="negative"
113
113
  priority={priority as ButtonPriority}
114
114
  size={size}
115
- addonEnd={{ type: 'icon', value: <ChevronRight /> }}
115
+ addonEnd={{ type: 'icon', value: <ChevronEnd /> }}
116
116
  addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
117
117
  block
118
118
  disabled
@@ -124,7 +124,7 @@ export const AllVariants: Story = {
124
124
  sentiment="negative"
125
125
  priority={priority as ButtonPriority}
126
126
  size={size}
127
- addonEnd={{ type: 'icon', value: <ChevronRight /> }}
127
+ addonEnd={{ type: 'icon', value: <ChevronEnd /> }}
128
128
  addonStart={{ type: 'avatar', value: [{ asset: <Freeze /> }] }}
129
129
  block
130
130
  loading
@@ -174,7 +174,7 @@ export const RTLDiff: Story = {
174
174
  Start icon
175
175
  </Button>
176
176
 
177
- <Button v2 size="md" addonEnd={{ type: 'icon', value: <ArrowRight /> }}>
177
+ <Button v2 size="md" addonEnd={{ type: 'icon', value: <ArrowEnd /> }}>
178
178
  End icon
179
179
  </Button>
180
180
 
@@ -182,7 +182,7 @@ export const RTLDiff: Story = {
182
182
  v2
183
183
  size="md"
184
184
  addonStart={{ type: 'icon', value: <Freeze /> }}
185
- addonEnd={{ type: 'icon', value: <ArrowRight /> }}
185
+ addonEnd={{ type: 'icon', value: <ArrowEnd /> }}
186
186
  >
187
187
  Both icons
188
188
  </Button>
@@ -206,7 +206,7 @@ export const RTLDiff: Story = {
206
206
  Sm start icon
207
207
  </Button>
208
208
 
209
- <Button v2 size="sm" addonEnd={{ type: 'icon', value: <ArrowRight /> }}>
209
+ <Button v2 size="sm" addonEnd={{ type: 'icon', value: <ArrowEnd /> }}>
210
210
  Sm end icon
211
211
  </Button>
212
212
 
@@ -214,12 +214,12 @@ export const RTLDiff: Story = {
214
214
  v2
215
215
  size="sm"
216
216
  addonStart={{ type: 'icon', value: <Freeze /> }}
217
- addonEnd={{ type: 'icon', value: <ArrowRight /> }}
217
+ addonEnd={{ type: 'icon', value: <ArrowEnd /> }}
218
218
  >
219
219
  Sm both icons
220
220
  </Button>
221
221
 
222
- <Button v2 size="md" loading addonEnd={{ type: 'icon', value: <ArrowRight /> }}>
222
+ <Button v2 size="md" loading addonEnd={{ type: 'icon', value: <ArrowEnd /> }}>
223
223
  Loading
224
224
  </Button>
225
225
 
@@ -6,7 +6,7 @@ import { useLayout } from '../../common/hooks';
6
6
  import Title from '../../Title';
7
7
  import messages from '../Calendar.messages';
8
8
  import Button from '../../Button/Button';
9
- import { ChevronDown, ChevronLeft, ChevronRight } from '@transferwise/icons';
9
+ import { ChevronDown, ChevronStart, ChevronEnd } from '@transferwise/icons';
10
10
  import IconButton from '../../IconButton';
11
11
 
12
12
  interface DateHeaderProps {
@@ -41,7 +41,7 @@ const DateHeader: React.FC<DateHeaderProps> = ({
41
41
  disabled={isPreviousDisabled}
42
42
  onClick={onPreviousClick}
43
43
  >
44
- <ChevronLeft className="left-single-direction" />
44
+ <ChevronStart />
45
45
  </IconButton>
46
46
  </div>
47
47
  {label && (
@@ -69,7 +69,7 @@ const DateHeader: React.FC<DateHeaderProps> = ({
69
69
  disabled={isNextDisabled}
70
70
  onClick={onNextClick}
71
71
  >
72
- <ChevronRight className="right-single-direction" />
72
+ <ChevronEnd />
73
73
  </IconButton>
74
74
  </div>
75
75
  </div>
@@ -1,4 +1,4 @@
1
- import { ChevronLeft, ChevronRight } from '@transferwise/icons';
1
+ import { ChevronStart, ChevronEnd } from '@transferwise/icons';
2
2
  import { clsx } from 'clsx';
3
3
  import { type CSSProperties, type ReactNode, useEffect, useRef, useState } from 'react';
4
4
 
@@ -182,7 +182,7 @@ const Carousel: React.FC<CarouselProps> = ({ header, className, cards, onClick }
182
182
  data-testid="scroll-carousel-left"
183
183
  onClick={() => scrollCarousel('backward')}
184
184
  >
185
- <ChevronLeft />
185
+ <ChevronStart />
186
186
  </IconButton>
187
187
  <IconButton
188
188
  size={32}
@@ -194,7 +194,7 @@ const Carousel: React.FC<CarouselProps> = ({ header, className, cards, onClick }
194
194
  disabled={scrollIsAtEnd}
195
195
  onClick={() => scrollCarousel('forward')}
196
196
  >
197
- <ChevronRight />
197
+ <ChevronEnd />
198
198
  </IconButton>
199
199
  </div>
200
200
  ) : null}
@@ -9,6 +9,19 @@
9
9
  .tw-date .tw-date--day {
10
10
  margin-block-end: 0;
11
11
  }
12
+ [dir="rtl"] .tw-date .np-input {
13
+ text-align: end;
14
+ }
15
+ [dir="rtl"] .tw-date .np-input::-moz-placeholder {
16
+ text-align: start;
17
+ }
18
+ [dir="rtl"] .tw-date .np-input:-moz-placeholder {
19
+ text-align: start;
20
+ }
21
+ [dir="rtl"] .tw-date .np-input::placeholder,
22
+ [dir="rtl"] .tw-date .np-input:placeholder-shown {
23
+ text-align: start;
24
+ }
12
25
  @media (min-width: 600px) {
13
26
  .np-theme-personal .tw-date label {
14
27
  margin-block-end: 0;
@@ -10,7 +10,15 @@
10
10
  .tw-date--year,
11
11
  .tw-date--month,
12
12
  .tw-date--day {
13
- margin-bottom: 0;
13
+ margin-bottom: 0;
14
+ }
15
+ [dir="rtl"] & .np-input {
16
+ text-align: right;
17
+
18
+ &::placeholder,
19
+ &:placeholder-shown {
20
+ text-align: start;
21
+ }
14
22
  }
15
23
  }
16
24
 
@@ -22,4 +30,4 @@
22
30
  }
23
31
  }
24
32
  }
25
- }
33
+ }
@@ -0,0 +1,36 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { fn, userEvent, within } from 'storybook/test';
3
+
4
+ import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
5
+ import DateInput from '..';
6
+
7
+ export default {
8
+ component: DateInput,
9
+ title: 'Forms/DateInput/Tests/RTL Diff',
10
+ tags: ['!autodocs', '!manifest'],
11
+ } satisfies Meta<typeof DateInput>;
12
+
13
+ type Story = StoryObj<typeof DateInput>;
14
+
15
+ export const Sizes: Story = {
16
+ render: () => (
17
+ <>
18
+ <DateInput size="sm" onChange={fn()} />
19
+ <DateInput size="md" onChange={fn()} />
20
+ <DateInput size="lg" onChange={fn()} />
21
+ <DateInput mode="month-year" onChange={fn()} />
22
+ </>
23
+ ),
24
+ ...withRTLDiff({ renderAs: 'iframe' }),
25
+ };
26
+
27
+ export const OpenDropdown: Story = {
28
+ render: () => <DateInput onChange={() => {}} />,
29
+ play: async ({ canvasElement }) => {
30
+ const canvas = within(canvasElement);
31
+ const trigger = canvas.queryByRole('combobox');
32
+ if (!trigger) return;
33
+ await userEvent.click(trigger);
34
+ },
35
+ ...withRTLDiff({ renderAs: 'iframe' }),
36
+ };
@@ -6,7 +6,6 @@ import { lorem10 } from '../../test-utils';
6
6
 
7
7
  import Provider from '../../Provider';
8
8
  import translations from '../../i18n';
9
- import { withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
10
9
  import { withVariantConfig } from '../../../.storybook/helpers';
11
10
 
12
11
  const meta: Meta<typeof DateInput> = {
@@ -231,15 +230,3 @@ export const InputErrorMobile: Story = {
231
230
  ...InputError,
232
231
  ...withVariantConfig(['mobile'], InputError),
233
232
  };
234
-
235
- export const RTLDiff: Story = {
236
- render: () => (
237
- <>
238
- <DateInput size="sm" onChange={fn()} />
239
- <DateInput size="md" onChange={fn()} />
240
- <DateInput size="lg" onChange={fn()} />
241
- <DateInput mode="month-year" onChange={fn()} />
242
- </>
243
- ),
244
- ...withRTLDiff(),
245
- };
@@ -90,7 +90,7 @@ export const TriggerVariants: Story = {
90
90
  />
91
91
  </>
92
92
  ),
93
- ...withRTLDiff({ width: 'stretch' }),
93
+ ...withRTLDiff({ renderAs: 'iframe', width: 'stretch' }),
94
94
  };
95
95
 
96
96
  export const OpenDropdown: Story = {
@@ -1,6 +1,7 @@
1
1
  import { userEvent, within } from 'storybook/test';
2
2
  import { Meta, StoryObj } from '@storybook/react-webpack5';
3
3
 
4
+ import { useRtlDiffI18n, withRTLDiff } from '../../../.storybook/decorators/RtlDiffDecorator';
4
5
  import InputWithDisplayFormat, { InputWithDisplayFormatProps } from '..';
5
6
  import Field, { FieldProps } from '../../Field/Field';
6
7
 
@@ -31,3 +32,54 @@ export const SecurityPinPlay: Story = {
31
32
  await userEvent.type(canvas.getByPlaceholderText('*-*-*-*-*-*'), '123456');
32
33
  },
33
34
  };
35
+
36
+ export const RTLDiff: StoryObj<typeof InputWithDisplayFormat> = {
37
+ render: () => {
38
+ const i18n = useRtlDiffI18n();
39
+
40
+ return (
41
+ <>
42
+ <Field id="empty" label="Empty with placeholder">
43
+ <InputWithDisplayFormat
44
+ id="empty"
45
+ value=""
46
+ displayPattern="**** - **** - ****"
47
+ placeholder={i18n.placeholder}
48
+ onChange={() => {}}
49
+ />
50
+ </Field>
51
+ <Field id="card-code" label="Localised pattern">
52
+ <InputWithDisplayFormat
53
+ id="card-code"
54
+ value={i18n.value}
55
+ maxLength={16}
56
+ displayPattern="**** - **** - ****"
57
+ onChange={() => {}}
58
+ />
59
+ </Field>
60
+ <Field id="iban" label="IBAN (not localised)">
61
+ <InputWithDisplayFormat
62
+ id="iban"
63
+ value="GB29NWBK60161331926819"
64
+ maxLength={22}
65
+ displayPattern="** **** **** **** **** ****"
66
+ onChange={() => {}}
67
+ />
68
+ </Field>
69
+ </>
70
+ );
71
+ },
72
+ ...withRTLDiff({
73
+ width: 'stretch',
74
+ i18n: {
75
+ value: {
76
+ ltr: 'XKQMRTBWJNFL',
77
+ rtl: 'خكقمرتبوجنفل',
78
+ },
79
+ placeholder: {
80
+ ltr: 'Enter code',
81
+ rtl: 'أدخل الرمز',
82
+ },
83
+ },
84
+ }),
85
+ };
@@ -7,6 +7,7 @@ export interface SelectInputOptionContentProps {
7
7
  note?: string;
8
8
  description?: string;
9
9
  icon?: React.ReactNode;
10
+ className?: string;
10
11
  }
11
12
 
12
13
  /**
@@ -19,6 +20,7 @@ export function SelectInputOptionContent({
19
20
  note,
20
21
  description,
21
22
  icon,
23
+ className,
22
24
  }: SelectInputOptionContentProps) {
23
25
  const withinTrigger = useContext(SelectInputOptionContentWithinTriggerContext);
24
26
 
@@ -27,6 +29,7 @@ export function SelectInputOptionContent({
27
29
  className={clsx(
28
30
  'np-select-input-option-content-container',
29
31
  (note || description) && 'np-text-body-large',
32
+ className,
30
33
  )}
31
34
  >
32
35
  {icon ? (
@@ -47,7 +50,7 @@ export function SelectInputOptionContent({
47
50
  withinTrigger && 'np-select-input-option-content-text-within-trigger',
48
51
  )}
49
52
  >
50
- <div className="d-inline">{title}</div>
53
+ <div className="d-inline np-select-input-option-content-title">{title}</div>
51
54
  {note ? (
52
55
  <span className="np-select-input-option-content-text-secondary np-text-body-default">
53
56
  {note}
@@ -721,6 +721,80 @@ describe('SelectInput', () => {
721
721
  expect(descriptionElement).toHaveClass('np-select-input-option-description-in-trigger');
722
722
  });
723
723
 
724
+ it('applies custom className to option content container in the trigger', () => {
725
+ render(
726
+ <SelectInput
727
+ items={[
728
+ { type: 'option', value: 'USD' },
729
+ { type: 'option', value: 'EUR' },
730
+ ]}
731
+ renderValue={(currency) => (
732
+ <SelectInputOptionContent title={currency} className="custom-option-class" />
733
+ )}
734
+ value="USD"
735
+ />,
736
+ );
737
+
738
+ const triggerContent = screen
739
+ .getByText('USD')
740
+ .closest('.np-select-input-option-content-container');
741
+ expect(triggerContent).toHaveClass('custom-option-class');
742
+ });
743
+
744
+ it('applies custom className to option content container in dropdown options', async () => {
745
+ render(
746
+ <SelectInput
747
+ items={[
748
+ { type: 'option', value: 'USD' },
749
+ { type: 'option', value: 'EUR' },
750
+ ]}
751
+ renderValue={(currency) => (
752
+ <SelectInputOptionContent title={currency} className="custom-option-class" />
753
+ )}
754
+ value="USD"
755
+ />,
756
+ );
757
+
758
+ const trigger = screen.getByRole('combobox');
759
+ await userEvent.click(trigger);
760
+
761
+ const listbox = screen.getByRole('listbox');
762
+ const options = within(listbox).getAllByRole('option');
763
+ const optionContent = options[0].querySelector('.np-select-input-option-content-container');
764
+ expect(optionContent).toHaveClass('custom-option-class');
765
+ });
766
+
767
+ it('supports conditional className based on withinTrigger', async () => {
768
+ render(
769
+ <SelectInput
770
+ items={[
771
+ { type: 'option', value: 'USD' },
772
+ { type: 'option', value: 'EUR' },
773
+ ]}
774
+ renderValue={(currency, withinTrigger) => (
775
+ <SelectInputOptionContent
776
+ title={currency}
777
+ className={withinTrigger ? undefined : 'dropdown-only-class'}
778
+ />
779
+ )}
780
+ value="USD"
781
+ />,
782
+ );
783
+
784
+ const triggerContent = screen
785
+ .getByText('USD')
786
+ .closest('.np-select-input-option-content-container');
787
+ expect(triggerContent).not.toHaveClass('dropdown-only-class');
788
+
789
+ const trigger = screen.getByRole('combobox');
790
+ await userEvent.click(trigger);
791
+
792
+ const listbox = screen.getByRole('listbox');
793
+ const options = within(listbox).getAllByRole('option');
794
+ const optionContent = options[0].querySelector('.np-select-input-option-content-container');
795
+ expect(optionContent).toHaveClass('dropdown-only-class');
796
+ });
797
+
724
798
  describe('listbox label', () => {
725
799
  const fieldLabel = 'Fruits';
726
800
  const triggerLabel = 'Select fruit';
@@ -567,7 +567,7 @@
567
567
  .wds-list-item-control-wrapper {
568
568
  grid-area: control;
569
569
  }
570
- .wds-list-item-navigation .tw-icon-chevron-right {
570
+ .wds-list-item-navigation .tw-icon-chevron-end {
571
571
  color: #c9cbce;
572
572
  color: var(--color-interactive-secondary);
573
573
  display: block;
@@ -169,10 +169,10 @@
169
169
  }
170
170
  }
171
171
 
172
- // LESS struggles with ranged container queries so
173
- // we need to escape the interpolated expression.
174
- @container (~"@{wds-list-item-cq-min} < width <= @{wds-list-item-cq-max}") {
175
- .wds-list-item-media-image{
172
+ // LESS struggles with ranged container queries so we need to
173
+ // escape the interpolated expression using `e()` function.
174
+ @container (e("@{wds-list-item-cq-min} < width <= @{wds-list-item-cq-max}")) {
175
+ .wds-list-item-media-image {
176
176
  object-position: bottom left;
177
177
  }
178
178
 
@@ -224,7 +224,7 @@
224
224
  }
225
225
 
226
226
  &-navigation {
227
- .tw-icon-chevron-right {
227
+ .tw-icon-chevron-end {
228
228
  color: var(--color-interactive-secondary);
229
229
  display: block;
230
230
  }
@@ -1,4 +1,4 @@
1
- import { ChevronRight } from '@transferwise/icons';
1
+ import { ChevronEnd } from '@transferwise/icons';
2
2
  import type { ButtonProps } from '../../Button/Button.types';
3
3
  import { useListItemControl } from '../useListItemControl';
4
4
  import { PrimitiveButton } from '../../Primitives';
@@ -32,7 +32,7 @@ export const Navigation = function Navigation({
32
32
  }: ListItemNavigationProps) {
33
33
  const { baseItemProps } = useListItemControl('navigation', { href, hideIndicator, ...props });
34
34
  const { ids, describedByIds } = useContext(ListItemContext);
35
- const icon = hideIndicator ? null : <ChevronRight size={16} data-testid="NavigationIndicator" />;
35
+ const icon = hideIndicator ? null : <ChevronEnd size={16} data-testid="NavigationIndicator" />;
36
36
 
37
37
  return href ? (
38
38
  <>{icon}</>
@@ -27,3 +27,6 @@
27
27
  .tw-telephone__number-input {
28
28
  flex: auto 1 1;
29
29
  }
30
+ [dir="rtl"] .tw-telephone__prefix-option .np-select-input-option-content-title {
31
+ direction: ltr;
32
+ }
@@ -7,7 +7,7 @@
7
7
  margin-left: var(--size-12);
8
8
  }
9
9
 
10
- &__number-input-field{
10
+ &__number-input-field {
11
11
  [dir="rtl"] & {
12
12
  text-align: end;
13
13
  }
@@ -22,7 +22,7 @@
22
22
  width: 100%;
23
23
  }
24
24
 
25
- .np-select-input-content{
25
+ .np-select-input-content {
26
26
  [dir="rtl"] & {
27
27
  text-align: end;
28
28
  direction: ltr;
@@ -40,3 +40,11 @@
40
40
  .tw-telephone__number-input {
41
41
  flex: auto 1 1;
42
42
  }
43
+
44
+ // Prevent bidi algorithm from flipping "+{country-code}" to "{country-code}+"
45
+ // in RTL dropdown options as phone numbers are universally read as LTR.
46
+ .tw-telephone__prefix-option .np-select-input-option-content-title {
47
+ [dir="rtl"] & {
48
+ direction: ltr;
49
+ }
50
+ }
@@ -229,6 +229,7 @@ const PhoneNumberInput = ({
229
229
  ?.map((country) => country.iso3)
230
230
  .join(', ')
231
231
  }
232
+ className={withinTrigger ? undefined : 'tw-telephone__prefix-option'}
232
233
  />
233
234
  )}
234
235
  filterable
@@ -33,7 +33,7 @@ export const Sizes: Story = {
33
33
  </Field>
34
34
  </>
35
35
  ),
36
- ...withRTLDiff(),
36
+ ...withRTLDiff({ renderAs: 'iframe' }),
37
37
  };
38
38
 
39
39
  export const DropdownOpen: Story = {
@@ -1,4 +1,4 @@
1
- import { ArrowRight, Check, Download } from '@transferwise/icons';
1
+ import { ArrowEnd, Check, Download } from '@transferwise/icons';
2
2
  import { clsx } from 'clsx';
3
3
  import { ReactElement, ReactNode } from 'react';
4
4
 
@@ -57,7 +57,7 @@ const PromoCardIndicator: React.FC<PromoCardIndicatorProps> = ({
57
57
  isIconString &&
58
58
  {
59
59
  check: Check,
60
- arrow: ArrowRight,
60
+ arrow: ArrowEnd,
61
61
  download: Download,
62
62
  }[icon];
63
63
 
@@ -53,9 +53,6 @@
53
53
  .np-Card-indicatorIcon .tw-icon {
54
54
  color: var(--Card-indicator-icon-color);
55
55
  }
56
- [dir="rtl"] .np-Card-indicatorIcon .tw-icon {
57
- transform: scaleX(-1);
58
- }
59
56
  .np-Card--checked,
60
57
  .np-Card--link {
61
58
  color: currentColor;
@@ -50,11 +50,6 @@
50
50
 
51
51
  &Icon .tw-icon {
52
52
  color: var(--Card-indicator-icon-color);
53
-
54
- // Flips icon for right to left content
55
- [dir="rtl"] & {
56
- transform: scaleX(-1);
57
- }
58
53
  }
59
54
  }
60
55
 
@@ -511,5 +511,5 @@ export const RTLDiff: Story = {
511
511
  />
512
512
  </>
513
513
  ),
514
- ...withRTLDiff(),
514
+ ...withRTLDiff({ renderAs: 'iframe' }),
515
515
  };
package/src/i18n/en.json CHANGED
@@ -35,6 +35,7 @@
35
35
  "neptune.PhoneNumberInput.SelectInput.placeholder": "Select an option...",
36
36
  "neptune.PhoneNumberInput.countryCodeLabel": "Country code",
37
37
  "neptune.PhoneNumberInput.phoneNumberLabel": "Phone number",
38
+ "neptune.PhoneNumberInput.phoneNumberPrefix": "Prefix",
38
39
  "neptune.Select.searchPlaceholder": "Search...",
39
40
  "neptune.SelectInput.noResultsFound": "No results found",
40
41
  "neptune.StatusIcon.iconLabel.error": "Error:",