uikit-react-public 0.49.3 → 0.49.5
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/dist/components/Select/index.d.ts +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +15 -0
- package/dist/components/ToggleGroup/ToggleGroup.stories.d.ts +18 -0
- package/dist/components/ToggleGroup/ToggleGroupContext.d.ts +8 -0
- package/dist/components/ToggleGroup/__tests__/ToggleGroup.test.d.ts +1 -0
- package/dist/components/ToggleGroup/index.d.ts +4 -0
- package/dist/components/ToggleGroup/subcomponents/Item.d.ts +11 -0
- package/dist/components/ToggleGroup/subcomponents/Item.stories.d.ts +331 -0
- package/dist/components/ToggleGroup/subcomponents/__tests__/Item.test.d.ts +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/index.js +7108 -6874
- package/lib/components/ConfidentialDisplayField/Documentation.mdx +1 -1
- package/lib/components/ConfidentialDisplayField/__tests__/ConfidentialDisplayField.test.tsx +5 -5
- package/lib/components/ConfidentialInput/Documentation.mdx +1 -1
- package/lib/components/ConfidentialInput/__tests__/ConfidentialInput.test.tsx +11 -11
- package/lib/components/Icon/svgImports.ts +4 -2
- package/lib/components/Select/index.ts +5 -1
- package/lib/components/ToggleGroup/ToggleGroup.mdx +31 -0
- package/lib/components/ToggleGroup/ToggleGroup.stories.tsx +120 -0
- package/lib/components/ToggleGroup/ToggleGroup.tsx +144 -0
- package/lib/components/ToggleGroup/ToggleGroupContext.tsx +25 -0
- package/lib/components/ToggleGroup/__tests__/ToggleGroup.test.tsx +468 -0
- package/lib/components/ToggleGroup/index.ts +4 -0
- package/lib/components/ToggleGroup/subcomponents/Item.stories.tsx +63 -0
- package/lib/components/ToggleGroup/subcomponents/Item.tsx +233 -0
- package/lib/components/ToggleGroup/subcomponents/__tests__/Item.test.tsx +195 -0
- package/lib/components/common/formatConfidentialValue.ts +1 -1
- package/lib/components/index.ts +3 -0
- package/package.json +3 -3
- package/dist/components/Icon/svgImports.d.ts +0 -8
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import ToggleGroup from '../ToggleGroup';
|
|
5
|
+
import ToggleGroupItem from '../subcomponents/Item';
|
|
6
|
+
import { ThemeContextProvider } from '../../../theme/useTheme';
|
|
7
|
+
|
|
8
|
+
const mockMatchMedia = (matchesDesktop: boolean) => {
|
|
9
|
+
globalThis.matchMedia = vi.fn().mockImplementation((query) => ({
|
|
10
|
+
matches: query.includes('min-width') ? matchesDesktop : false,
|
|
11
|
+
media: query,
|
|
12
|
+
addListener: vi.fn(),
|
|
13
|
+
removeListener: vi.fn(),
|
|
14
|
+
addEventListener: vi.fn(),
|
|
15
|
+
removeEventListener: vi.fn(),
|
|
16
|
+
dispatchEvent: vi.fn(),
|
|
17
|
+
}));
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const wrap = (ui: React.ReactElement) =>
|
|
21
|
+
render(<ThemeContextProvider>{ui}</ThemeContextProvider>);
|
|
22
|
+
|
|
23
|
+
describe('ToggleGroup', () => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
mockMatchMedia(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('renders a radiogroup with selectable radio items', () => {
|
|
29
|
+
const onValueChange = vi.fn();
|
|
30
|
+
|
|
31
|
+
wrap(
|
|
32
|
+
<ToggleGroup
|
|
33
|
+
defaultValue='option-1'
|
|
34
|
+
onValueChange={onValueChange}
|
|
35
|
+
>
|
|
36
|
+
<ToggleGroupItem
|
|
37
|
+
value='option-1'
|
|
38
|
+
label='Option 1'
|
|
39
|
+
/>
|
|
40
|
+
<ToggleGroupItem
|
|
41
|
+
value='option-2'
|
|
42
|
+
label='Option 2'
|
|
43
|
+
/>
|
|
44
|
+
</ToggleGroup>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(screen.getByRole('radiogroup')).toBeInTheDocument();
|
|
48
|
+
expect(screen.getByRole('radio', { name: 'Option 1' })).toHaveAttribute(
|
|
49
|
+
'aria-checked',
|
|
50
|
+
'true'
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
fireEvent.click(screen.getByRole('radio', { name: 'Option 2' }));
|
|
54
|
+
|
|
55
|
+
expect(onValueChange).toHaveBeenCalledWith('option-2');
|
|
56
|
+
expect(screen.getByRole('radio', { name: 'Option 2' })).toHaveAttribute(
|
|
57
|
+
'aria-checked',
|
|
58
|
+
'true'
|
|
59
|
+
);
|
|
60
|
+
expect(screen.getByRole('radio', { name: 'Option 1' })).toHaveAttribute(
|
|
61
|
+
'aria-checked',
|
|
62
|
+
'false'
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('only ever has one selected item at a time', () => {
|
|
67
|
+
wrap(
|
|
68
|
+
<ToggleGroup defaultValue='option-1'>
|
|
69
|
+
<ToggleGroupItem
|
|
70
|
+
value='option-1'
|
|
71
|
+
label='Option 1'
|
|
72
|
+
/>
|
|
73
|
+
<ToggleGroupItem
|
|
74
|
+
value='option-2'
|
|
75
|
+
label='Option 2'
|
|
76
|
+
/>
|
|
77
|
+
<ToggleGroupItem
|
|
78
|
+
value='option-3'
|
|
79
|
+
label='Option 3'
|
|
80
|
+
/>
|
|
81
|
+
</ToggleGroup>
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
fireEvent.click(screen.getByRole('radio', { name: 'Option 3' }));
|
|
85
|
+
|
|
86
|
+
const checked = screen
|
|
87
|
+
.getAllByRole('radio')
|
|
88
|
+
.filter((item) => item.getAttribute('aria-checked') === 'true');
|
|
89
|
+
|
|
90
|
+
expect(checked).toHaveLength(1);
|
|
91
|
+
expect(checked[0]).toHaveAccessibleName('Option 3');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('behaves as a controlled component when value is provided', () => {
|
|
95
|
+
const onValueChange = vi.fn();
|
|
96
|
+
|
|
97
|
+
const { rerender } = wrap(
|
|
98
|
+
<ToggleGroup
|
|
99
|
+
value='option-1'
|
|
100
|
+
onValueChange={onValueChange}
|
|
101
|
+
>
|
|
102
|
+
<ToggleGroupItem
|
|
103
|
+
value='option-1'
|
|
104
|
+
label='Option 1'
|
|
105
|
+
/>
|
|
106
|
+
<ToggleGroupItem
|
|
107
|
+
value='option-2'
|
|
108
|
+
label='Option 2'
|
|
109
|
+
/>
|
|
110
|
+
</ToggleGroup>
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
fireEvent.click(screen.getByRole('radio', { name: 'Option 2' }));
|
|
114
|
+
|
|
115
|
+
expect(onValueChange).toHaveBeenCalledWith('option-2');
|
|
116
|
+
// Selection does not change without the caller updating the value prop
|
|
117
|
+
expect(screen.getByRole('radio', { name: 'Option 1' })).toHaveAttribute(
|
|
118
|
+
'aria-checked',
|
|
119
|
+
'true'
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
rerender(
|
|
123
|
+
<ThemeContextProvider>
|
|
124
|
+
<ToggleGroup
|
|
125
|
+
value='option-2'
|
|
126
|
+
onValueChange={onValueChange}
|
|
127
|
+
>
|
|
128
|
+
<ToggleGroupItem
|
|
129
|
+
value='option-1'
|
|
130
|
+
label='Option 1'
|
|
131
|
+
/>
|
|
132
|
+
<ToggleGroupItem
|
|
133
|
+
value='option-2'
|
|
134
|
+
label='Option 2'
|
|
135
|
+
/>
|
|
136
|
+
</ToggleGroup>
|
|
137
|
+
</ThemeContextProvider>
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
expect(screen.getByRole('radio', { name: 'Option 2' })).toHaveAttribute(
|
|
141
|
+
'aria-checked',
|
|
142
|
+
'true'
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('moves focus and selection with arrow keys', () => {
|
|
147
|
+
wrap(
|
|
148
|
+
<ToggleGroup defaultValue='option-1'>
|
|
149
|
+
<ToggleGroupItem
|
|
150
|
+
value='option-1'
|
|
151
|
+
label='Option 1'
|
|
152
|
+
/>
|
|
153
|
+
<ToggleGroupItem
|
|
154
|
+
value='option-2'
|
|
155
|
+
label='Option 2'
|
|
156
|
+
/>
|
|
157
|
+
<ToggleGroupItem
|
|
158
|
+
value='option-3'
|
|
159
|
+
label='Option 3'
|
|
160
|
+
/>
|
|
161
|
+
</ToggleGroup>
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const option1 = screen.getByRole('radio', { name: 'Option 1' });
|
|
165
|
+
const option2 = screen.getByRole('radio', { name: 'Option 2' });
|
|
166
|
+
const option3 = screen.getByRole('radio', { name: 'Option 3' });
|
|
167
|
+
|
|
168
|
+
option1.focus();
|
|
169
|
+
fireEvent.keyDown(screen.getByRole('radiogroup'), { key: 'ArrowRight' });
|
|
170
|
+
|
|
171
|
+
expect(option2).toHaveFocus();
|
|
172
|
+
expect(option2).toHaveAttribute('aria-checked', 'true');
|
|
173
|
+
|
|
174
|
+
fireEvent.keyDown(screen.getByRole('radiogroup'), { key: 'End' });
|
|
175
|
+
|
|
176
|
+
expect(option3).toHaveFocus();
|
|
177
|
+
expect(option3).toHaveAttribute('aria-checked', 'true');
|
|
178
|
+
|
|
179
|
+
fireEvent.keyDown(screen.getByRole('radiogroup'), { key: 'Home' });
|
|
180
|
+
|
|
181
|
+
expect(option1).toHaveFocus();
|
|
182
|
+
expect(option1).toHaveAttribute('aria-checked', 'true');
|
|
183
|
+
|
|
184
|
+
fireEvent.keyDown(screen.getByRole('radiogroup'), { key: 'ArrowLeft' });
|
|
185
|
+
|
|
186
|
+
expect(option3).toHaveFocus();
|
|
187
|
+
expect(option3).toHaveAttribute('aria-checked', 'true');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test('skips disabled items when navigating with arrow keys', () => {
|
|
191
|
+
wrap(
|
|
192
|
+
<ToggleGroup defaultValue='option-1'>
|
|
193
|
+
<ToggleGroupItem
|
|
194
|
+
value='option-1'
|
|
195
|
+
label='Option 1'
|
|
196
|
+
/>
|
|
197
|
+
<ToggleGroupItem
|
|
198
|
+
value='option-2'
|
|
199
|
+
label='Option 2'
|
|
200
|
+
disabled
|
|
201
|
+
/>
|
|
202
|
+
<ToggleGroupItem
|
|
203
|
+
value='option-3'
|
|
204
|
+
label='Option 3'
|
|
205
|
+
/>
|
|
206
|
+
</ToggleGroup>
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const option1 = screen.getByRole('radio', { name: 'Option 1' });
|
|
210
|
+
const option3 = screen.getByRole('radio', { name: 'Option 3' });
|
|
211
|
+
|
|
212
|
+
option1.focus();
|
|
213
|
+
fireEvent.keyDown(screen.getByRole('radiogroup'), { key: 'ArrowRight' });
|
|
214
|
+
|
|
215
|
+
expect(option3).toHaveFocus();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test('ignores non-navigation keys', () => {
|
|
219
|
+
wrap(
|
|
220
|
+
<ToggleGroup defaultValue='option-1'>
|
|
221
|
+
<ToggleGroupItem
|
|
222
|
+
value='option-1'
|
|
223
|
+
label='Option 1'
|
|
224
|
+
/>
|
|
225
|
+
<ToggleGroupItem
|
|
226
|
+
value='option-2'
|
|
227
|
+
label='Option 2'
|
|
228
|
+
/>
|
|
229
|
+
</ToggleGroup>
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const option1 = screen.getByRole('radio', { name: 'Option 1' });
|
|
233
|
+
|
|
234
|
+
option1.focus();
|
|
235
|
+
fireEvent.keyDown(screen.getByRole('radiogroup'), { key: 'a' });
|
|
236
|
+
|
|
237
|
+
expect(option1).toHaveFocus();
|
|
238
|
+
expect(option1).toHaveAttribute('aria-checked', 'true');
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe('ToggleGroup mobile select fallback', () => {
|
|
243
|
+
beforeAll(() => {
|
|
244
|
+
// CustomOption scrolls the selected option into view; jsdom has no layout engine.
|
|
245
|
+
Object.defineProperty(Element.prototype, 'scrollIntoView', {
|
|
246
|
+
value: vi.fn(),
|
|
247
|
+
writable: true,
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
beforeEach(() => {
|
|
252
|
+
mockMatchMedia(false);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('renders the radiogroup on mobile when item count is at or below the threshold', () => {
|
|
256
|
+
wrap(
|
|
257
|
+
<ToggleGroup defaultValue='option-1'>
|
|
258
|
+
<ToggleGroupItem
|
|
259
|
+
value='option-1'
|
|
260
|
+
label='Option 1'
|
|
261
|
+
/>
|
|
262
|
+
<ToggleGroupItem
|
|
263
|
+
value='option-2'
|
|
264
|
+
label='Option 2'
|
|
265
|
+
/>
|
|
266
|
+
</ToggleGroup>
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
expect(screen.getByRole('radiogroup')).toBeInTheDocument();
|
|
270
|
+
expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('renders a Select instead of the radiogroup once item count exceeds the threshold', () => {
|
|
274
|
+
wrap(
|
|
275
|
+
<ToggleGroup defaultValue='option-1'>
|
|
276
|
+
<ToggleGroupItem
|
|
277
|
+
value='option-1'
|
|
278
|
+
label='Option 1'
|
|
279
|
+
/>
|
|
280
|
+
<ToggleGroupItem
|
|
281
|
+
value='option-2'
|
|
282
|
+
label='Option 2'
|
|
283
|
+
/>
|
|
284
|
+
<ToggleGroupItem
|
|
285
|
+
value='option-3'
|
|
286
|
+
label='Option 3'
|
|
287
|
+
/>
|
|
288
|
+
</ToggleGroup>
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
expect(screen.queryByRole('radiogroup')).not.toBeInTheDocument();
|
|
292
|
+
expect(screen.getByRole('combobox')).toBeInTheDocument();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test('counts items nested in fragments toward the mobile select threshold', async () => {
|
|
296
|
+
const user = userEvent.setup();
|
|
297
|
+
|
|
298
|
+
wrap(
|
|
299
|
+
<ToggleGroup defaultValue='option-1'>
|
|
300
|
+
<>
|
|
301
|
+
<ToggleGroupItem
|
|
302
|
+
value='option-1'
|
|
303
|
+
label='Option 1'
|
|
304
|
+
/>
|
|
305
|
+
<ToggleGroupItem
|
|
306
|
+
value='option-2'
|
|
307
|
+
label='Option 2'
|
|
308
|
+
/>
|
|
309
|
+
</>
|
|
310
|
+
<ToggleGroupItem
|
|
311
|
+
value='option-3'
|
|
312
|
+
label='Option 3'
|
|
313
|
+
/>
|
|
314
|
+
</ToggleGroup>
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
expect(screen.getByRole('combobox')).toBeInTheDocument();
|
|
318
|
+
|
|
319
|
+
await user.click(screen.getByRole('combobox'));
|
|
320
|
+
|
|
321
|
+
expect(
|
|
322
|
+
screen.getByRole('option', { name: 'Option 1' })
|
|
323
|
+
).toBeInTheDocument();
|
|
324
|
+
expect(
|
|
325
|
+
screen.getByRole('option', { name: 'Option 2' })
|
|
326
|
+
).toBeInTheDocument();
|
|
327
|
+
expect(
|
|
328
|
+
screen.getByRole('option', { name: 'Option 3' })
|
|
329
|
+
).toBeInTheDocument();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
test('updates the selected value when an option is chosen from the mobile select', async () => {
|
|
333
|
+
const user = userEvent.setup();
|
|
334
|
+
const onValueChange = vi.fn();
|
|
335
|
+
|
|
336
|
+
wrap(
|
|
337
|
+
<ToggleGroup
|
|
338
|
+
defaultValue='option-1'
|
|
339
|
+
onValueChange={onValueChange}
|
|
340
|
+
>
|
|
341
|
+
<ToggleGroupItem
|
|
342
|
+
value='option-1'
|
|
343
|
+
label='Option 1'
|
|
344
|
+
/>
|
|
345
|
+
<ToggleGroupItem
|
|
346
|
+
value='option-2'
|
|
347
|
+
label='Option 2'
|
|
348
|
+
/>
|
|
349
|
+
<ToggleGroupItem
|
|
350
|
+
value='option-3'
|
|
351
|
+
label='Option 3'
|
|
352
|
+
/>
|
|
353
|
+
</ToggleGroup>
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
await user.click(screen.getByRole('combobox'));
|
|
357
|
+
await user.click(screen.getByRole('option', { name: 'Option 2' }));
|
|
358
|
+
|
|
359
|
+
expect(onValueChange).toHaveBeenCalledWith('option-2');
|
|
360
|
+
expect(screen.getByRole('combobox')).toHaveTextContent('Option 2');
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// The Select fallback only forwards `label`/`value` for each item, so a disabled
|
|
364
|
+
// ToggleGroupItem's disabled state is not carried over to the mobile Select option.
|
|
365
|
+
test('does not prevent selection of a disabled item in the mobile select', async () => {
|
|
366
|
+
const user = userEvent.setup();
|
|
367
|
+
const onValueChange = vi.fn();
|
|
368
|
+
|
|
369
|
+
wrap(
|
|
370
|
+
<ToggleGroup
|
|
371
|
+
defaultValue='option-1'
|
|
372
|
+
onValueChange={onValueChange}
|
|
373
|
+
>
|
|
374
|
+
<ToggleGroupItem
|
|
375
|
+
value='option-1'
|
|
376
|
+
label='Option 1'
|
|
377
|
+
/>
|
|
378
|
+
<ToggleGroupItem
|
|
379
|
+
value='option-2'
|
|
380
|
+
label='Option 2'
|
|
381
|
+
disabled
|
|
382
|
+
/>
|
|
383
|
+
<ToggleGroupItem
|
|
384
|
+
value='option-3'
|
|
385
|
+
label='Option 3'
|
|
386
|
+
/>
|
|
387
|
+
</ToggleGroup>
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
await user.click(screen.getByRole('combobox'));
|
|
391
|
+
await user.click(screen.getByRole('option', { name: 'Option 2' }));
|
|
392
|
+
|
|
393
|
+
expect(onValueChange).toHaveBeenCalledWith('option-2');
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test('renders a native <select> with matching options when selectProps requests the native variant', () => {
|
|
397
|
+
wrap(
|
|
398
|
+
<ToggleGroup
|
|
399
|
+
defaultValue='option-1'
|
|
400
|
+
selectProps={{
|
|
401
|
+
native: true,
|
|
402
|
+
nativeHtmlAttributes: { onChange: vi.fn() },
|
|
403
|
+
}}
|
|
404
|
+
>
|
|
405
|
+
<ToggleGroupItem
|
|
406
|
+
value='option-1'
|
|
407
|
+
label='Option 1'
|
|
408
|
+
/>
|
|
409
|
+
<ToggleGroupItem
|
|
410
|
+
value='option-2'
|
|
411
|
+
label='Option 2'
|
|
412
|
+
/>
|
|
413
|
+
<ToggleGroupItem
|
|
414
|
+
value='option-3'
|
|
415
|
+
label='Option 3'
|
|
416
|
+
/>
|
|
417
|
+
</ToggleGroup>
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
const select = screen.getByTestId(
|
|
421
|
+
'ucl-uikit-select--native'
|
|
422
|
+
) as HTMLSelectElement;
|
|
423
|
+
|
|
424
|
+
expect(select.tagName).toBe('SELECT');
|
|
425
|
+
expect(select.value).toBe('option-1');
|
|
426
|
+
expect(
|
|
427
|
+
Array.from(select.querySelectorAll('option')).map(
|
|
428
|
+
(option) => option.textContent
|
|
429
|
+
)
|
|
430
|
+
).toEqual(['Option 1', 'Option 2', 'Option 3']);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
test('relies on the caller-supplied nativeHtmlAttributes.onChange rather than onValueChange for native selects', () => {
|
|
434
|
+
const onValueChange = vi.fn();
|
|
435
|
+
const nativeOnChange = vi.fn();
|
|
436
|
+
|
|
437
|
+
wrap(
|
|
438
|
+
<ToggleGroup
|
|
439
|
+
defaultValue='option-1'
|
|
440
|
+
onValueChange={onValueChange}
|
|
441
|
+
selectProps={{
|
|
442
|
+
native: true,
|
|
443
|
+
nativeHtmlAttributes: { onChange: nativeOnChange },
|
|
444
|
+
}}
|
|
445
|
+
>
|
|
446
|
+
<ToggleGroupItem
|
|
447
|
+
value='option-1'
|
|
448
|
+
label='Option 1'
|
|
449
|
+
/>
|
|
450
|
+
<ToggleGroupItem
|
|
451
|
+
value='option-2'
|
|
452
|
+
label='Option 2'
|
|
453
|
+
/>
|
|
454
|
+
<ToggleGroupItem
|
|
455
|
+
value='option-3'
|
|
456
|
+
label='Option 3'
|
|
457
|
+
/>
|
|
458
|
+
</ToggleGroup>
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
fireEvent.change(screen.getByTestId('ucl-uikit-select--native'), {
|
|
462
|
+
target: { value: 'option-2' },
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
expect(nativeOnChange).toHaveBeenCalled();
|
|
466
|
+
expect(onValueChange).not.toHaveBeenCalled();
|
|
467
|
+
});
|
|
468
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import ToggleGroup from '../ToggleGroup';
|
|
4
|
+
import Item from './Item';
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Components/ToggleGroup/Item',
|
|
8
|
+
component: Item,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
decorators: [
|
|
14
|
+
(Story) => (
|
|
15
|
+
<ToggleGroup defaultValue='option-1'>
|
|
16
|
+
<Story />
|
|
17
|
+
</ToggleGroup>
|
|
18
|
+
),
|
|
19
|
+
],
|
|
20
|
+
} satisfies Meta<typeof Item>;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
type Story = StoryObj<typeof meta>;
|
|
25
|
+
|
|
26
|
+
export const Selected: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
value: 'option-1',
|
|
29
|
+
label: 'Selected',
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const Unselected: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
value: 'option-2',
|
|
36
|
+
label: 'Unselected',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const WithIcon: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
value: 'option-2',
|
|
43
|
+
label: 'With icon',
|
|
44
|
+
icon: 'Calendar',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const WithSublabel: Story = {
|
|
49
|
+
args: {
|
|
50
|
+
value: 'option-2',
|
|
51
|
+
label: 'With sublabel',
|
|
52
|
+
sublabel: 'Sublabel text',
|
|
53
|
+
icon: 'User',
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const Disabled: Story = {
|
|
58
|
+
args: {
|
|
59
|
+
value: 'option-2',
|
|
60
|
+
label: 'Disabled',
|
|
61
|
+
disabled: true,
|
|
62
|
+
},
|
|
63
|
+
};
|