@transferwise/components 46.131.1 → 46.132.0
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.
- package/build/common/liveRegion/LiveRegion.js +46 -7
- package/build/common/liveRegion/LiveRegion.js.map +1 -1
- package/build/common/liveRegion/LiveRegion.mjs +46 -7
- package/build/common/liveRegion/LiveRegion.mjs.map +1 -1
- package/build/flowNavigation/FlowNavigation.js +1 -0
- package/build/flowNavigation/FlowNavigation.js.map +1 -1
- package/build/flowNavigation/FlowNavigation.mjs +1 -0
- package/build/flowNavigation/FlowNavigation.mjs.map +1 -1
- package/build/main.css +52 -1
- package/build/overlayHeader/OverlayHeader.js +1 -0
- package/build/overlayHeader/OverlayHeader.js.map +1 -1
- package/build/overlayHeader/OverlayHeader.mjs +1 -0
- package/build/overlayHeader/OverlayHeader.mjs.map +1 -1
- package/build/prompt/InfoPrompt/InfoPrompt.js +2 -0
- package/build/prompt/InfoPrompt/InfoPrompt.js.map +1 -1
- package/build/prompt/InfoPrompt/InfoPrompt.mjs +2 -0
- package/build/prompt/InfoPrompt/InfoPrompt.mjs.map +1 -1
- package/build/styles/common/liveRegion/LiveRegion.css +3 -0
- package/build/styles/css/neptune.css +48 -1
- package/build/styles/main.css +52 -1
- package/build/styles/styles/less/neptune.css +48 -1
- package/build/types/common/liveRegion/LiveRegion.d.ts +5 -2
- package/build/types/common/liveRegion/LiveRegion.d.ts.map +1 -1
- package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/alert/Alert.story.tsx +0 -6
- package/src/button/_stories/Button.story.tsx +0 -5
- package/src/checkboxButton/CheckboxButton.story.tsx +0 -1
- package/src/circularButton/CircularButton.story.tsx +0 -1
- package/src/common/liveRegion/LiveRegion.css +3 -0
- package/src/common/liveRegion/LiveRegion.less +3 -0
- package/src/common/liveRegion/LiveRegion.test.tsx +69 -2
- package/src/common/liveRegion/LiveRegion.tsx +77 -8
- package/src/dateLookup/DateLookup.test.story.tsx +0 -7
- package/src/dateLookup/DateLookup.test.tsx +22 -0
- package/src/display/Display.story.tsx +15 -1
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.story.tsx +0 -1
- package/src/header/Header.story.tsx +0 -5
- package/src/inputWithDisplayFormat/InputWithDisplayFormat.story.tsx +0 -1
- package/src/inputs/SelectInput/_stories/SelectInput.docs.mdx +62 -0
- package/src/inputs/SelectInput/_stories/SelectInput.story.tsx +796 -220
- package/src/inputs/SelectInput/_stories/SelectInput.test.story.tsx +433 -4
- package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.story.tsx +0 -5
- package/src/listItem/AvatarLayout/ListItemAvatarLayout.story.tsx +0 -5
- package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +0 -5
- package/src/listItem/Button/ListItemButton.story.tsx +0 -5
- package/src/listItem/Checkbox/ListItemCheckbox.story.tsx +0 -5
- package/src/listItem/IconButton/ListItemIconButton.story.tsx +0 -5
- package/src/listItem/Image/ListItemImage.story.tsx +0 -5
- package/src/listItem/Navigation/ListItemNavigation.story.tsx +0 -5
- package/src/listItem/Prompt/ListItemPrompt.story.tsx +1 -5
- package/src/listItem/Radio/ListItemRadio.story.tsx +0 -5
- package/src/listItem/Switch/ListItemSwitch.story.tsx +0 -5
- package/src/listItem/_stories/ListItem.disabled.story.tsx +0 -1
- package/src/listItem/_stories/ListItem.scenarios.story.tsx +0 -1
- package/src/listItem/_stories/ListItem.story.tsx +0 -5
- package/src/main.css +52 -1
- package/src/main.less +1 -0
- package/src/modal/Modal.story.tsx +0 -1
- package/src/popover/Popover.story.tsx +0 -1
- package/src/prompt/ActionPrompt/ActionPrompt.story.tsx +0 -5
- package/src/prompt/InfoPrompt/InfoPrompt.story.tsx +0 -5
- package/src/prompt/InfoPrompt/InfoPrompt.test.story.tsx +142 -5
- package/src/prompt/InfoPrompt/InfoPrompt.test.tsx +11 -6
- package/src/prompt/InfoPrompt/InfoPrompt.tsx +2 -1
- package/src/prompt/InlinePrompt/InlinePrompt.story.tsx +0 -5
- package/src/provider/theme/ThemeProvider.story.tsx +8 -0
- package/src/sentimentSurface/SentimentSurface.story.tsx +0 -5
- package/src/sticky/Sticky.story.tsx +0 -1
- package/src/styles/less/core/_typography.less +15 -2
- package/src/styles/less/neptune.css +48 -1
- package/src/tokens/tokens.story.tsx +1 -1
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
expect,
|
|
4
|
+
fireEvent,
|
|
5
|
+
fn,
|
|
6
|
+
type Mock,
|
|
7
|
+
screen,
|
|
8
|
+
userEvent,
|
|
9
|
+
waitFor,
|
|
10
|
+
within,
|
|
11
|
+
} from 'storybook/test';
|
|
12
|
+
import { Flag } from '@wise/art';
|
|
13
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
14
|
|
|
5
15
|
import { allModes } from '../../../../.storybook/modes';
|
|
16
|
+
import { withVariantConfig } from '../../../../.storybook/helpers';
|
|
6
17
|
import Body from '../../../body';
|
|
7
18
|
import { Field } from '../../../field/Field';
|
|
8
19
|
import { lorem5, lorem500 } from '../../../test-utils';
|
|
9
20
|
import { sortByRelevance } from '../SelectInput.utils';
|
|
10
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
SelectInput,
|
|
23
|
+
type SelectInputItem,
|
|
24
|
+
SelectInputOptionContent,
|
|
25
|
+
type SelectInputProps,
|
|
26
|
+
} from '..';
|
|
11
27
|
|
|
12
28
|
const meta = {
|
|
13
29
|
title: 'Forms/SelectInput/Tests',
|
|
@@ -18,12 +34,141 @@ const meta = {
|
|
|
18
34
|
onClose: fn() satisfies Mock,
|
|
19
35
|
onOpen: fn() satisfies Mock,
|
|
20
36
|
},
|
|
21
|
-
tags: ['!autodocs'],
|
|
37
|
+
tags: ['!autodocs', '!manifest'],
|
|
22
38
|
} satisfies Meta<typeof SelectInput>;
|
|
23
39
|
export default meta;
|
|
24
40
|
|
|
25
41
|
type Story<T, M extends boolean = false> = StoryObj<SelectInputProps<T, M>>;
|
|
26
42
|
|
|
43
|
+
interface TestMonth {
|
|
44
|
+
id: number;
|
|
45
|
+
name: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const testMonths: TestMonth[] = [
|
|
49
|
+
'January',
|
|
50
|
+
'February',
|
|
51
|
+
'March',
|
|
52
|
+
'April',
|
|
53
|
+
'May',
|
|
54
|
+
'June',
|
|
55
|
+
'July',
|
|
56
|
+
'August',
|
|
57
|
+
'September',
|
|
58
|
+
'October',
|
|
59
|
+
'November',
|
|
60
|
+
'December',
|
|
61
|
+
].map((name, index) => ({ id: index + 1, name }));
|
|
62
|
+
|
|
63
|
+
interface TestCurrency {
|
|
64
|
+
code: string;
|
|
65
|
+
name: string;
|
|
66
|
+
countries?: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const testPopularCurrencies: TestCurrency[] = [
|
|
70
|
+
{ code: 'USD', name: 'United States Dollar', countries: ['Hong Kong', 'Saudi Arabia'] },
|
|
71
|
+
{ code: 'EUR', name: 'Euro', countries: ['Spain', 'Germany', 'France', 'Austria', 'Estonia'] },
|
|
72
|
+
{ code: 'GBP', name: 'British pound', countries: ['England', 'Scotland', 'Wales'] },
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
const testAllCurrencies: TestCurrency[] = [
|
|
76
|
+
...testPopularCurrencies,
|
|
77
|
+
{ code: 'AUD', name: 'Australian dollar' },
|
|
78
|
+
{ code: 'CAD', name: 'Canadian dollar', countries: ['Canada'] },
|
|
79
|
+
{ code: 'ÅLD', name: 'Ålandian peso', countries: ['Ålandia'] },
|
|
80
|
+
].sort((a, b) => a.code.localeCompare(b.code));
|
|
81
|
+
|
|
82
|
+
function testCurrencyOption(currency: TestCurrency) {
|
|
83
|
+
return {
|
|
84
|
+
type: 'option',
|
|
85
|
+
value: currency,
|
|
86
|
+
filterMatchers: [currency.code, currency.name, ...(currency.countries ?? [])],
|
|
87
|
+
} satisfies SelectInputItem<TestCurrency>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Visual regression story: all three sizes rendered across every theme.
|
|
92
|
+
* - `sm` — opened, simple (months) list
|
|
93
|
+
* - `md` — closed
|
|
94
|
+
* - `lg` — opened, grouped currencies list
|
|
95
|
+
*/
|
|
96
|
+
export const Variants: Story<TestCurrency> = {
|
|
97
|
+
render: function Render() {
|
|
98
|
+
const smRef = useRef<HTMLButtonElement | null>(null);
|
|
99
|
+
const lgRef = useRef<HTMLButtonElement | null>(null);
|
|
100
|
+
|
|
101
|
+
const simpleItems: SelectInputItem<TestMonth>[] = testMonths.map((month) => ({
|
|
102
|
+
type: 'option',
|
|
103
|
+
value: month,
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
const groupedItems: SelectInputItem<TestCurrency>[] = [
|
|
107
|
+
{
|
|
108
|
+
type: 'group',
|
|
109
|
+
label: 'Popular currencies',
|
|
110
|
+
options: testPopularCurrencies.map(testCurrencyOption),
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'group',
|
|
114
|
+
label: 'All currencies',
|
|
115
|
+
options: testAllCurrencies.map(testCurrencyOption),
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
const timer = setTimeout(() => {
|
|
121
|
+
smRef.current?.click();
|
|
122
|
+
setTimeout(() => {
|
|
123
|
+
lgRef.current?.click();
|
|
124
|
+
}, 100);
|
|
125
|
+
}, 200);
|
|
126
|
+
return () => clearTimeout(timer);
|
|
127
|
+
}, []);
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<div style={{ display: 'flex', gap: '2rem' }}>
|
|
131
|
+
<div style={{ minHeight: '550px', width: '280px' }}>
|
|
132
|
+
<p className="np-text-body-small m-b-1">Small (opened)</p>
|
|
133
|
+
<SelectInput<TestMonth>
|
|
134
|
+
size="sm"
|
|
135
|
+
placeholder="Month"
|
|
136
|
+
items={simpleItems}
|
|
137
|
+
triggerRef={smRef}
|
|
138
|
+
renderValue={(month) => <SelectInputOptionContent title={month.name} />}
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
<div style={{ width: '280px' }}>
|
|
142
|
+
<p className="np-text-body-small m-b-1">Medium</p>
|
|
143
|
+
<SelectInput<TestMonth>
|
|
144
|
+
size="md"
|
|
145
|
+
placeholder="Month"
|
|
146
|
+
items={simpleItems}
|
|
147
|
+
renderValue={(month) => <SelectInputOptionContent title={month.name} />}
|
|
148
|
+
/>
|
|
149
|
+
</div>
|
|
150
|
+
<div style={{ minHeight: '550px', width: '280px' }}>
|
|
151
|
+
<p className="np-text-body-small m-b-1">Large (opened)</p>
|
|
152
|
+
<SelectInput<TestCurrency>
|
|
153
|
+
size="lg"
|
|
154
|
+
placeholder="Currency"
|
|
155
|
+
items={groupedItems}
|
|
156
|
+
triggerRef={lgRef}
|
|
157
|
+
renderValue={(currency) => (
|
|
158
|
+
<SelectInputOptionContent
|
|
159
|
+
title={currency.code}
|
|
160
|
+
note={currency.name}
|
|
161
|
+
icon={<Flag code={currency.code} intrinsicSize={24} />}
|
|
162
|
+
/>
|
|
163
|
+
)}
|
|
164
|
+
/>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
},
|
|
169
|
+
...withVariantConfig(['default', 'dark', 'bright-green', 'forest-green', 'rtl']),
|
|
170
|
+
};
|
|
171
|
+
|
|
27
172
|
/**
|
|
28
173
|
* Test story with a large list of countries where almost all have "United States dollar"
|
|
29
174
|
* in their metadata. This reproduces the bug where searching "united" would scroll to
|
|
@@ -1308,6 +1453,250 @@ const wait = async (duration = 500) =>
|
|
|
1308
1453
|
setTimeout(resolve, duration);
|
|
1309
1454
|
});
|
|
1310
1455
|
|
|
1456
|
+
const currencyInteractionArgs = {
|
|
1457
|
+
items: [
|
|
1458
|
+
{
|
|
1459
|
+
type: 'group',
|
|
1460
|
+
label: 'Popular currencies',
|
|
1461
|
+
options: testPopularCurrencies.map(testCurrencyOption),
|
|
1462
|
+
},
|
|
1463
|
+
{
|
|
1464
|
+
type: 'group',
|
|
1465
|
+
label: 'All currencies',
|
|
1466
|
+
options: testAllCurrencies.map(testCurrencyOption),
|
|
1467
|
+
},
|
|
1468
|
+
],
|
|
1469
|
+
defaultValue: testPopularCurrencies[0],
|
|
1470
|
+
renderValue: (currency: TestCurrency) => (
|
|
1471
|
+
<SelectInputOptionContent title={currency.code} note={currency.name} />
|
|
1472
|
+
),
|
|
1473
|
+
renderFooter: ({
|
|
1474
|
+
resultsEmpty,
|
|
1475
|
+
queryNormalized,
|
|
1476
|
+
}: {
|
|
1477
|
+
resultsEmpty: boolean;
|
|
1478
|
+
queryNormalized: string | null | undefined;
|
|
1479
|
+
}) =>
|
|
1480
|
+
resultsEmpty && queryNormalized != null && /^[a-z]{3}$/u.test(queryNormalized) ? (
|
|
1481
|
+
<>
|
|
1482
|
+
It is not possible to use {queryNormalized.toUpperCase()} yet.{' '}
|
|
1483
|
+
<a href="#_" onClick={(e) => e.preventDefault()}>
|
|
1484
|
+
Email me when it is available.
|
|
1485
|
+
</a>
|
|
1486
|
+
</>
|
|
1487
|
+
) : (
|
|
1488
|
+
<>
|
|
1489
|
+
Cannot find it?{' '}
|
|
1490
|
+
<a href="#_" onClick={(e) => e.preventDefault()}>
|
|
1491
|
+
Request the currency you need,
|
|
1492
|
+
</a>{' '}
|
|
1493
|
+
and we will notify you once it is available.
|
|
1494
|
+
</>
|
|
1495
|
+
),
|
|
1496
|
+
filterable: true,
|
|
1497
|
+
filterPlaceholder: 'Type a currency / country',
|
|
1498
|
+
size: 'lg',
|
|
1499
|
+
} satisfies Story<TestCurrency>['args'];
|
|
1500
|
+
|
|
1501
|
+
export const BasicInteraction: Story<TestMonth | null> = {
|
|
1502
|
+
args: {
|
|
1503
|
+
placeholder: 'Month',
|
|
1504
|
+
items: testMonths.map((month) => ({ type: 'option', value: month })),
|
|
1505
|
+
renderValue: (month) => <SelectInputOptionContent title={month.name} />,
|
|
1506
|
+
},
|
|
1507
|
+
render: function Render({ onChange, onClear, ...args }) {
|
|
1508
|
+
const [selectedMonth, setSelectedMonth] = useState<TestMonth | null>(null);
|
|
1509
|
+
return (
|
|
1510
|
+
<SelectInput
|
|
1511
|
+
{...args}
|
|
1512
|
+
value={selectedMonth}
|
|
1513
|
+
onChange={(month) => {
|
|
1514
|
+
setSelectedMonth(month);
|
|
1515
|
+
onChange?.(month);
|
|
1516
|
+
}}
|
|
1517
|
+
onClear={() => {
|
|
1518
|
+
setSelectedMonth(null);
|
|
1519
|
+
onClear?.();
|
|
1520
|
+
}}
|
|
1521
|
+
/>
|
|
1522
|
+
);
|
|
1523
|
+
},
|
|
1524
|
+
play: async ({ canvasElement, step }) => {
|
|
1525
|
+
const canvas = within(canvasElement);
|
|
1526
|
+
|
|
1527
|
+
await step('renders placeholder', async () => {
|
|
1528
|
+
const triggerButton = canvas.getByRole('combobox');
|
|
1529
|
+
await waitFor(async () => expect(triggerButton).toHaveTextContent('Month'));
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
await step('selects option via mouse', async () => {
|
|
1533
|
+
const triggerButton = canvas.getByRole('combobox');
|
|
1534
|
+
await userEvent.click(triggerButton);
|
|
1535
|
+
await userEvent.unhover(triggerButton);
|
|
1536
|
+
const option = within(screen.getByRole('listbox')).getByRole('option', { name: 'May' });
|
|
1537
|
+
await userEvent.click(option);
|
|
1538
|
+
await waitFor(async () => expect(triggerButton).toHaveTextContent('May'));
|
|
1539
|
+
});
|
|
1540
|
+
},
|
|
1541
|
+
};
|
|
1542
|
+
|
|
1543
|
+
export const KeyboardInteraction: Story<TestCurrency> = {
|
|
1544
|
+
args: currencyInteractionArgs,
|
|
1545
|
+
play: async ({ step }) => {
|
|
1546
|
+
await step('Tab to the combobox', async () => {
|
|
1547
|
+
await userEvent.tab();
|
|
1548
|
+
});
|
|
1549
|
+
|
|
1550
|
+
await step('Open the combobox', async () => {
|
|
1551
|
+
await userEvent.keyboard(' ');
|
|
1552
|
+
});
|
|
1553
|
+
|
|
1554
|
+
await step('Check if options are displayed', async () => {
|
|
1555
|
+
await waitFor(async () => expect(await screen.findAllByRole('option')).toHaveLength(9));
|
|
1556
|
+
await waitFor(async () => expect(screen.getByText(/^Cannot find it\?/u)).toBeInTheDocument());
|
|
1557
|
+
});
|
|
1558
|
+
|
|
1559
|
+
await step('Type "huf" in the combobox', async () => {
|
|
1560
|
+
// this is workaround for Chromatic: Firefox and Edge tests failing.
|
|
1561
|
+
// Unclear on a proper solution
|
|
1562
|
+
await wait(750);
|
|
1563
|
+
const input = await screen.findByRole('combobox');
|
|
1564
|
+
await userEvent.type(input, 'huf');
|
|
1565
|
+
});
|
|
1566
|
+
|
|
1567
|
+
await step('Check if no options are displayed', async () => {
|
|
1568
|
+
// this is workaround for Chromatic: Firefox and Edge tests failing.
|
|
1569
|
+
// Unclear on a proper solution
|
|
1570
|
+
await wait(750);
|
|
1571
|
+
await expect(await screen.findByText(/^No results found/u)).toBeInTheDocument();
|
|
1572
|
+
await expect(
|
|
1573
|
+
await screen.findByText(/^It is not possible to use HUF yet\./u),
|
|
1574
|
+
).toBeInTheDocument();
|
|
1575
|
+
await waitFor(
|
|
1576
|
+
async () => {
|
|
1577
|
+
await expect(screen.queryAllByRole('option')).toHaveLength(0);
|
|
1578
|
+
},
|
|
1579
|
+
{ timeout: 1500 },
|
|
1580
|
+
);
|
|
1581
|
+
});
|
|
1582
|
+
|
|
1583
|
+
await step('Remove last two characters', async () => {
|
|
1584
|
+
await wait(500);
|
|
1585
|
+
const input = await screen.findByRole('combobox');
|
|
1586
|
+
await userEvent.type(input, '{Backspace}{Backspace}');
|
|
1587
|
+
});
|
|
1588
|
+
|
|
1589
|
+
await step('Check if two options are displayed', async () => {
|
|
1590
|
+
await waitFor(async () =>
|
|
1591
|
+
expect(within(screen.getByRole('listbox')).queryAllByRole('option')).toHaveLength(2),
|
|
1592
|
+
);
|
|
1593
|
+
});
|
|
1594
|
+
|
|
1595
|
+
await step('Type "e" in the combobox', async () => {
|
|
1596
|
+
const input = await screen.findByRole('combobox');
|
|
1597
|
+
await userEvent.type(input, '{Backspace}e');
|
|
1598
|
+
});
|
|
1599
|
+
|
|
1600
|
+
await step('Check if aria-activedescendant is set', async () => {
|
|
1601
|
+
const input = screen.getByRole('combobox');
|
|
1602
|
+
await waitFor(async () => expect(input).toHaveAttribute('aria-activedescendant'));
|
|
1603
|
+
});
|
|
1604
|
+
},
|
|
1605
|
+
};
|
|
1606
|
+
|
|
1607
|
+
export const MultiSelectInteraction: Story<TestCurrency, true> = {
|
|
1608
|
+
args: {
|
|
1609
|
+
...currencyInteractionArgs,
|
|
1610
|
+
multiple: true,
|
|
1611
|
+
placeholder: 'Choose currencies…',
|
|
1612
|
+
defaultValue: [testPopularCurrencies[0]],
|
|
1613
|
+
renderValue: (currency, withinTrigger) =>
|
|
1614
|
+
withinTrigger ? (
|
|
1615
|
+
currency.code
|
|
1616
|
+
) : (
|
|
1617
|
+
<SelectInputOptionContent title={currency.code} note={currency.name} />
|
|
1618
|
+
),
|
|
1619
|
+
},
|
|
1620
|
+
play: async ({ canvasElement, step, args }) => {
|
|
1621
|
+
const canvas = within(canvasElement);
|
|
1622
|
+
|
|
1623
|
+
await step('Open the combobox', async () => {
|
|
1624
|
+
const triggerButton = canvas.getByRole('combobox');
|
|
1625
|
+
await userEvent.click(triggerButton);
|
|
1626
|
+
await wait(500);
|
|
1627
|
+
await userEvent.unhover(triggerButton);
|
|
1628
|
+
await expect(args.onOpen).toHaveBeenCalledOnce();
|
|
1629
|
+
});
|
|
1630
|
+
|
|
1631
|
+
await step('Select EUR option', async () => {
|
|
1632
|
+
const option = within(screen.getByRole('listbox')).getAllByRole('option', {
|
|
1633
|
+
name: /^EUR/u,
|
|
1634
|
+
})[0];
|
|
1635
|
+
await wait(500);
|
|
1636
|
+
await userEvent.click(option);
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
await step('Check if selected options are displayed in trigger', async () => {
|
|
1640
|
+
const triggerButton = document.querySelector('button[role="combobox"]');
|
|
1641
|
+
await waitFor(async () => expect(triggerButton).toHaveTextContent('USD, EUR'));
|
|
1642
|
+
});
|
|
1643
|
+
},
|
|
1644
|
+
};
|
|
1645
|
+
|
|
1646
|
+
/**
|
|
1647
|
+
* Verifies that currencies with non-ASCII characters (e.g. ÅLD / Ålandian peso)
|
|
1648
|
+
* render correctly in the dropdown and can be found via filter.
|
|
1649
|
+
*/
|
|
1650
|
+
export const SpecialCharacterOptions: Story<TestCurrency> = {
|
|
1651
|
+
args: {
|
|
1652
|
+
...currencyInteractionArgs,
|
|
1653
|
+
filterable: true,
|
|
1654
|
+
filterPlaceholder: 'Type a currency',
|
|
1655
|
+
},
|
|
1656
|
+
play: async ({ canvasElement, step }) => {
|
|
1657
|
+
const canvas = within(canvasElement);
|
|
1658
|
+
|
|
1659
|
+
await step('Open the combobox', async () => {
|
|
1660
|
+
const triggerButton = canvas.getByRole('combobox');
|
|
1661
|
+
await userEvent.click(triggerButton);
|
|
1662
|
+
await userEvent.unhover(triggerButton);
|
|
1663
|
+
});
|
|
1664
|
+
|
|
1665
|
+
await step('ÅLD option is visible in dropdown', async () => {
|
|
1666
|
+
await waitFor(async () =>
|
|
1667
|
+
expect(
|
|
1668
|
+
within(screen.getByRole('listbox')).getByRole('option', { name: /ÅLD/u }),
|
|
1669
|
+
).toBeInTheDocument(),
|
|
1670
|
+
);
|
|
1671
|
+
});
|
|
1672
|
+
|
|
1673
|
+
await step('Filter for Ålandian peso', async () => {
|
|
1674
|
+
await wait(500);
|
|
1675
|
+
const input = await screen.findByRole('combobox');
|
|
1676
|
+
await userEvent.type(input, 'åla');
|
|
1677
|
+
});
|
|
1678
|
+
|
|
1679
|
+
await step('Only ÅLD option remains', async () => {
|
|
1680
|
+
await waitFor(async () =>
|
|
1681
|
+
expect(within(screen.getByRole('listbox')).getAllByRole('option')).toHaveLength(1),
|
|
1682
|
+
);
|
|
1683
|
+
});
|
|
1684
|
+
},
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
export const WithClearInteraction: Story<TestCurrency> = {
|
|
1688
|
+
args: {
|
|
1689
|
+
...currencyInteractionArgs,
|
|
1690
|
+
onClear: fn() satisfies Mock,
|
|
1691
|
+
},
|
|
1692
|
+
play: async ({ step }) => {
|
|
1693
|
+
await step('Has clear button', async () => {
|
|
1694
|
+
const clearBtn = await screen.findByRole('button', { name: 'Clear' });
|
|
1695
|
+
await expect(clearBtn).toBeInTheDocument();
|
|
1696
|
+
});
|
|
1697
|
+
},
|
|
1698
|
+
};
|
|
1699
|
+
|
|
1311
1700
|
/**
|
|
1312
1701
|
* This test ensures that when the SelectInput is used within a scrollable page,
|
|
1313
1702
|
* opening the dropdown does not cause any unwanted scrolling or layout shifts.
|
|
@@ -1416,3 +1805,43 @@ export const TriggerWithDescription: Story<OptionWithDescription> = {
|
|
|
1416
1805
|
);
|
|
1417
1806
|
},
|
|
1418
1807
|
};
|
|
1808
|
+
|
|
1809
|
+
/** Basic months dropdown at 400% zoom for accessibility testing. */
|
|
1810
|
+
export const Zoom400: Story<TestMonth | null> = {
|
|
1811
|
+
render: function Render({ onChange, onClear, ...args }) {
|
|
1812
|
+
const triggerRef = useRef<HTMLButtonElement | null>(null);
|
|
1813
|
+
const [selectedMonth, setSelectedMonth] = useState<TestMonth | null>(null);
|
|
1814
|
+
|
|
1815
|
+
useEffect(() => {
|
|
1816
|
+
const timer = setTimeout(() => {
|
|
1817
|
+
triggerRef.current?.click();
|
|
1818
|
+
}, 200);
|
|
1819
|
+
return () => clearTimeout(timer);
|
|
1820
|
+
}, []);
|
|
1821
|
+
|
|
1822
|
+
return (
|
|
1823
|
+
<SelectInput
|
|
1824
|
+
{...args}
|
|
1825
|
+
triggerRef={triggerRef}
|
|
1826
|
+
value={selectedMonth}
|
|
1827
|
+
onChange={(month) => {
|
|
1828
|
+
setSelectedMonth(month);
|
|
1829
|
+
onChange?.(month);
|
|
1830
|
+
}}
|
|
1831
|
+
onClear={() => {
|
|
1832
|
+
setSelectedMonth(null);
|
|
1833
|
+
onClear?.();
|
|
1834
|
+
}}
|
|
1835
|
+
/>
|
|
1836
|
+
);
|
|
1837
|
+
},
|
|
1838
|
+
args: {
|
|
1839
|
+
placeholder: 'Month',
|
|
1840
|
+
items: testMonths.map((month) => ({
|
|
1841
|
+
type: 'option',
|
|
1842
|
+
value: month,
|
|
1843
|
+
})),
|
|
1844
|
+
renderValue: (month) => <SelectInputOptionContent title={month.name} />,
|
|
1845
|
+
},
|
|
1846
|
+
...withVariantConfig(['400%']),
|
|
1847
|
+
};
|
|
@@ -19,11 +19,6 @@ import type { ListItemAdditionalInfoProps } from './ListItemAdditionalInfo';
|
|
|
19
19
|
export default {
|
|
20
20
|
component: ListItem.AdditionalInfo,
|
|
21
21
|
title: 'Content/ListItem/ListItem.AdditionalInfo',
|
|
22
|
-
parameters: {
|
|
23
|
-
docs: {
|
|
24
|
-
toc: true,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
22
|
args: {
|
|
28
23
|
children: lorem20,
|
|
29
24
|
},
|
|
@@ -13,11 +13,6 @@ import type { ListItemAvatarLayoutProps } from './ListItemAvatarLayout';
|
|
|
13
13
|
export default {
|
|
14
14
|
component: ListItem.AvatarLayout,
|
|
15
15
|
title: 'Content/ListItem/ListItem.AvatarLayout',
|
|
16
|
-
parameters: {
|
|
17
|
-
docs: {
|
|
18
|
-
toc: true,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
16
|
args: {
|
|
22
17
|
avatars: [{ asset: <Flag code="gb" /> }, { asset: <Flag code="eur" /> }],
|
|
23
18
|
orientation: 'horizontal',
|
|
@@ -77,11 +77,6 @@ const getPropsForPreview = (args: PreviewStoryArgs) => {
|
|
|
77
77
|
const meta: Meta<typeof ListItem.Button> = {
|
|
78
78
|
component: ListItem.Button,
|
|
79
79
|
title: 'Content/ListItem/ListItem.Button',
|
|
80
|
-
parameters: {
|
|
81
|
-
docs: {
|
|
82
|
-
toc: true,
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
80
|
args: {
|
|
86
81
|
partiallyInteractive: false,
|
|
87
82
|
priority: 'secondary-neutral',
|
|
@@ -12,11 +12,6 @@ import { fn } from 'storybook/test';
|
|
|
12
12
|
const meta: Meta<ListItemCheckboxProps> = {
|
|
13
13
|
component: ListItem.Checkbox,
|
|
14
14
|
title: 'Content/ListItem/ListItem.Checkbox',
|
|
15
|
-
parameters: {
|
|
16
|
-
docs: {
|
|
17
|
-
toc: true,
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
15
|
args: {
|
|
21
16
|
checked: false,
|
|
22
17
|
indeterminate: false,
|
|
@@ -27,11 +27,6 @@ const hideControls = disableControls([
|
|
|
27
27
|
const meta: Meta<ListItemIconButtonProps> = {
|
|
28
28
|
component: ListItem.IconButton,
|
|
29
29
|
title: 'Content/ListItem/ListItem.IconButton',
|
|
30
|
-
parameters: {
|
|
31
|
-
docs: {
|
|
32
|
-
toc: true,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
30
|
args: {
|
|
36
31
|
partiallyInteractive: false,
|
|
37
32
|
priority: undefined,
|
|
@@ -12,11 +12,6 @@ import type { ListItemImageProps } from './ListItemImage';
|
|
|
12
12
|
export default {
|
|
13
13
|
component: ListItem.Image,
|
|
14
14
|
title: 'Content/ListItem/ListItem.Image',
|
|
15
|
-
parameters: {
|
|
16
|
-
docs: {
|
|
17
|
-
toc: true,
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
15
|
args: {
|
|
21
16
|
size: 48,
|
|
22
17
|
loading: undefined,
|
|
@@ -13,11 +13,6 @@ import type { ListItemNavigationProps } from './ListItemNavigation';
|
|
|
13
13
|
const meta: Meta<ListItemNavigationProps> = {
|
|
14
14
|
component: ListItem.Navigation,
|
|
15
15
|
title: 'Content/ListItem/ListItem.Navigation',
|
|
16
|
-
parameters: {
|
|
17
|
-
docs: {
|
|
18
|
-
toc: true,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
16
|
args: {
|
|
22
17
|
href: 'https://wise.com',
|
|
23
18
|
onClick: fn(),
|
|
@@ -16,11 +16,7 @@ import { Clock } from '@transferwise/icons';
|
|
|
16
16
|
const meta: Meta<ListItemPromptProps> = {
|
|
17
17
|
component: Prompt,
|
|
18
18
|
title: 'Content/ListItem/ListItem.Prompt',
|
|
19
|
-
|
|
20
|
-
docs: {
|
|
21
|
-
toc: true,
|
|
22
|
-
},
|
|
23
|
-
},
|
|
19
|
+
|
|
24
20
|
decorators: [withoutKey],
|
|
25
21
|
args: {
|
|
26
22
|
sentiment: undefined,
|
|
@@ -13,11 +13,6 @@ import { ProfileType } from '../../common';
|
|
|
13
13
|
const meta: Meta<ListItemRadioProps> = {
|
|
14
14
|
component: ListItem.Radio,
|
|
15
15
|
title: 'Content/ListItem/ListItem.Radio',
|
|
16
|
-
parameters: {
|
|
17
|
-
docs: {
|
|
18
|
-
toc: true,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
16
|
args: {
|
|
22
17
|
name: 'radio-group',
|
|
23
18
|
value: 'option1',
|
|
@@ -12,11 +12,6 @@ import type { ListItemSwitchProps } from './ListItemSwitch';
|
|
|
12
12
|
const meta: Meta<ListItemSwitchProps> = {
|
|
13
13
|
component: ListItem.Switch,
|
|
14
14
|
title: 'Content/ListItem/ListItem.Switch',
|
|
15
|
-
parameters: {
|
|
16
|
-
docs: {
|
|
17
|
-
toc: true,
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
15
|
args: {
|
|
21
16
|
checked: false,
|
|
22
17
|
onClick: fn(),
|