@sproutsocial/seeds-react-menu 1.16.16 → 1.18.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/.turbo/turbo-build.log +14 -22
- package/CHANGELOG.md +51 -0
- package/dist/esm/index.js +542 -229
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/v3/index.js +870 -1081
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/v3/index.d.mts +82 -38
- package/dist/v3/index.d.ts +82 -38
- package/dist/v3/index.js +887 -1098
- package/dist/v3/index.js.map +1 -1
- package/dist/v3/menu.css +947 -0
- package/package.json +20 -21
- package/src/ActionMenu/ActionMenu.stories.tsx +1 -1
- package/src/Autocomplete/Autocomplete.stories.tsx +1 -1
- package/src/MenuContent/MenuContent.stories.tsx +1 -1
- package/src/MenuFooter/MenuFooter.stories.tsx +1 -1
- package/src/MenuGroup/MenuGroup.stories.tsx +1 -1
- package/src/MenuHeader/MenuHeader.stories.tsx +1 -1
- package/src/MenuItem/MenuItem.stories.tsx +1 -1
- package/src/MenuToggleButton/MenuToggleButton.stories.tsx +1 -1
- package/src/MultiSelectMenu/MultiSelectMenu.stories.tsx +1 -1
- package/src/NestedMenu/NestedMenu.stories.tsx +1 -1
- package/src/SingleSelectMenu/SingleSelectMenu.stories.tsx +1 -1
- package/src/SubmenuItem/SubmenuItem.stories.tsx +1 -1
- package/src/v3/ActionMenu.stories.tsx +1 -1
- package/src/v3/ActionMenuStyles.tsx +169 -149
- package/src/v3/Common/ComboboxStyles.tsx +396 -511
- package/src/v3/Common/SelectIcons.tsx +17 -8
- package/src/v3/Common/SelectItem.tsx +25 -38
- package/src/v3/Common/SelectStyles.tsx +146 -144
- package/src/v3/Common/cn.ts +38 -0
- package/src/v3/MenuButton.stories.tsx +1 -1
- package/src/v3/MenuButtonStyles.tsx +55 -34
- package/src/v3/ModalStories.stories.tsx +1 -1
- package/src/v3/MultiCombobox.stories.tsx +1 -1
- package/src/v3/MultiCombobox.tsx +7 -0
- package/src/v3/MultiSearchableSelect.stories.tsx +1 -1
- package/src/v3/MultiSearchableSelect.tsx +15 -8
- package/src/v3/MultiSelect.stories.tsx +1 -1
- package/src/v3/MultiSelect.tsx +20 -17
- package/src/v3/SingleCombobox.stories.tsx +1 -1
- package/src/v3/SingleCombobox.tsx +7 -0
- package/src/v3/SingleSearchableSelect.stories.tsx +1 -1
- package/src/v3/SingleSearchableSelect.tsx +7 -0
- package/src/v3/SingleSelect.stories.tsx +1 -1
- package/src/v3/SingleSelect.tsx +22 -14
- package/src/v3/__tests__/ariaLabels.test.tsx +133 -0
- package/src/v3/menu.css +947 -0
- package/tsup.config.ts +0 -1
- package/dist/esm/chunk-ROQATIB7.js +0 -357
- package/dist/esm/chunk-ROQATIB7.js.map +0 -1
- package/dist/esm/v2/index.js +0 -2089
- package/dist/esm/v2/index.js.map +0 -1
- package/dist/v2/index.d.mts +0 -108
- package/dist/v2/index.d.ts +0 -108
- package/dist/v2/index.js +0 -2280
- package/dist/v2/index.js.map +0 -1
- package/src/v2/Autocomplete/Autocomplete.stories.tsx +0 -645
- package/src/v2/Autocomplete/MultiAutocomplete.tsx +0 -487
- package/src/v2/Autocomplete/SingleAutocomplete.tsx +0 -366
- package/src/v2/Autocomplete/index.ts +0 -2
- package/src/v2/Common-V2/ComboboxContent.tsx +0 -457
- package/src/v2/Common-V2/MenuGroup.tsx +0 -60
- package/src/v2/Common-V2/MenuGroupTypes.ts +0 -30
- package/src/v2/Common-V2/MenuHeading.tsx +0 -83
- package/src/v2/Common-V2/MenuItem.tsx +0 -138
- package/src/v2/Common-V2/Popout.tsx +0 -124
- package/src/v2/Common-V2/PopoutTypes.tsx +0 -109
- package/src/v2/Common-V2/SelectToggleButton.tsx +0 -99
- package/src/v2/Common-V2/index.ts +0 -11
- package/src/v2/Common-V2/props.ts +0 -84
- package/src/v2/Common-V2/styles.tsx +0 -41
- package/src/v2/Common-V2/types.ts +0 -16
- package/src/v2/Common-V2/useHighlightedIndex.ts +0 -62
- package/src/v2/Common-V2/utils.ts +0 -238
- package/src/v2/SearchableSelect/AutocompleteContent.tsx +0 -325
- package/src/v2/SearchableSelect/SearchableMultiSelect.tsx +0 -527
- package/src/v2/SearchableSelect/SearchableSelect.tsx +0 -395
- package/src/v2/SearchableSelect/index.ts +0 -12
- package/src/v2/Select/MultiSelect.tsx +0 -417
- package/src/v2/Select/Select.stories.tsx +0 -593
- package/src/v2/Select/SingleSelect.tsx +0 -285
- package/src/v2/Select/index.ts +0 -2
- package/src/v2/index.ts +0 -2
|
@@ -32,16 +32,16 @@ import {
|
|
|
32
32
|
} from "./Common/ComboboxStyles";
|
|
33
33
|
import { ClearIcon, StyledChevron, ChevronIcon } from "./Common/SelectIcons";
|
|
34
34
|
import Icon from "@sproutsocial/seeds-react-icon";
|
|
35
|
-
import
|
|
35
|
+
import { cn } from "./Common/cn";
|
|
36
36
|
|
|
37
|
-
// ───
|
|
37
|
+
// ─── CSS-class components (see menu.css) ────────────────────────────────────
|
|
38
38
|
|
|
39
|
-
const SelectionText =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
const SelectionText = ({
|
|
40
|
+
className,
|
|
41
|
+
...rest
|
|
42
|
+
}: React.ComponentProps<"span">) => (
|
|
43
|
+
<span className={cn("seeds-select-selection-text", className)} {...rest} />
|
|
44
|
+
);
|
|
45
45
|
|
|
46
46
|
// ─── Sentinels ────────────────────────────────────────────────────────────────
|
|
47
47
|
|
|
@@ -79,6 +79,9 @@ interface MultiSearchableSelectBaseProps {
|
|
|
79
79
|
loadingText?: string;
|
|
80
80
|
disabled?: boolean;
|
|
81
81
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
82
|
+
"aria-label"?: string;
|
|
83
|
+
/** Id of a visible label. Preferred over `aria-label`. */
|
|
84
|
+
"aria-labelledby"?: string;
|
|
82
85
|
"aria-describedby"?: string;
|
|
83
86
|
isInvalid?: boolean;
|
|
84
87
|
required?: boolean;
|
|
@@ -151,6 +154,8 @@ export function MultiSearchableSelect<T extends DataWithId>(
|
|
|
151
154
|
fullWidth = true,
|
|
152
155
|
} = props;
|
|
153
156
|
const ariaDescribedBy = props["aria-describedby"];
|
|
157
|
+
const ariaLabel = props["aria-label"];
|
|
158
|
+
const ariaLabelledBy = props["aria-labelledby"];
|
|
154
159
|
const isInvalid = props.isInvalid;
|
|
155
160
|
|
|
156
161
|
const isChildrenMode = "children" in props && props.children != null;
|
|
@@ -609,6 +614,8 @@ export function MultiSearchableSelect<T extends DataWithId>(
|
|
|
609
614
|
<ComboboxStatus>{isLoading ? loadingText : null}</ComboboxStatus>
|
|
610
615
|
<ComboboxEmpty>{isLoading ? null : emptyText}</ComboboxEmpty>
|
|
611
616
|
<SearchableSelectList
|
|
617
|
+
aria-label={ariaLabel}
|
|
618
|
+
aria-labelledby={ariaLabelledBy}
|
|
612
619
|
style={
|
|
613
620
|
isVirtualized
|
|
614
621
|
? {
|
package/src/v3/MultiSelect.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Select } from "@base-ui/react/select";
|
|
3
|
-
import styled from "styled-components";
|
|
4
3
|
import { useSeedsPortalContainer } from "./SeedsPortal";
|
|
5
4
|
import SelectItem from "./Common/SelectItem";
|
|
6
5
|
import type { DataWithId } from "./Common/types";
|
|
@@ -17,25 +16,21 @@ import {
|
|
|
17
16
|
SelectPopup,
|
|
18
17
|
} from "./Common/SelectStyles";
|
|
19
18
|
import { StyledChevron, ChevronIcon } from "./Common/SelectIcons";
|
|
19
|
+
import { cn } from "./Common/cn";
|
|
20
20
|
|
|
21
|
-
// ───
|
|
21
|
+
// ─── CSS-class components (see menu.css) ────────────────────────────────────
|
|
22
22
|
|
|
23
|
-
const SelectionText =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const SelectionText = ({
|
|
24
|
+
className,
|
|
25
|
+
...rest
|
|
26
|
+
}: React.ComponentProps<"span">) => (
|
|
27
|
+
<span className={cn("seeds-select-selection-text", className)} {...rest} />
|
|
28
|
+
);
|
|
29
29
|
|
|
30
30
|
// The styles in here need cleaned up, but in MultiSearchableSelect are correct
|
|
31
|
-
const Placeholder =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
line-height: 16px;
|
|
35
|
-
padding-top: 2px;
|
|
36
|
-
padding-bottom: 2px;
|
|
37
|
-
margin: 2px 8px 0px 0px;
|
|
38
|
-
`;
|
|
31
|
+
const Placeholder = ({ className, ...rest }: React.ComponentProps<"div">) => (
|
|
32
|
+
<div className={cn("seeds-select-placeholder", className)} {...rest} />
|
|
33
|
+
);
|
|
39
34
|
|
|
40
35
|
// ─── Props ────────────────────────────────────────────────────────────────────
|
|
41
36
|
|
|
@@ -43,6 +38,9 @@ interface MultiSelectBaseProps {
|
|
|
43
38
|
id?: string;
|
|
44
39
|
placeholder?: string;
|
|
45
40
|
disabled?: boolean;
|
|
41
|
+
"aria-label"?: string;
|
|
42
|
+
/** Id of a visible label. Preferred over `aria-label`. */
|
|
43
|
+
"aria-labelledby"?: string;
|
|
46
44
|
"aria-describedby"?: string;
|
|
47
45
|
isInvalid?: boolean;
|
|
48
46
|
required?: boolean;
|
|
@@ -93,6 +91,8 @@ export type MultiSelectProps<T extends DataWithId> =
|
|
|
93
91
|
export function MultiSelect<T extends DataWithId>(props: MultiSelectProps<T>) {
|
|
94
92
|
const { id, placeholder = "Select...", fullWidth = true } = props;
|
|
95
93
|
const ariaDescribedBy = props["aria-describedby"];
|
|
94
|
+
const ariaLabel = props["aria-label"];
|
|
95
|
+
const ariaLabelledBy = props["aria-labelledby"];
|
|
96
96
|
const isInvalid = props.isInvalid;
|
|
97
97
|
|
|
98
98
|
const isChildrenMode = "children" in props && props.children != null;
|
|
@@ -232,7 +232,10 @@ export function MultiSelect<T extends DataWithId>(props: MultiSelectProps<T>) {
|
|
|
232
232
|
<SelectPositioner sideOffset={8} alignItemWithTrigger={false}>
|
|
233
233
|
<SelectPopup>
|
|
234
234
|
<Select.ScrollUpArrow />
|
|
235
|
-
<Select.List
|
|
235
|
+
<Select.List
|
|
236
|
+
aria-label={ariaLabel}
|
|
237
|
+
aria-labelledby={ariaLabelledBy}
|
|
238
|
+
>
|
|
236
239
|
{children
|
|
237
240
|
? children
|
|
238
241
|
: groupBy
|
|
@@ -32,6 +32,9 @@ interface SingleComboboxBaseProps {
|
|
|
32
32
|
emptyText?: string;
|
|
33
33
|
disabled?: boolean;
|
|
34
34
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
35
|
+
"aria-label"?: string;
|
|
36
|
+
/** Id of a visible label. Preferred over `aria-label`. */
|
|
37
|
+
"aria-labelledby"?: string;
|
|
35
38
|
"aria-describedby"?: string;
|
|
36
39
|
isInvalid?: boolean;
|
|
37
40
|
required?: boolean;
|
|
@@ -96,6 +99,8 @@ export function SingleCombobox<T extends DataWithId>(
|
|
|
96
99
|
fullWidth = true,
|
|
97
100
|
} = props;
|
|
98
101
|
const ariaDescribedBy = props["aria-describedby"];
|
|
102
|
+
const ariaLabel = props["aria-label"];
|
|
103
|
+
const ariaLabelledBy = props["aria-labelledby"];
|
|
99
104
|
const isInvalid = props.isInvalid;
|
|
100
105
|
|
|
101
106
|
const isChildrenMode = "children" in props && props.children != null;
|
|
@@ -244,6 +249,8 @@ export function SingleCombobox<T extends DataWithId>(
|
|
|
244
249
|
>
|
|
245
250
|
<ComboboxEmpty>{emptyText}</ComboboxEmpty>
|
|
246
251
|
<ComboboxList
|
|
252
|
+
aria-label={ariaLabel}
|
|
253
|
+
aria-labelledby={ariaLabelledBy}
|
|
247
254
|
style={
|
|
248
255
|
isVirtualized
|
|
249
256
|
? {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./storyData";
|
|
12
12
|
|
|
13
13
|
const meta: Meta<typeof SingleSearchableSelect> = {
|
|
14
|
-
title: "
|
|
14
|
+
title: "Components/Menus/v3/Single Searchable Select",
|
|
15
15
|
component: SingleSearchableSelect,
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -41,6 +41,9 @@ interface SingleSearchableSelectBaseProps {
|
|
|
41
41
|
loadingText?: string;
|
|
42
42
|
disabled?: boolean;
|
|
43
43
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
44
|
+
"aria-label"?: string;
|
|
45
|
+
/** Id of a visible label. Preferred over `aria-label`. */
|
|
46
|
+
"aria-labelledby"?: string;
|
|
44
47
|
"aria-describedby"?: string;
|
|
45
48
|
isInvalid?: boolean;
|
|
46
49
|
required?: boolean;
|
|
@@ -112,6 +115,8 @@ export function SingleSearchableSelect<T extends DataWithId>(
|
|
|
112
115
|
fullWidth = true,
|
|
113
116
|
} = props;
|
|
114
117
|
const ariaDescribedBy = props["aria-describedby"];
|
|
118
|
+
const ariaLabel = props["aria-label"];
|
|
119
|
+
const ariaLabelledBy = props["aria-labelledby"];
|
|
115
120
|
const isInvalid = props.isInvalid;
|
|
116
121
|
|
|
117
122
|
const isChildrenMode = "children" in props && props.children != null;
|
|
@@ -278,6 +283,8 @@ export function SingleSearchableSelect<T extends DataWithId>(
|
|
|
278
283
|
<ComboboxStatus>{isLoading ? loadingText : null}</ComboboxStatus>
|
|
279
284
|
<ComboboxEmpty>{isLoading ? null : emptyText}</ComboboxEmpty>
|
|
280
285
|
<SearchableSelectList
|
|
286
|
+
aria-label={ariaLabel}
|
|
287
|
+
aria-labelledby={ariaLabelledBy}
|
|
281
288
|
style={
|
|
282
289
|
isVirtualized
|
|
283
290
|
? {
|
package/src/v3/SingleSelect.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Select } from "@base-ui/react/select";
|
|
3
|
-
import styled from "styled-components";
|
|
4
3
|
import { useSeedsPortalContainer } from "./SeedsPortal";
|
|
5
4
|
import SelectItem from "./Common/SelectItem";
|
|
6
5
|
import type { DataWithId } from "./Common/types";
|
|
@@ -16,21 +15,22 @@ import {
|
|
|
16
15
|
SelectPopup,
|
|
17
16
|
} from "./Common/SelectStyles";
|
|
18
17
|
import { StyledChevron, ChevronIcon } from "./Common/SelectIcons";
|
|
18
|
+
import { cn, type WithStringClassName } from "./Common/cn";
|
|
19
19
|
|
|
20
20
|
// <Listbox(?!\.|B)
|
|
21
|
-
// ───
|
|
21
|
+
// ─── CSS-class components (see menu.css) ────────────────────────────────────
|
|
22
22
|
|
|
23
|
-
const StyledValue =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
const StyledValue = React.forwardRef<
|
|
24
|
+
React.ElementRef<typeof Select.Value>,
|
|
25
|
+
WithStringClassName<React.ComponentProps<typeof Select.Value>>
|
|
26
|
+
>(({ className, ...rest }, ref) => (
|
|
27
|
+
<Select.Value
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cn("seeds-select-value-text", className)}
|
|
30
|
+
{...rest}
|
|
31
|
+
/>
|
|
32
|
+
));
|
|
33
|
+
StyledValue.displayName = "StyledValue";
|
|
34
34
|
|
|
35
35
|
// ─── Props ────────────────────────────────────────────────────────────────────
|
|
36
36
|
|
|
@@ -39,6 +39,9 @@ interface SingleSelectBaseProps {
|
|
|
39
39
|
placeholder?: string;
|
|
40
40
|
includePlaceholderItem?: boolean;
|
|
41
41
|
disabled?: boolean;
|
|
42
|
+
"aria-label"?: string;
|
|
43
|
+
/** Id of a visible label. Preferred over `aria-label`. */
|
|
44
|
+
"aria-labelledby"?: string;
|
|
42
45
|
"aria-describedby"?: string;
|
|
43
46
|
isInvalid?: boolean;
|
|
44
47
|
required?: boolean;
|
|
@@ -85,6 +88,8 @@ export function SingleSelect<T extends DataWithId>(
|
|
|
85
88
|
) {
|
|
86
89
|
const { id, placeholder, includePlaceholderItem, fullWidth = true } = props;
|
|
87
90
|
const ariaDescribedBy = props["aria-describedby"];
|
|
91
|
+
const ariaLabel = props["aria-label"];
|
|
92
|
+
const ariaLabelledBy = props["aria-labelledby"];
|
|
88
93
|
const isInvalid = props.isInvalid;
|
|
89
94
|
|
|
90
95
|
const isChildrenMode = "children" in props && props.children != null;
|
|
@@ -193,7 +198,10 @@ export function SingleSelect<T extends DataWithId>(
|
|
|
193
198
|
<SelectPositioner sideOffset={8} alignItemWithTrigger={false}>
|
|
194
199
|
<SelectPopup>
|
|
195
200
|
<Select.ScrollUpArrow />
|
|
196
|
-
<Select.List
|
|
201
|
+
<Select.List
|
|
202
|
+
aria-label={ariaLabel}
|
|
203
|
+
aria-labelledby={ariaLabelledBy}
|
|
204
|
+
>
|
|
197
205
|
{children ? (
|
|
198
206
|
children
|
|
199
207
|
) : groupBy ? (
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
fireEvent,
|
|
4
|
+
render,
|
|
5
|
+
screen,
|
|
6
|
+
} from "@sproutsocial/seeds-react-testing-library";
|
|
7
|
+
import { SingleSelect } from "../SingleSelect";
|
|
8
|
+
import { MultiSelect } from "../MultiSelect";
|
|
9
|
+
import { SingleCombobox } from "../SingleCombobox";
|
|
10
|
+
import { MultiCombobox } from "../MultiCombobox";
|
|
11
|
+
import { SingleSearchableSelect } from "../SingleSearchableSelect";
|
|
12
|
+
import { MultiSearchableSelect } from "../MultiSearchableSelect";
|
|
13
|
+
import { books, itemToString } from "../storyData";
|
|
14
|
+
|
|
15
|
+
// Base UI's Select.List and Combobox.List render role="listbox" with no name of
|
|
16
|
+
// their own. axe only reports that as aria-input-field-name once the trigger has
|
|
17
|
+
// dropped its aria-controls, which happens while the popup animates closed — a
|
|
18
|
+
// state jsdom does not reach. So these assert the property that fixes the rule:
|
|
19
|
+
// the listbox carries a name of its own, independent of the trigger.
|
|
20
|
+
|
|
21
|
+
const LABEL_ID = "book-label";
|
|
22
|
+
const VisibleLabel = () => <span id={LABEL_ID}>Book</span>;
|
|
23
|
+
|
|
24
|
+
const openSelectPopup = () => {
|
|
25
|
+
fireEvent.click(screen.getByRole("combobox"));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const openComboboxPopup = () => {
|
|
29
|
+
fireEvent.click(screen.getByRole("button", { name: "Open popup" }));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
interface Labelling {
|
|
33
|
+
"aria-label"?: string;
|
|
34
|
+
"aria-labelledby"?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface Case {
|
|
38
|
+
name: string;
|
|
39
|
+
renderWith: (labelling: Labelling) => ReturnType<typeof render>;
|
|
40
|
+
openPopup: () => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const cases: Case[] = [
|
|
44
|
+
{
|
|
45
|
+
name: "SingleSelect",
|
|
46
|
+
renderWith: (labelling) =>
|
|
47
|
+
render(
|
|
48
|
+
<SingleSelect data={books} itemToString={itemToString} {...labelling} />
|
|
49
|
+
),
|
|
50
|
+
openPopup: openSelectPopup,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "MultiSelect",
|
|
54
|
+
renderWith: (labelling) =>
|
|
55
|
+
render(
|
|
56
|
+
<MultiSelect data={books} itemToString={itemToString} {...labelling} />
|
|
57
|
+
),
|
|
58
|
+
openPopup: openSelectPopup,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "SingleSearchableSelect",
|
|
62
|
+
renderWith: (labelling) =>
|
|
63
|
+
render(
|
|
64
|
+
<SingleSearchableSelect
|
|
65
|
+
data={books}
|
|
66
|
+
itemToString={itemToString}
|
|
67
|
+
{...labelling}
|
|
68
|
+
/>
|
|
69
|
+
),
|
|
70
|
+
openPopup: openSelectPopup,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "MultiSearchableSelect",
|
|
74
|
+
renderWith: (labelling) =>
|
|
75
|
+
render(
|
|
76
|
+
<MultiSearchableSelect
|
|
77
|
+
data={books}
|
|
78
|
+
itemToString={itemToString}
|
|
79
|
+
{...labelling}
|
|
80
|
+
/>
|
|
81
|
+
),
|
|
82
|
+
openPopup: openSelectPopup,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "SingleCombobox",
|
|
86
|
+
renderWith: (labelling) =>
|
|
87
|
+
render(
|
|
88
|
+
<SingleCombobox
|
|
89
|
+
data={books}
|
|
90
|
+
itemToString={itemToString}
|
|
91
|
+
{...labelling}
|
|
92
|
+
/>
|
|
93
|
+
),
|
|
94
|
+
openPopup: openComboboxPopup,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "MultiCombobox",
|
|
98
|
+
renderWith: (labelling) =>
|
|
99
|
+
render(
|
|
100
|
+
<MultiCombobox
|
|
101
|
+
data={books}
|
|
102
|
+
itemToString={itemToString}
|
|
103
|
+
{...labelling}
|
|
104
|
+
/>
|
|
105
|
+
),
|
|
106
|
+
openPopup: openComboboxPopup,
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
describe.each(cases)("$name popup listbox", ({ renderWith, openPopup }) => {
|
|
111
|
+
test("is named by aria-label", () => {
|
|
112
|
+
renderWith({ "aria-label": "Book" });
|
|
113
|
+
openPopup();
|
|
114
|
+
|
|
115
|
+
expect(screen.getByRole("listbox", { name: "Book" })).toBeInTheDocument();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("is named by aria-labelledby", () => {
|
|
119
|
+
render(<VisibleLabel />);
|
|
120
|
+
renderWith({ "aria-labelledby": LABEL_ID });
|
|
121
|
+
openPopup();
|
|
122
|
+
|
|
123
|
+
expect(screen.getByRole("listbox", { name: "Book" })).toBeInTheDocument();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("is unnamed when neither is given", () => {
|
|
127
|
+
renderWith({});
|
|
128
|
+
openPopup();
|
|
129
|
+
|
|
130
|
+
expect(screen.getByRole("listbox")).not.toHaveAttribute("aria-label");
|
|
131
|
+
expect(screen.getByRole("listbox")).not.toHaveAttribute("aria-labelledby");
|
|
132
|
+
});
|
|
133
|
+
});
|