@dhasdk/simple-ui 1.0.7 → 1.0.8
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/.babelrc +12 -0
- package/.storybook/main.ts +35 -0
- package/.storybook/preview.ts +4 -0
- package/BAKpostcss.config.jsBAK +15 -0
- package/BAKtailwind.config.mjsBAK +99 -0
- package/README.md +464 -16
- package/coverage/storybook/coverage-storybook.json +32411 -0
- package/coverage/storybook/lcov-report/Accordion.tsx.html +805 -0
- package/coverage/storybook/lcov-report/Badge.tsx.html +346 -0
- package/coverage/storybook/lcov-report/Breadcrumbs.tsx.html +742 -0
- package/coverage/storybook/lcov-report/Button.tsx.html +448 -0
- package/coverage/storybook/lcov-report/ButtonGroup.tsx.html +403 -0
- package/coverage/storybook/lcov-report/Card.tsx.html +292 -0
- package/coverage/storybook/lcov-report/CharacterCounter.tsx.html +253 -0
- package/coverage/storybook/lcov-report/CheckBox.tsx.html +1555 -0
- package/coverage/storybook/lcov-report/DatePicker.tsx.html +826 -0
- package/coverage/storybook/lcov-report/Input.tsx.html +1012 -0
- package/coverage/storybook/lcov-report/List.tsx.html +364 -0
- package/coverage/storybook/lcov-report/Modal.tsx.html +745 -0
- package/coverage/storybook/lcov-report/Pill.tsx.html +358 -0
- package/coverage/storybook/lcov-report/Search.tsx.html +997 -0
- package/coverage/storybook/lcov-report/SearchContent.tsx.html +235 -0
- package/coverage/storybook/lcov-report/SectionHeader.tsx.html +358 -0
- package/coverage/storybook/lcov-report/Select.tsx.html +1012 -0
- package/coverage/storybook/lcov-report/Shield.tsx.html +802 -0
- package/coverage/storybook/lcov-report/SideBarNav.tsx.html +490 -0
- package/coverage/storybook/lcov-report/Skeleton.tsx.html +394 -0
- package/coverage/storybook/lcov-report/Slider.tsx.html +385 -0
- package/coverage/storybook/lcov-report/Status.tsx.html +322 -0
- package/coverage/storybook/lcov-report/Tabs.tsx.html +610 -0
- package/coverage/storybook/lcov-report/Toggle.tsx.html +373 -0
- package/coverage/storybook/lcov-report/Tooltip.tsx.html +496 -0
- package/coverage/storybook/lcov-report/base.css +224 -0
- package/coverage/storybook/lcov-report/block-navigation.js +87 -0
- package/coverage/storybook/lcov-report/favicon.png +0 -0
- package/coverage/storybook/lcov-report/index.html +476 -0
- package/coverage/storybook/lcov-report/prettify.css +1 -0
- package/coverage/storybook/lcov-report/prettify.js +2 -0
- package/coverage/storybook/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/storybook/lcov-report/sorter.js +196 -0
- package/coverage/storybook/lcov.info +2312 -0
- package/dist/README.md +1815 -0
- package/eslint.config.mjs +13 -0
- package/package.json +6 -7
- package/project.json +11 -0
- package/src/assets/img/Frame.svg +5 -0
- package/src/assets/img/backArrowRight.svg +10 -0
- package/src/assets/img/bc-separator.png +0 -0
- package/src/assets/img/calendar.png +0 -0
- package/src/assets/img/calendar.svg +4 -0
- package/src/assets/img/check.svg +5 -0
- package/src/assets/img/check_box.svg +10 -0
- package/src/assets/img/check_box_empty.svg +10 -0
- package/src/assets/img/check_box_fill.svg +10 -0
- package/src/assets/img/check_box_fill_empty.svg +10 -0
- package/src/assets/img/chevron-down-white.svg +2 -0
- package/src/assets/img/chevron-down.svg +2 -0
- package/src/assets/img/chevron-left.svg +1 -0
- package/src/assets/img/chevron-right-light.svg +4 -0
- package/src/assets/img/chevron-right.svg +3 -0
- package/src/assets/img/chevron-up-white.svg +1 -0
- package/src/assets/img/chevron-up.svg +1 -0
- package/src/assets/img/clock.svg +6 -0
- package/src/assets/img/close.svg +1 -0
- package/src/assets/img/close2.svg +6 -0
- package/src/assets/img/closeModal.svg +10 -0
- package/src/assets/img/close_icon_dark.svg +10 -0
- package/src/assets/img/close_small.svg +3 -0
- package/src/assets/img/emergency_home.svg +10 -0
- package/src/assets/img/first-aid-kit.svg +7 -0
- package/src/assets/img/heartbeat.svg +4 -0
- package/src/assets/img/home-gray.svg +3 -0
- package/src/assets/img/home.svg +3 -0
- package/src/assets/img/hospital.jpg +0 -0
- package/src/assets/img/indeterminate_check_box.svg +10 -0
- package/src/assets/img/indeterminate_check_box_fill.svg +10 -0
- package/src/assets/img/info_24_ 1d4ed8.svg +3 -0
- package/src/assets/img/info_24_ 2c6441.svg +3 -0
- package/src/assets/img/marker_check_by_default.svg +10 -0
- package/src/assets/img/marker_check_by_default_fill.svg +10 -0
- package/src/assets/img/minus-accordion.svg +5 -0
- package/src/assets/img/minus.svg +3 -0
- package/src/assets/img/open.svg +1 -0
- package/src/assets/img/pill-white.svg +7 -0
- package/src/assets/img/pill.svg +5 -0
- package/src/assets/img/plus-accordion.svg +5 -0
- package/src/assets/img/plus.svg +4 -0
- package/src/assets/img/prescription.svg +6 -0
- package/src/assets/img/search.svg +10 -0
- package/src/assets/img/search_icon_light.svg +10 -0
- package/src/assets/img/separator.svg +3 -0
- package/src/assets/img/stethoscope-white.svg +8 -0
- package/src/assets/img/stethoscope.svg +8 -0
- package/src/assets/img/thumb_up.svg +10 -0
- package/src/assets/img/vector.svg +3 -0
- package/src/assets/img/warning-badge-disabled.svg +11 -0
- package/src/assets/img/warning-badge-green.svg +11 -0
- package/src/assets/img/warning-badge-red.svg +11 -0
- package/src/assets/img/warning-badge-yellow.svg +11 -0
- package/src/assets/img/warning.svg +10 -0
- package/src/global.d.ts +13 -0
- package/{index.d.ts → src/index.ts} +13 -5
- package/src/lib/Accordian--Accordian.stories.tsx +312 -0
- package/src/lib/Accordion.spec.tsx +384 -0
- package/src/lib/Accordion.tsx +240 -0
- package/src/lib/AppointmentPicker.spec.tsx +138 -0
- package/src/lib/AppointmentPicker.tsx +97 -0
- package/src/lib/Badge--Badge.stories.tsx +60 -0
- package/src/lib/Badge.spec.tsx +70 -0
- package/src/lib/Badge.tsx +87 -0
- package/src/lib/Breadcrumbs-Breadcrumbs.stories.tsx +114 -0
- package/src/lib/Breadcrumbs.spec.tsx +218 -0
- package/src/lib/Breadcrumbs.tsx +219 -0
- package/src/lib/Button--Button.stories.tsx +220 -0
- package/src/lib/Button.spec.tsx +241 -0
- package/src/lib/Button.tsx +121 -0
- package/src/lib/ButtonGroup--ButtonGroup.stories.tsx +129 -0
- package/src/lib/ButtonGroup.spec.tsx +89 -0
- package/src/lib/ButtonGroup.tsx +107 -0
- package/src/lib/Card--Card.stories.tsx +113 -0
- package/src/lib/Card.spec.tsx +112 -0
- package/src/lib/Card.tsx +69 -0
- package/src/lib/CharacterCounter--CharacterCounter.stories.tsx +169 -0
- package/src/lib/CharacterCounter.spec.tsx +123 -0
- package/src/lib/CharacterCounter.tsx +56 -0
- package/src/lib/CheckBox--CheckBox.stories.tsx +107 -0
- package/src/lib/CheckBox.spec.tsx +412 -0
- package/src/lib/CheckBox.tsx +491 -0
- package/src/lib/DatePicker--DatePicker.stories.tsx +228 -0
- package/src/lib/DatePicker.spec.tsx +424 -0
- package/src/lib/DatePicker.tsx +247 -0
- package/src/lib/Input--Input.stories.tsx +449 -0
- package/src/lib/Input.spec.tsx +281 -0
- package/src/lib/Input.tsx +309 -0
- package/src/lib/List--List.stories.tsx +157 -0
- package/src/lib/List.spec.tsx +211 -0
- package/src/lib/List.tsx +93 -0
- package/src/lib/Modal--Modal.stories.tsx +454 -0
- package/src/lib/Modal.spec.tsx +202 -0
- package/src/lib/Modal.tsx +220 -0
- package/src/lib/Pill--Pill.stories.tsx +98 -0
- package/src/lib/Pill.spec.tsx +103 -0
- package/src/lib/Pill.tsx +91 -0
- package/src/lib/ProgressBar.spec.tsx +106 -0
- package/src/lib/ProgressBar.tsx +112 -0
- package/src/lib/RadioGroup.spec.tsx +84 -0
- package/src/lib/RadioGroup.tsx +74 -0
- package/src/lib/RadioIcon.tsx +13 -0
- package/src/lib/Search--Search.stories.tsx +67 -0
- package/src/lib/Search.spec.tsx +182 -0
- package/src/lib/Search.tsx +304 -0
- package/src/lib/SearchContent.tsx +51 -0
- package/src/lib/SectionHeader--SectionHeader.stories.tsx +98 -0
- package/src/lib/SectionHeader.spec.tsx +60 -0
- package/src/lib/SectionHeader.tsx +91 -0
- package/src/lib/Select--Select.stories.tsx +387 -0
- package/src/lib/Select.spec.tsx +493 -0
- package/src/lib/Select.tsx +311 -0
- package/src/lib/Shield--Shield.stories.tsx +196 -0
- package/src/lib/Shield.spec.tsx +275 -0
- package/src/lib/Shield.tsx +239 -0
- package/src/lib/SideBarNav--SideBarNav.stories.tsx +136 -0
- package/src/lib/SideBarNav.spec.tsx +178 -0
- package/src/lib/SideBarNav.tsx +135 -0
- package/src/lib/Skeleton--Skeleton.stories.tsx +77 -0
- package/src/lib/Skeleton.module.css +16 -0
- package/src/lib/Skeleton.spec.tsx +83 -0
- package/src/lib/Skeleton.tsx +103 -0
- package/src/lib/SkipLink.spec.tsx +76 -0
- package/src/lib/SkipLink.tsx +48 -0
- package/src/lib/Slider--Slider.stories.tsx +108 -0
- package/src/lib/Slider.module.css +109 -0
- package/src/lib/Slider.spec.tsx +67 -0
- package/src/lib/Slider.tsx +101 -0
- package/src/lib/Status--Status.stories.tsx +93 -0
- package/src/lib/Status.spec.tsx +118 -0
- package/src/lib/Status.tsx +79 -0
- package/src/lib/Tabs--Tabs.stories.tsx +294 -0
- package/src/lib/Tabs.spec.tsx +249 -0
- package/src/lib/Tabs.tsx +188 -0
- package/src/lib/Tester.spec.tsx +17 -0
- package/src/lib/Toggle--Toggle.stories.tsx +162 -0
- package/src/lib/Toggle.spec.tsx +122 -0
- package/src/lib/Toggle.tsx +96 -0
- package/src/lib/Tooltip--Tooltip.stories.tsx +315 -0
- package/src/lib/Tooltip.spec.tsx +307 -0
- package/src/lib/Tooltip.tsx +137 -0
- package/src/lib/bak-simple-ui.stories.tsx-bak +24 -0
- package/src/styles.css +190 -0
- package/tsconfig.json +25 -0
- package/tsconfig.lib.json +42 -0
- package/tsconfig.spec.json +29 -0
- package/tsconfig.storybook.json +36 -0
- package/vite.config.mts +87 -0
- package/vitest.setup.ts +12 -0
- package/index.css +0 -1
- package/index.js +0 -35
- package/index.mjs +0 -4981
- package/lib/Accordion.d.ts +0 -36
- package/lib/AppointmentPicker.d.ts +0 -21
- package/lib/Badge.d.ts +0 -11
- package/lib/Breadcrumbs.d.ts +0 -13
- package/lib/Button.d.ts +0 -15
- package/lib/ButtonGroup.d.ts +0 -8
- package/lib/Card.d.ts +0 -11
- package/lib/CharacterCounter.d.ts +0 -11
- package/lib/CheckBox.d.ts +0 -30
- package/lib/DatePicker.d.ts +0 -7
- package/lib/Input.d.ts +0 -16
- package/lib/List.d.ts +0 -22
- package/lib/Modal.d.ts +0 -18
- package/lib/Pill.d.ts +0 -13
- package/lib/ProgressBar.d.ts +0 -19
- package/lib/RadioGroup.d.ts +0 -15
- package/lib/Search.d.ts +0 -26
- package/lib/SearchContent.d.ts +0 -6
- package/lib/SectionHeader.d.ts +0 -18
- package/lib/Select.d.ts +0 -19
- package/lib/Shield.d.ts +0 -12
- package/lib/SideBarNav.d.ts +0 -21
- package/lib/Skeleton.d.ts +0 -15
- package/lib/SkipLink.d.ts +0 -22
- package/lib/Slider.d.ts +0 -14
- package/lib/Status.d.ts +0 -10
- package/lib/Tabs.d.ts +0 -23
- package/lib/Toggle.d.ts +0 -11
- package/lib/Tooltip.d.ts +0 -14
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { Meta, StoryContext } from '@storybook/react';
|
|
2
|
+
import { expect, userEvent, within, waitFor, fireEvent } from 'storybook/test';
|
|
3
|
+
import { Select } from './Select';
|
|
4
|
+
import { Filled } from './Button--Button.stories';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Select> = {
|
|
8
|
+
title: 'Components/Select', // Tells Storybook to place the Select component inside Components section
|
|
9
|
+
component: Select,
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: 'centered',
|
|
12
|
+
},
|
|
13
|
+
argTypes: {
|
|
14
|
+
label: { control: 'text'},
|
|
15
|
+
optionsLabel: { control: 'text'},
|
|
16
|
+
variant: { control: 'text'},
|
|
17
|
+
},
|
|
18
|
+
args: { // default options argument so as to not define repeatedly below
|
|
19
|
+
variant: 'default',
|
|
20
|
+
options: [
|
|
21
|
+
{name: 'blue'},
|
|
22
|
+
{name: 'white'},
|
|
23
|
+
{name: 'red'},
|
|
24
|
+
{name: 'green'},
|
|
25
|
+
{name: 'yellow'},
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
<Dropdown
|
|
32
|
+
label='Border Color'
|
|
33
|
+
optionsLabel='Choose a Color'
|
|
34
|
+
variant='MedCard'
|
|
35
|
+
options={[
|
|
36
|
+
{name: 'gray', value: 'border-gray-500'},
|
|
37
|
+
{name: 'Blue', value: 'border-blue-500'}
|
|
38
|
+
]}
|
|
39
|
+
setSelectedOption={setSelectedBorder} />
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
export default meta;
|
|
43
|
+
|
|
44
|
+
// type Story = StoryObj<typeof Select>;
|
|
45
|
+
|
|
46
|
+
//export const ToggleHandler: StoryFn = () => {
|
|
47
|
+
|
|
48
|
+
// const SelectDefault:StoryFn = (args: SelectProps) => {
|
|
49
|
+
export const SelectDefault = {
|
|
50
|
+
args: {
|
|
51
|
+
setSelectedOption: () => console.log('Clicked! Value: '),
|
|
52
|
+
},
|
|
53
|
+
play:async ({ canvasElement }: StoryContext) => {
|
|
54
|
+
|
|
55
|
+
// Load canvas area to interact with
|
|
56
|
+
const canvas = within(canvasElement);
|
|
57
|
+
|
|
58
|
+
// search for an item that begins with 'Select options' - this is the drop-down box
|
|
59
|
+
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
60
|
+
const selectComponent = await waitFor(() => canvas.getByLabelText(/^Select options.*$/i), { timeout: 500 });
|
|
61
|
+
|
|
62
|
+
// Click on Select to open it
|
|
63
|
+
selectComponent.click();
|
|
64
|
+
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
66
|
+
// We should be able to find an option with the name of 'red'
|
|
67
|
+
const option1 = await waitFor(() => canvas.getByLabelText('option red'), { timeout: 750 });
|
|
68
|
+
|
|
69
|
+
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
70
|
+
// test that option1 ('red') was selected and is visible
|
|
71
|
+
expect(option1).toBeVisible();
|
|
72
|
+
|
|
73
|
+
// click 'red' option
|
|
74
|
+
option1.click();
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const SelectOutline = {
|
|
80
|
+
args: {
|
|
81
|
+
setSelectedOption: () => console.log('Clicked! Value: '),
|
|
82
|
+
variant: 'outline',
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const SelectFill = {
|
|
87
|
+
args: {
|
|
88
|
+
setSelectedOption: () => console.log('Clicked! Value: '),
|
|
89
|
+
variant: 'fill',
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const testOptions = [
|
|
94
|
+
{ name: 'Option 1', value: '1' },
|
|
95
|
+
{ name: 'Option 2', value: '2' },
|
|
96
|
+
{ name: 'Option 3', value: '3' },
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
export const CloseOnEscapeDocument = {
|
|
101
|
+
args: {
|
|
102
|
+
label: 'Test Select',
|
|
103
|
+
options: testOptions,
|
|
104
|
+
setSelectedOption: (val: string) => console.log('Selected: ', val),
|
|
105
|
+
},
|
|
106
|
+
play: async ({ canvasElement }: StoryContext) => {
|
|
107
|
+
const canvas = within(canvasElement);
|
|
108
|
+
// Find the select button by its accessible name (which includes the current selected option).
|
|
109
|
+
const selectButton = canvas.getByRole('button', { name: /Select options -/ });
|
|
110
|
+
// Click to open the dropdown.
|
|
111
|
+
fireEvent.click(selectButton);
|
|
112
|
+
// Wait until the dropdown (the listbox) appears.
|
|
113
|
+
await waitFor(() => expect(canvas.getByRole('listbox')).toBeInTheDocument());
|
|
114
|
+
// Dispatch a keydown event with Escape on the document.
|
|
115
|
+
fireEvent.keyDown(document, { key: 'Escape', code: 'Escape' });
|
|
116
|
+
// Wait until the dropdown is closed.
|
|
117
|
+
await waitFor(() => expect(canvas.queryByRole('listbox')).toBeNull());
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const CloseOnFocusOutside = {
|
|
122
|
+
args: {
|
|
123
|
+
label: 'Test Select',
|
|
124
|
+
options: testOptions,
|
|
125
|
+
setSelectedOption: (val: string) => console.log('Selected: ', val),
|
|
126
|
+
},
|
|
127
|
+
play: async ({ canvasElement }: StoryContext) => {
|
|
128
|
+
const canvas = within(canvasElement);
|
|
129
|
+
// Create an external button (outside the Select component) and add it to the document.
|
|
130
|
+
const externalButton = document.createElement('button');
|
|
131
|
+
externalButton.textContent = 'External';
|
|
132
|
+
document.body.appendChild(externalButton);
|
|
133
|
+
|
|
134
|
+
// Open the dropdown.
|
|
135
|
+
const selectButton = canvas.getByRole('button', { name: /Select options -/ });
|
|
136
|
+
fireEvent.click(selectButton);
|
|
137
|
+
await waitFor(() => expect(canvas.getByRole('listbox')).toBeInTheDocument());
|
|
138
|
+
|
|
139
|
+
// Focus the external button to simulate focus leaving the Select.
|
|
140
|
+
externalButton.focus();
|
|
141
|
+
// Fire a focusin event on that element.
|
|
142
|
+
fireEvent.focusIn(externalButton);
|
|
143
|
+
// Wait for the dropdown to be closed.
|
|
144
|
+
await waitFor(() => expect(canvas.queryByRole('listbox')).toBeNull());
|
|
145
|
+
|
|
146
|
+
// Clean up the external element.
|
|
147
|
+
document.body.removeChild(externalButton);
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export const KeyboardNavigationInDropdown = {
|
|
152
|
+
args: {
|
|
153
|
+
label: 'Test Select',
|
|
154
|
+
options: testOptions,
|
|
155
|
+
setSelectedOption: (val: string) => console.log('Selected: ', val),
|
|
156
|
+
},
|
|
157
|
+
play: async ({ canvasElement }: StoryContext) => {
|
|
158
|
+
const canvas = within(canvasElement);
|
|
159
|
+
const selectButton = canvas.getByRole('button', { name: /Select options -/ });
|
|
160
|
+
fireEvent.click(selectButton);
|
|
161
|
+
|
|
162
|
+
// Wait for the dropdown (listbox) to appear.
|
|
163
|
+
const listbox = await waitFor(() => canvas.getByRole('listbox'));
|
|
164
|
+
|
|
165
|
+
// When opened, the toggle sets focusedIndex to 0 so Option 1 should be focused.
|
|
166
|
+
await waitFor(() => {
|
|
167
|
+
expect(document.activeElement?.getAttribute('aria-label')).toMatch(/option Option 1/);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Press ArrowDown to move focus to Option 2.
|
|
171
|
+
fireEvent.keyDown(listbox, { key: 'ArrowDown', code: 'ArrowDown' });
|
|
172
|
+
await waitFor(() => {
|
|
173
|
+
expect(document.activeElement?.getAttribute('aria-label')).toMatch(/option Option 2/);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Press ArrowUp to move focus back to Option 1.
|
|
177
|
+
fireEvent.keyDown(listbox, { key: 'ArrowUp', code: 'ArrowUp' });
|
|
178
|
+
await waitFor(() => {
|
|
179
|
+
expect(document.activeElement?.getAttribute('aria-label')).toMatch(/option Option 1/);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Press End to move focus to the last option (Option 3).
|
|
183
|
+
fireEvent.keyDown(listbox, { key: 'End', code: 'End' });
|
|
184
|
+
await waitFor(() => {
|
|
185
|
+
expect(document.activeElement?.getAttribute('aria-label')).toMatch(/option Option 3/);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Press Home to move focus back to the first option (Option 1).
|
|
189
|
+
fireEvent.keyDown(listbox, { key: 'Home', code: 'Home' });
|
|
190
|
+
await waitFor(() => {
|
|
191
|
+
expect(document.activeElement?.getAttribute('aria-label')).toMatch(/option Option 1/);
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export const OptionKeydownActions = {
|
|
197
|
+
args: {
|
|
198
|
+
label: 'Test Select',
|
|
199
|
+
options: testOptions,
|
|
200
|
+
setSelectedOption: (val: string) => console.log('Selected: ', val),
|
|
201
|
+
},
|
|
202
|
+
play: async ({ canvasElement }: StoryContext) => {
|
|
203
|
+
const canvas = within(canvasElement);
|
|
204
|
+
const selectButton = canvas.getByRole('button', { name: /Select options -/ });
|
|
205
|
+
|
|
206
|
+
// Open the dropdown.
|
|
207
|
+
fireEvent.click(selectButton);
|
|
208
|
+
await waitFor(() => expect(canvas.getByRole('listbox')).toBeInTheDocument());
|
|
209
|
+
|
|
210
|
+
// Find the option button for "Option 2" (its aria-label is "option Option 2").
|
|
211
|
+
const option2 = canvas.getByRole('option', { name: /option Option 2/ });
|
|
212
|
+
|
|
213
|
+
// Simulate a keydown event with "Enter" on Option 2.
|
|
214
|
+
fireEvent.keyDown(option2, { key: 'Enter', code: 'Enter' });
|
|
215
|
+
// After pressing Enter, the dropdown should close and the select button's accessible name
|
|
216
|
+
// should update to include "Option 2".
|
|
217
|
+
await waitFor(() => {
|
|
218
|
+
expect(canvas.queryByRole('listbox')).toBeNull();
|
|
219
|
+
expect(selectButton).toHaveAccessibleName('Select options - Option 2');
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Re-open the dropdown to test the Escape key on an option.
|
|
223
|
+
fireEvent.click(selectButton);
|
|
224
|
+
await waitFor(() => expect(canvas.getByRole('listbox')).toBeInTheDocument());
|
|
225
|
+
// Find the option button for "Option 3".
|
|
226
|
+
const option3 = canvas.getByRole('option', { name: /option Option 3/ });
|
|
227
|
+
// Simulate a keydown event with "Escape" on Option 3.
|
|
228
|
+
fireEvent.keyDown(option3, { key: 'Escape', code: 'Escape' });
|
|
229
|
+
// The dropdown should close and the selection should remain as "Option 2" from the previous selection.
|
|
230
|
+
await waitFor(() => {
|
|
231
|
+
expect(canvas.queryByRole('listbox')).toBeNull();
|
|
232
|
+
expect(selectButton).toHaveAccessibleName('Select options - Option 2');
|
|
233
|
+
});
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export const FallbackVariant = {
|
|
238
|
+
args: {
|
|
239
|
+
label: 'Fallback Variant',
|
|
240
|
+
variant: 'nonexistent', // not defined in variants
|
|
241
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
242
|
+
setSelectedOption: () => {},
|
|
243
|
+
},
|
|
244
|
+
play: async ({ canvasElement }: StoryContext) => {
|
|
245
|
+
const canvas = within(canvasElement);
|
|
246
|
+
const btn = canvas.getByRole('button', { name: /Select options -/ });
|
|
247
|
+
// Assert that a unique class from variants.default is present.
|
|
248
|
+
expect(btn.className).toContain('hover:bg-gray-200');
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// const SelectDefault:StoryFn = (args: SelectProps) => {
|
|
253
|
+
export const SelectCloseTest = {
|
|
254
|
+
args: {
|
|
255
|
+
setSelectedOption: () => console.log('Clicked! Value: '),
|
|
256
|
+
},
|
|
257
|
+
play:async ({ canvasElement }: StoryContext) => {
|
|
258
|
+
|
|
259
|
+
// Load canvas area to interact with
|
|
260
|
+
const canvas = within(canvasElement);
|
|
261
|
+
|
|
262
|
+
// search for an item that begins with 'Select options' - this is the drop-down box
|
|
263
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
264
|
+
const selectComponent = await waitFor(() => canvas.getByLabelText(/^Select options.*$/i), { timeout: 500 });
|
|
265
|
+
|
|
266
|
+
// Click on Select to open it
|
|
267
|
+
selectComponent.click();
|
|
268
|
+
|
|
269
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
270
|
+
// We should be able to find an option with the name of 'red'
|
|
271
|
+
const option1 = await waitFor(() => canvas.getByLabelText('option red'), { timeout: 750 });
|
|
272
|
+
|
|
273
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
274
|
+
// test that option1 ('red') was selected and is visible
|
|
275
|
+
expect(option1).toBeVisible();
|
|
276
|
+
|
|
277
|
+
// select outside of select and click that region to close opened component
|
|
278
|
+
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
279
|
+
await userEvent.click(document.body);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
export const SelectWithLabel = {
|
|
285
|
+
args: {
|
|
286
|
+
setSelectedOption: () => console.log('Clicked! Value: '),
|
|
287
|
+
label: 'Select a Color',
|
|
288
|
+
options: [
|
|
289
|
+
{name: 'Blue', value: 'blue'},
|
|
290
|
+
{name: 'White', value: 'white'},
|
|
291
|
+
{name: 'Red', value: 'red'},
|
|
292
|
+
{name: 'Green', value: 'green'},
|
|
293
|
+
{name: 'Yellow', value: 'yellow'},
|
|
294
|
+
],
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export const SelectItemValues = {
|
|
299
|
+
args: {
|
|
300
|
+
setSelectedOption: () => console.log('Clicked! Value: '),
|
|
301
|
+
options: [
|
|
302
|
+
{name: 'Blue', value: 'blue'},
|
|
303
|
+
{name: 'White', value: 'white'},
|
|
304
|
+
{name: 'Red', value: 'red'},
|
|
305
|
+
{name: 'Green', value: 'green'},
|
|
306
|
+
{name: 'Yellow', value: 'yellow'},
|
|
307
|
+
],
|
|
308
|
+
},
|
|
309
|
+
play:async ({ canvasElement }: StoryContext) => {
|
|
310
|
+
|
|
311
|
+
// Load canvas area to interact with
|
|
312
|
+
const canvas = within(canvasElement);
|
|
313
|
+
|
|
314
|
+
// search for an item that begins with 'Select options' - this is the drop-down box
|
|
315
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
316
|
+
const selectComponent = await waitFor(() => canvas.getByLabelText(/^Select options.*$/i), { timeout: 500 });
|
|
317
|
+
|
|
318
|
+
// Click on Select to open it
|
|
319
|
+
selectComponent.click();
|
|
320
|
+
|
|
321
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
322
|
+
// We should be able to find an option with the name of 'red'
|
|
323
|
+
const option1 = await waitFor(() => canvas.getByLabelText('option Red'), { timeout: 750 });
|
|
324
|
+
|
|
325
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
326
|
+
// test that option1 ('red') was selected and is visible
|
|
327
|
+
expect(option1).toBeVisible();
|
|
328
|
+
|
|
329
|
+
// click 'red' option
|
|
330
|
+
option1.click();
|
|
331
|
+
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
// story to simulate the case when the select dropdown is close to the bottom of the container
|
|
336
|
+
// and will open upward
|
|
337
|
+
export const SelectAbove = {
|
|
338
|
+
args: {
|
|
339
|
+
setSelectedOption: () => console.log('Clicked! Value: '),
|
|
340
|
+
},
|
|
341
|
+
play: async ({ canvasElement }: StoryContext) => {
|
|
342
|
+
// Force a limited document height to simulate constrained space.
|
|
343
|
+
Object.defineProperty(document.body, 'offsetHeight', {
|
|
344
|
+
configurable: true,
|
|
345
|
+
value: 350,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
const canvas = within(canvasElement);
|
|
349
|
+
// Get the select button.
|
|
350
|
+
const selectButton = canvas.getByRole('button', { name: /^Select options/ });
|
|
351
|
+
// Override the container’s bounding rect to simulate that the select is near the bottom.
|
|
352
|
+
const container = selectButton.parentElement;
|
|
353
|
+
if (container) {
|
|
354
|
+
container.getBoundingClientRect = () => ({
|
|
355
|
+
top: 250, // Must be > dropdownHeight
|
|
356
|
+
bottom: 310, // This makes the button’s bottom near the bottom of the container
|
|
357
|
+
left: 0,
|
|
358
|
+
right: 600,
|
|
359
|
+
width: 600,
|
|
360
|
+
height: 60,
|
|
361
|
+
x: 0,
|
|
362
|
+
y: 0,
|
|
363
|
+
toJSON: () => ({}),
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Open the dropdown.
|
|
368
|
+
selectButton.click();
|
|
369
|
+
|
|
370
|
+
// Wait for the dropdown to appear.
|
|
371
|
+
const listbox = await waitFor(() => canvas.getByRole('listbox'));
|
|
372
|
+
// Force the dropdown's height to a value that will trigger the condition.
|
|
373
|
+
Object.defineProperty(listbox, 'offsetHeight', {
|
|
374
|
+
configurable: true,
|
|
375
|
+
value: 100,
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Given these values:
|
|
379
|
+
// - containerHeight becomes 350 (from document.body.offsetHeight),
|
|
380
|
+
// - buttonRect.bottom is 310,
|
|
381
|
+
// so spaceBelow = 350 - 310 = 40, which is less than dropdownHeight (100),
|
|
382
|
+
// and buttonRect.top (250) is greater than 100.
|
|
383
|
+
// Therefore, the updateDropdownPosition() in the component file should call setIsAbove(true).
|
|
384
|
+
// We verify this by checking for the styling applied when isAbove is true.
|
|
385
|
+
expect(listbox.className).toContain('rounded-t-lg');
|
|
386
|
+
},
|
|
387
|
+
};
|