@sproutsocial/seeds-react-menu 0.1.0 → 0.2.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 +10 -10
- package/CHANGELOG.md +17 -1
- package/dist/esm/index.js +209 -198
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +103 -37
- package/dist/index.d.ts +103 -37
- package/dist/index.js +239 -229
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/src/ActionMenu/ActionMenu.feature +9 -3
- package/src/ActionMenu/ActionMenu.tsx +75 -42
- package/src/ActionMenu/__tests__/ActionMenu.test.tsx +36 -42
- package/src/ActionMenu/__tests__/ActionMenu.typetest.tsx +13 -13
- package/src/MenuContent/MenuContent.tsx +31 -1
- package/src/MenuContent/MenuContentTypes.ts +2 -2
- package/src/MenuContent/styles.tsx +10 -6
- package/src/MenuFooter/MenuFooter.feature +1 -1
- package/src/MenuFooter/MenuFooter.tsx +8 -0
- package/src/MenuFooter/__tests__/MenuFooter.test.tsx +53 -26
- package/src/MenuFooter/styles.tsx +1 -1
- package/src/MenuGroup/MenuGroup.feature +14 -26
- package/src/MenuGroup/MenuGroup.tsx +21 -1
- package/src/MenuGroup/__tests__/MenuGroup.test.tsx +40 -6
- package/src/MenuGroup/styles.tsx +4 -3
- package/src/MenuHeader/MenuHeader.tsx +16 -5
- package/src/MenuHeader/__tests__/MenuHeader.test.tsx +50 -6
- package/src/MenuHeader/styles.tsx +21 -22
- package/src/MenuItem/MenuItem.feature +66 -26
- package/src/MenuItem/MenuItem.tsx +35 -20
- package/src/MenuItem/MenuItemTypes.ts +13 -1
- package/src/MenuItem/__tests__/MenuItem.test.tsx +431 -154
- package/src/MenuItem/__tests__/MenuItem.typetest.tsx +57 -38
- package/src/MenuItem/styles.tsx +42 -3
- package/src/{MenuItemSelectable/MenuItemSelectable.tsx → MenuItem/useOptionProps.tsx} +31 -54
- package/src/MenuRoot/MenuRoot.tsx +12 -17
- package/src/MenuRoot/__tests__/MenuRoot.test.tsx +3 -3
- package/src/MenuRoot/__tests__/MenuRoot.typetest.tsx +10 -10
- package/src/MultiSelectMenu/MultiSelectMenu.tsx +8 -1
- package/src/MultiSelectMenu/__tests__/MultiSelectMenu.test.tsx +19 -19
- package/src/MultiSelectMenu/__tests__/MultiSelectMenu.typetest.tsx +10 -10
- package/src/SingleSelectMenu/SingleSelectMenu.feature +11 -0
- package/src/SingleSelectMenu/SingleSelectMenu.tsx +9 -0
- package/src/SingleSelectMenu/__tests__/SingleSelectMenu.test.tsx +11 -14
- package/src/SingleSelectMenu/__tests__/SingleSelectMenu.typetest.tsx +14 -14
- package/src/__tests__/Menu.test.tsx +20 -16
- package/src/hooks/useItemsFromChildren.tsx +1 -4
- package/src/index.ts +0 -1
- package/src/menuTestingUtils.tsx +7 -4
- package/src/MenuItemSelectable/MenuItemSelectable.feature +0 -99
- package/src/MenuItemSelectable/MenuItemSelectableTypes.ts +0 -15
- package/src/MenuItemSelectable/__tests__/MenuItemSelectable.test.tsx +0 -303
- package/src/MenuItemSelectable/__tests__/MenuItemSelectable.typetest.tsx +0 -56
- package/src/MenuItemSelectable/index.ts +0 -5
- package/src/MenuItemSelectable/styles.tsx +0 -21
|
@@ -9,20 +9,20 @@ import {
|
|
|
9
9
|
export const MultiSelectMenuTypeTest = () => (
|
|
10
10
|
<>
|
|
11
11
|
{/* Valid MultiSelectMenu with minimal required props */}
|
|
12
|
-
<MultiSelectMenu
|
|
12
|
+
<MultiSelectMenu menuToggleElement={<>test</>}>Test</MultiSelectMenu>
|
|
13
13
|
{/* Valid MultiSelectMenu allows MenuContent by itself as a child */}
|
|
14
|
-
<MultiSelectMenu
|
|
14
|
+
<MultiSelectMenu menuToggleElement={<>test</>}>
|
|
15
15
|
<MenuContent>Test</MenuContent>
|
|
16
16
|
</MultiSelectMenu>
|
|
17
17
|
{/* Valid MultiSelectMenu allows multiple children without fragment */}
|
|
18
|
-
<MultiSelectMenu
|
|
18
|
+
<MultiSelectMenu menuToggleElement={<>test</>}>
|
|
19
19
|
<MenuHeader>Test</MenuHeader>
|
|
20
20
|
<MenuContent>Test</MenuContent>
|
|
21
21
|
<MenuFooter>Test</MenuFooter>
|
|
22
22
|
</MultiSelectMenu>
|
|
23
23
|
{/* Valid MultiSelectMenu accepts Downshift props and functions for useSelect */}
|
|
24
24
|
<MultiSelectMenu
|
|
25
|
-
|
|
25
|
+
menuToggleElement={<>test</>}
|
|
26
26
|
onSelectedItemChange={() => {}}
|
|
27
27
|
selectedItem={null}
|
|
28
28
|
stateReducer={(c) => c}
|
|
@@ -34,7 +34,7 @@ export const MultiSelectMenuTypeTest = () => (
|
|
|
34
34
|
</MultiSelectMenu>
|
|
35
35
|
{/* Valid MultiSelectMenu accepts Downshift props and functions for useMultipleSelection */}
|
|
36
36
|
<MultiSelectMenu
|
|
37
|
-
|
|
37
|
+
menuToggleElement={<>test</>}
|
|
38
38
|
onSelectedItemsChange={() => {}}
|
|
39
39
|
selectedItems={[]}
|
|
40
40
|
multiSelectStateReducer={(c) => c}
|
|
@@ -44,19 +44,19 @@ export const MultiSelectMenuTypeTest = () => (
|
|
|
44
44
|
Test
|
|
45
45
|
</MultiSelectMenu>
|
|
46
46
|
|
|
47
|
-
{/* @ts-expect-error -
|
|
47
|
+
{/* @ts-expect-error - menuToggleElement is a required prop */}
|
|
48
48
|
<MultiSelectMenu>Test</MultiSelectMenu>
|
|
49
49
|
<MultiSelectMenu
|
|
50
|
-
/* @ts-expect-error -
|
|
51
|
-
|
|
50
|
+
/* @ts-expect-error - menuToggleElement must be a valid react element */
|
|
51
|
+
menuToggleElement="test"
|
|
52
52
|
>
|
|
53
53
|
Test
|
|
54
54
|
</MultiSelectMenu>
|
|
55
55
|
{/* @ts-expect-error - when no children provided */}
|
|
56
|
-
<MultiSelectMenu
|
|
56
|
+
<MultiSelectMenu menuToggleElement="test" />
|
|
57
57
|
|
|
58
58
|
<MultiSelectMenu
|
|
59
|
-
|
|
59
|
+
menuToggleElement={<>test</>}
|
|
60
60
|
/* @ts-expect-error - isOpen can't be a string */
|
|
61
61
|
isOpen="false"
|
|
62
62
|
/* @ts-expect-error - onSelectedItemChange can't be a string */
|
|
@@ -10,6 +10,17 @@ Feature: Single Select Menu
|
|
|
10
10
|
When an item is selected
|
|
11
11
|
Then a selectedItem is set
|
|
12
12
|
|
|
13
|
+
Scenario: SingleSelectMenu remains open when interacting with the footer
|
|
14
|
+
Given the menu has a footer
|
|
15
|
+
And the footer contains an interactive element
|
|
16
|
+
When an interactive element in the footer is clicked
|
|
17
|
+
Then the menu will remain open
|
|
18
|
+
|
|
19
|
+
Scenario: SingleSelectMenu closes when a selection is made
|
|
20
|
+
Given the menu is using the built in behavior
|
|
21
|
+
When a menu item is selected
|
|
22
|
+
Then the menu will close
|
|
23
|
+
|
|
13
24
|
Rule: API
|
|
14
25
|
Background:
|
|
15
26
|
Given an engineer is implementing a SingleSelectMenu
|
|
@@ -10,6 +10,15 @@ import { MenuRoot } from "../MenuRoot";
|
|
|
10
10
|
import type { TypeDefaultItemProps } from "../types";
|
|
11
11
|
import type { TypeSingleSelectMenuProps } from "./SingleSelectMenuTypes";
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @link https://seeds.sproutsocial.com/components/singleselect-menu/
|
|
15
|
+
*
|
|
16
|
+
* @description A SingleSelectMenu allows a single selection of a {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItem} from a list or groups or lists.
|
|
17
|
+
*
|
|
18
|
+
* **To trigger actions from a menu:**
|
|
19
|
+
* @see {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/ActionMenu | ActionMenu}
|
|
20
|
+
*/
|
|
21
|
+
|
|
13
22
|
export const SingleSelectMenu = ({
|
|
14
23
|
children,
|
|
15
24
|
stateReducer: externalStateReducer,
|
|
@@ -4,14 +4,13 @@ import {
|
|
|
4
4
|
render,
|
|
5
5
|
screen,
|
|
6
6
|
waitFor,
|
|
7
|
-
act,
|
|
8
7
|
} from "@sproutsocial/seeds-react-testing-library";
|
|
9
8
|
import {
|
|
10
9
|
SingleSelectMenu,
|
|
11
10
|
MenuToggleButton,
|
|
12
11
|
MenuContent,
|
|
13
12
|
MenuGroup,
|
|
14
|
-
|
|
13
|
+
MenuItem,
|
|
15
14
|
MenuFooter,
|
|
16
15
|
} from "../../index";
|
|
17
16
|
import { Switch } from "@sproutsocial/seeds-react-switch";
|
|
@@ -30,16 +29,16 @@ describe("User Behavior", () => {
|
|
|
30
29
|
const { user } = render(
|
|
31
30
|
<SingleSelectMenu
|
|
32
31
|
onSelectedItemChange={checkOnChange}
|
|
33
|
-
|
|
32
|
+
menuToggleElement={
|
|
34
33
|
<MenuToggleButton role="button">Click me</MenuToggleButton>
|
|
35
34
|
}
|
|
36
35
|
>
|
|
37
36
|
<MenuContent>
|
|
38
37
|
<MenuGroup title="Menu Title">
|
|
39
38
|
{menuItems.map(({ id, label }) => (
|
|
40
|
-
<
|
|
39
|
+
<MenuItem key={id} id={id}>
|
|
41
40
|
{label}
|
|
42
|
-
</
|
|
41
|
+
</MenuItem>
|
|
43
42
|
))}
|
|
44
43
|
</MenuGroup>
|
|
45
44
|
</MenuContent>
|
|
@@ -96,16 +95,16 @@ describe("User Behavior", () => {
|
|
|
96
95
|
|
|
97
96
|
const { user } = render(
|
|
98
97
|
<SingleSelectMenu
|
|
99
|
-
|
|
98
|
+
menuToggleElement={
|
|
100
99
|
<MenuToggleButton role="button">Click me</MenuToggleButton>
|
|
101
100
|
}
|
|
102
101
|
>
|
|
103
102
|
<MenuContent>
|
|
104
103
|
<MenuGroup title="Menu Title">
|
|
105
104
|
{menuItems.map(({ id, label }) => (
|
|
106
|
-
<
|
|
105
|
+
<MenuItem key={id} id={id}>
|
|
107
106
|
{label}
|
|
108
|
-
</
|
|
107
|
+
</MenuItem>
|
|
109
108
|
))}
|
|
110
109
|
</MenuGroup>
|
|
111
110
|
</MenuContent>
|
|
@@ -129,20 +128,18 @@ describe("User Behavior", () => {
|
|
|
129
128
|
// Check that the menu is still open
|
|
130
129
|
expect(screen.getByRole("listbox")).toBeVisible();
|
|
131
130
|
});
|
|
132
|
-
});
|
|
133
131
|
|
|
134
|
-
|
|
135
|
-
it("should close automatically on selection", async () => {
|
|
132
|
+
it("closes automatically on selection", async () => {
|
|
136
133
|
const { user } = render(
|
|
137
134
|
<SingleSelectMenu
|
|
138
|
-
|
|
135
|
+
menuToggleElement={<MenuToggleButton>Click me</MenuToggleButton>}
|
|
139
136
|
>
|
|
140
137
|
<MenuContent>
|
|
141
138
|
<MenuGroup title="Menu Title">
|
|
142
139
|
{menuItems.map(({ id, label }) => (
|
|
143
|
-
<
|
|
140
|
+
<MenuItem key={id} id={id}>
|
|
144
141
|
{label}
|
|
145
|
-
</
|
|
142
|
+
</MenuItem>
|
|
146
143
|
))}
|
|
147
144
|
</MenuGroup>
|
|
148
145
|
</MenuContent>
|
|
@@ -8,20 +8,20 @@ import {
|
|
|
8
8
|
export const SingleSelectMenuTypeTest = () => (
|
|
9
9
|
<>
|
|
10
10
|
{/* Valid SingleSelectMenu with minimal required props */}
|
|
11
|
-
<SingleSelectMenu
|
|
11
|
+
<SingleSelectMenu menuToggleElement={<>test</>}>Test</SingleSelectMenu>
|
|
12
12
|
{/* Valid SingleSelectMenu allows MenuContent by itself as a child */}
|
|
13
|
-
<SingleSelectMenu
|
|
13
|
+
<SingleSelectMenu menuToggleElement={<>test</>}>
|
|
14
14
|
<MenuContent>Test</MenuContent>
|
|
15
15
|
</SingleSelectMenu>
|
|
16
16
|
{/* Valid SingleSelectMenu allows multiple children without fragment */}
|
|
17
|
-
<SingleSelectMenu
|
|
17
|
+
<SingleSelectMenu menuToggleElement={<>test</>}>
|
|
18
18
|
<MenuHeader>Test</MenuHeader>
|
|
19
19
|
<MenuContent>Test</MenuContent>
|
|
20
20
|
<MenuFooter>Test</MenuFooter>
|
|
21
21
|
</SingleSelectMenu>
|
|
22
22
|
{/* Valid SingleSelectMenu accepts Downshift props and functions for useSelect */}
|
|
23
23
|
<SingleSelectMenu
|
|
24
|
-
|
|
24
|
+
menuToggleElement={<>test</>}
|
|
25
25
|
onSelectedItemChange={() => {}}
|
|
26
26
|
selectedItem={null}
|
|
27
27
|
stateReducer={(c) => c}
|
|
@@ -32,19 +32,19 @@ export const SingleSelectMenuTypeTest = () => (
|
|
|
32
32
|
Test
|
|
33
33
|
</SingleSelectMenu>
|
|
34
34
|
|
|
35
|
-
{/* @ts-expect-error -
|
|
35
|
+
{/* @ts-expect-error - menuToggleElement is a required prop */}
|
|
36
36
|
<SingleSelectMenu>Test</SingleSelectMenu>
|
|
37
37
|
<SingleSelectMenu
|
|
38
|
-
/* @ts-expect-error -
|
|
39
|
-
|
|
38
|
+
/* @ts-expect-error - menuToggleElement must be a valid react element */
|
|
39
|
+
menuToggleElement="test"
|
|
40
40
|
>
|
|
41
41
|
Test
|
|
42
42
|
</SingleSelectMenu>
|
|
43
43
|
{/* @ts-expect-error - when no children provided */}
|
|
44
|
-
<SingleSelectMenu
|
|
44
|
+
<SingleSelectMenu menuToggleElement="test" />
|
|
45
45
|
|
|
46
46
|
<SingleSelectMenu
|
|
47
|
-
|
|
47
|
+
menuToggleElement={<>test</>}
|
|
48
48
|
/* @ts-expect-error - isOpen can't be a string */
|
|
49
49
|
isOpen="false"
|
|
50
50
|
/* @ts-expect-error - onSelectedItemChange can't be a string */
|
|
@@ -57,35 +57,35 @@ export const SingleSelectMenuTypeTest = () => (
|
|
|
57
57
|
Test
|
|
58
58
|
</SingleSelectMenu>
|
|
59
59
|
<SingleSelectMenu
|
|
60
|
-
|
|
60
|
+
menuToggleElement={<>test</>}
|
|
61
61
|
/* @ts-expect-error - onMultiSelectStateChange can't be used on SingleSelectMenu */
|
|
62
62
|
onMultiSelectStateChange={() => {}}
|
|
63
63
|
>
|
|
64
64
|
Test
|
|
65
65
|
</SingleSelectMenu>
|
|
66
66
|
<SingleSelectMenu
|
|
67
|
-
|
|
67
|
+
menuToggleElement={<>test</>}
|
|
68
68
|
/* @ts-expect-error - selectedItems can't be used on SingleSelectMenu */
|
|
69
69
|
selectedItems={[]}
|
|
70
70
|
>
|
|
71
71
|
Test
|
|
72
72
|
</SingleSelectMenu>
|
|
73
73
|
<SingleSelectMenu
|
|
74
|
-
|
|
74
|
+
menuToggleElement={<>test</>}
|
|
75
75
|
/* @ts-expect-error - multiSelectStateReducer can't be used on SingleSelectMenu */
|
|
76
76
|
multiSelectStateReducer={(c) => c}
|
|
77
77
|
>
|
|
78
78
|
Test
|
|
79
79
|
</SingleSelectMenu>
|
|
80
80
|
<SingleSelectMenu
|
|
81
|
-
|
|
81
|
+
menuToggleElement={<>test</>}
|
|
82
82
|
/* @ts-expect-error - onMultiSelectStateChange can't be used on SingleSelectMenu */
|
|
83
83
|
onMultiSelectStateChange={() => {}}
|
|
84
84
|
>
|
|
85
85
|
Test
|
|
86
86
|
</SingleSelectMenu>
|
|
87
87
|
<SingleSelectMenu
|
|
88
|
-
|
|
88
|
+
menuToggleElement={<>test</>}
|
|
89
89
|
/* @ts-expect-error - getA11yMultiStatusMessage can't be used on SingleSelectMenu */
|
|
90
90
|
getA11yMultiStatusMessage={() => ""}
|
|
91
91
|
>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* eslint-disable testing-library/no-unnecessary-act */
|
|
2
|
+
import { PointerEventsCheckLevel } from "@testing-library/user-event";
|
|
2
3
|
import {
|
|
3
4
|
render,
|
|
4
5
|
screen,
|
|
5
6
|
waitFor,
|
|
6
|
-
act,
|
|
7
7
|
} from "@sproutsocial/seeds-react-testing-library";
|
|
8
8
|
import {
|
|
9
9
|
ActionMenu,
|
|
@@ -23,7 +23,7 @@ describe("Menu", () => {
|
|
|
23
23
|
it("should render the trigger button", () => {
|
|
24
24
|
render(
|
|
25
25
|
<Component
|
|
26
|
-
|
|
26
|
+
menuToggleElement={
|
|
27
27
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
28
28
|
Open
|
|
29
29
|
</MenuToggleButton>
|
|
@@ -40,7 +40,7 @@ describe("Menu", () => {
|
|
|
40
40
|
it("should default to open if initialIsOpen is true", () => {
|
|
41
41
|
render(
|
|
42
42
|
<Component
|
|
43
|
-
|
|
43
|
+
menuToggleElement={
|
|
44
44
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
45
45
|
Open
|
|
46
46
|
</MenuToggleButton>
|
|
@@ -61,7 +61,7 @@ describe("Menu", () => {
|
|
|
61
61
|
it("should open when trigger button is clicked", async () => {
|
|
62
62
|
const { user } = render(
|
|
63
63
|
<Component
|
|
64
|
-
|
|
64
|
+
menuToggleElement={
|
|
65
65
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
66
66
|
Open
|
|
67
67
|
</MenuToggleButton>
|
|
@@ -86,7 +86,7 @@ describe("Menu", () => {
|
|
|
86
86
|
it("should open when trigger button is focused and enter key pressed", async () => {
|
|
87
87
|
const { user } = render(
|
|
88
88
|
<Component
|
|
89
|
-
|
|
89
|
+
menuToggleElement={
|
|
90
90
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
91
91
|
Open
|
|
92
92
|
</MenuToggleButton>
|
|
@@ -112,7 +112,7 @@ describe("Menu", () => {
|
|
|
112
112
|
it("should open when trigger button is focused and space key pressed", async () => {
|
|
113
113
|
const { user } = render(
|
|
114
114
|
<Component
|
|
115
|
-
|
|
115
|
+
menuToggleElement={
|
|
116
116
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
117
117
|
Open
|
|
118
118
|
</MenuToggleButton>
|
|
@@ -138,7 +138,7 @@ describe("Menu", () => {
|
|
|
138
138
|
it("should close when trigger button is clicked while open", async () => {
|
|
139
139
|
const { user } = render(
|
|
140
140
|
<Component
|
|
141
|
-
|
|
141
|
+
menuToggleElement={
|
|
142
142
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
143
143
|
Open
|
|
144
144
|
</MenuToggleButton>
|
|
@@ -167,7 +167,7 @@ describe("Menu", () => {
|
|
|
167
167
|
const mockOnIsOpenChange = jest.fn();
|
|
168
168
|
const { user } = render(
|
|
169
169
|
<Component
|
|
170
|
-
|
|
170
|
+
menuToggleElement={
|
|
171
171
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
172
172
|
Open
|
|
173
173
|
</MenuToggleButton>
|
|
@@ -199,7 +199,7 @@ describe("Menu", () => {
|
|
|
199
199
|
const { user } = render(
|
|
200
200
|
<div>
|
|
201
201
|
<Component
|
|
202
|
-
|
|
202
|
+
menuToggleElement={
|
|
203
203
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
204
204
|
Open
|
|
205
205
|
</MenuToggleButton>
|
|
@@ -230,7 +230,7 @@ describe("Menu", () => {
|
|
|
230
230
|
const mockOnSelectedItemChange = jest.fn();
|
|
231
231
|
const { user } = render(
|
|
232
232
|
<Component
|
|
233
|
-
|
|
233
|
+
menuToggleElement={
|
|
234
234
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
235
235
|
Open
|
|
236
236
|
</MenuToggleButton>
|
|
@@ -252,7 +252,11 @@ describe("Menu", () => {
|
|
|
252
252
|
const menuItem = await screen.findByText("Item 1");
|
|
253
253
|
|
|
254
254
|
// Use click to activate menu item
|
|
255
|
-
await user
|
|
255
|
+
await user
|
|
256
|
+
.setup({
|
|
257
|
+
pointerEventsCheck: PointerEventsCheckLevel.Never,
|
|
258
|
+
})
|
|
259
|
+
.click(menuItem);
|
|
256
260
|
|
|
257
261
|
// Check that onSelectedItemChange is called
|
|
258
262
|
await waitFor(() => expect(mockOnSelectedItemChange).toHaveBeenCalled());
|
|
@@ -262,7 +266,7 @@ describe("Menu", () => {
|
|
|
262
266
|
const mockOnSelectedItemChange = jest.fn();
|
|
263
267
|
const { user } = render(
|
|
264
268
|
<Component
|
|
265
|
-
|
|
269
|
+
menuToggleElement={
|
|
266
270
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
267
271
|
Open
|
|
268
272
|
</MenuToggleButton>
|
|
@@ -294,7 +298,7 @@ describe("Menu", () => {
|
|
|
294
298
|
const mockOnSelectedItemChange = jest.fn();
|
|
295
299
|
const { user } = render(
|
|
296
300
|
<Component
|
|
297
|
-
|
|
301
|
+
menuToggleElement={
|
|
298
302
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
299
303
|
Open
|
|
300
304
|
</MenuToggleButton>
|
|
@@ -326,7 +330,7 @@ describe("Menu", () => {
|
|
|
326
330
|
const mockOnIsOpenChange = jest.fn();
|
|
327
331
|
const { user } = render(
|
|
328
332
|
<Component
|
|
329
|
-
|
|
333
|
+
menuToggleElement={
|
|
330
334
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
331
335
|
Open
|
|
332
336
|
</MenuToggleButton>
|
|
@@ -358,7 +362,7 @@ describe("Menu", () => {
|
|
|
358
362
|
const mockOnHighlightedIndexChange = jest.fn();
|
|
359
363
|
const { user } = render(
|
|
360
364
|
<Component
|
|
361
|
-
|
|
365
|
+
menuToggleElement={
|
|
362
366
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
363
367
|
Open
|
|
364
368
|
</MenuToggleButton>
|
|
@@ -392,7 +396,7 @@ describe("Menu", () => {
|
|
|
392
396
|
const mockStateReducer = jest.fn((state, { changes }) => changes);
|
|
393
397
|
const { user } = render(
|
|
394
398
|
<Component
|
|
395
|
-
|
|
399
|
+
menuToggleElement={
|
|
396
400
|
<MenuToggleButton role="button" aria-label="Open Menu">
|
|
397
401
|
Open
|
|
398
402
|
</MenuToggleButton>
|
|
@@ -42,10 +42,7 @@ const getAllMenuItems = (children: ReactNode) => {
|
|
|
42
42
|
const allMenuItems: TypeItemElements[] = [];
|
|
43
43
|
// console.log("children", children);
|
|
44
44
|
walkAllChildren(children, (element, parents) => {
|
|
45
|
-
if (
|
|
46
|
-
checkIfIsElement(element, "MenuItem") ||
|
|
47
|
-
checkIfIsElement(element, "MenuItemSelectable")
|
|
48
|
-
) {
|
|
45
|
+
if (checkIfIsElement(element, "MenuItem")) {
|
|
49
46
|
allMenuItems.push({
|
|
50
47
|
element: element as TypeItemElements["element"],
|
|
51
48
|
parents,
|
package/src/index.ts
CHANGED
package/src/menuTestingUtils.tsx
CHANGED
|
@@ -35,14 +35,17 @@ export const testDefaultContext = (
|
|
|
35
35
|
*/
|
|
36
36
|
export const TestWithMenuRoot = ({
|
|
37
37
|
children,
|
|
38
|
-
|
|
38
|
+
menuToggleElement,
|
|
39
39
|
...props
|
|
40
40
|
}: {
|
|
41
41
|
children: TypeMenuRootProps["children"];
|
|
42
|
-
|
|
43
|
-
} & Partial<Omit<TypeMenuRootProps, "children" | "
|
|
42
|
+
menuToggleElement: TypeMenuRootProps["menuToggleElement"];
|
|
43
|
+
} & Partial<Omit<TypeMenuRootProps, "children" | "menuToggleElement">>) => {
|
|
44
44
|
return (
|
|
45
|
-
<MenuRoot
|
|
45
|
+
<MenuRoot
|
|
46
|
+
menuToggleElement={menuToggleElement}
|
|
47
|
+
{...testDefaultContext(props)}
|
|
48
|
+
>
|
|
46
49
|
{children}
|
|
47
50
|
</MenuRoot>
|
|
48
51
|
);
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
Feature: MenuItemSelectable
|
|
2
|
-
|
|
3
|
-
A selectable item designed to be included within a Menu component, providing different input types
|
|
4
|
-
|
|
5
|
-
Rule: User Behavior
|
|
6
|
-
|
|
7
|
-
Background:
|
|
8
|
-
Given an end user is interacting with the component
|
|
9
|
-
|
|
10
|
-
Scenario Outline: MenuItemSelectable can be checked
|
|
11
|
-
Given the MenuItemSelectable is in the unchecked state
|
|
12
|
-
And the MenuItemSelectable is focused
|
|
13
|
-
And the MenuItemSelectable is not disabled
|
|
14
|
-
When the MenuItemSelectable is triggered via <interaction>
|
|
15
|
-
Then the MenuItemSelectable should be checked
|
|
16
|
-
|
|
17
|
-
Examples: Interactions
|
|
18
|
-
| interaction |
|
|
19
|
-
| clicking with mouse |
|
|
20
|
-
| pressing the Enter key |
|
|
21
|
-
| pressing the Space key |
|
|
22
|
-
|
|
23
|
-
Scenario Outline: MenuItemSelectable can be unchecked
|
|
24
|
-
Given the MenuItemSelectable is in the checked state
|
|
25
|
-
And the MenuItemSelectable is focused
|
|
26
|
-
And the MenuItemSelectable is not disabled
|
|
27
|
-
When the MenuItemSelectable is triggered via <interaction>
|
|
28
|
-
Then the MenuItemSelectable should be unchecked
|
|
29
|
-
|
|
30
|
-
Examples: Interactions
|
|
31
|
-
| interaction |
|
|
32
|
-
| clicking with mouse |
|
|
33
|
-
| pressing the Enter key |
|
|
34
|
-
| pressing the Space key |
|
|
35
|
-
|
|
36
|
-
Scenario Outline: MenuItemSelectable is disabled
|
|
37
|
-
Given the MenuItemSelectable is disabled
|
|
38
|
-
And the MenuItemSelectable is focused
|
|
39
|
-
When the MenuItemSelectable is triggered via <interaction>
|
|
40
|
-
Then no events should fire
|
|
41
|
-
|
|
42
|
-
Examples: Interactions
|
|
43
|
-
| interaction |
|
|
44
|
-
| clicking with mouse |
|
|
45
|
-
| pressing the Enter key |
|
|
46
|
-
| pressing the Space key |
|
|
47
|
-
|
|
48
|
-
Rule: API
|
|
49
|
-
Background:
|
|
50
|
-
Given an engineer is developing using the component
|
|
51
|
-
|
|
52
|
-
Scenario: MenuItemSelectable accepts children
|
|
53
|
-
When <child component(s)> are provided
|
|
54
|
-
Then the MenuItemSelectable should render the <component(s)>
|
|
55
|
-
|
|
56
|
-
Examples: child components
|
|
57
|
-
| child component(s) | component(s) |
|
|
58
|
-
| a Link is | Link |
|
|
59
|
-
| a Text is | Text |
|
|
60
|
-
| a Icon is | Icon |
|
|
61
|
-
| a Text then Icon are | Text and Icon |
|
|
62
|
-
| a Icon and Text are | Icon and Text |
|
|
63
|
-
|
|
64
|
-
Scenario Outline: MenuItemSelectable supports different input types
|
|
65
|
-
When an <inputTypeProp> is passed to the MenuItemSelectable component
|
|
66
|
-
Then the MenuItemSelectable renders with the appropriate <component> type
|
|
67
|
-
|
|
68
|
-
Examples: Input Types
|
|
69
|
-
| inputTypeProp | component |
|
|
70
|
-
| checkbox | Checkbox |
|
|
71
|
-
| radio | Radio |
|
|
72
|
-
| switch | Switch |
|
|
73
|
-
|
|
74
|
-
Scenario: MenuItemSelectable defaults to an icon input type
|
|
75
|
-
When the MenuItemSelectable is implemented without an inputType prop specified
|
|
76
|
-
Then the MenuItemSelectable defaults to an icon input type
|
|
77
|
-
|
|
78
|
-
Scenario: MenuItemSelectable checked state can be enabled via a prop
|
|
79
|
-
When the selected prop is set to true
|
|
80
|
-
Then the MenuItemSelectable should appear in the checked state
|
|
81
|
-
|
|
82
|
-
Scenario Outline: MenuItemSelectable validates prop types
|
|
83
|
-
When any <propName> is passed to the MenuItemSelectable
|
|
84
|
-
Then the MenuItemSelectable should check that each <propName> is of the expected <propType>
|
|
85
|
-
|
|
86
|
-
Examples: Prop Types
|
|
87
|
-
| propName | propType |
|
|
88
|
-
| children | ReactNode |
|
|
89
|
-
| disabled | boolean |
|
|
90
|
-
| elevation | low, medium, or high |
|
|
91
|
-
| href | string |
|
|
92
|
-
| onClick | React.MouseEventHandler |
|
|
93
|
-
| role | string |
|
|
94
|
-
| selected | boolean |
|
|
95
|
-
| inputType | checkbox, radio, or switch |
|
|
96
|
-
|
|
97
|
-
Scenario: MenuItemSelectable extends MenuItem
|
|
98
|
-
When MenuItemSelectable features are used
|
|
99
|
-
Then the MenuItemSelectable responds as a MenuItem would
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { TypeMenuItemProps } from "../MenuItem";
|
|
2
|
-
|
|
3
|
-
export const INPUT_TYPES = {
|
|
4
|
-
CHECKBOX: "checkbox",
|
|
5
|
-
RADIO: "radio",
|
|
6
|
-
SWITCH: "switch",
|
|
7
|
-
ICON: "icon",
|
|
8
|
-
} as const;
|
|
9
|
-
export type InputType = (typeof INPUT_TYPES)[keyof typeof INPUT_TYPES];
|
|
10
|
-
|
|
11
|
-
export interface TypeMenuItemSelectableProps extends TypeMenuItemProps {
|
|
12
|
-
active?: boolean;
|
|
13
|
-
inputType?: InputType;
|
|
14
|
-
inputLabel?: string;
|
|
15
|
-
}
|