Skip to content

Commit 8c91c15

Browse files
authored
chore(dropdown): add split button action example (#11753)
* chore(dropdown): add split button action example * added aria label * added aria label * added aria labels * added the onOpenChange prop * added focus logic * remove unnecessary nesting * update description and title * update description * update imports
1 parent a5726d0 commit 8c91c15

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

packages/react-core/src/components/Dropdown/examples/Dropdown.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ propComponents:
1616
]
1717
---
1818

19-
import { useState } from 'react';
19+
import { useState, useRef } from 'react';
2020
import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
2121

2222
## Examples
@@ -63,3 +63,15 @@ To provide users with more context about a `<DropdownItem>`, pass a short messag
6363
```ts file="./DropdownWithDescriptions.tsx"
6464

6565
```
66+
67+
### Split toggle with checkbox
68+
69+
To combine a checkbox or other control with a dropdown menu, use a split button.
70+
71+
A `<MenuToggle>` can be rendered as a split button via `splitButtonItems`. Elements to be displayed before the dropdown toggle button (like the `<MenuToggleCheckbox>`) must be included in the `splitButtonItems`.
72+
73+
If the dropdown menu closes upon selection, you will need to manually shift focus back to the toggle element after a user selects an item from the menu.
74+
75+
```ts file="./DropdownWithSplit.tsx"
76+
77+
```
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import {
2+
Dropdown,
3+
MenuToggle,
4+
MenuToggleCheckbox,
5+
DropdownItem,
6+
DropdownList,
7+
Divider,
8+
MenuToggleElement
9+
} from '@patternfly/react-core';
10+
import { useRef, useState } from 'react';
11+
12+
export const DropdownSplitButtonText: React.FunctionComponent = () => {
13+
const [isOpen, setIsOpen] = useState(false);
14+
const toggleRef = useRef<MenuToggleElement>(null);
15+
16+
const onFocus = () => {
17+
if (!toggleRef.current) {
18+
return;
19+
}
20+
21+
const toggleButton = toggleRef.current.querySelector('button[aria-expanded]');
22+
toggleButton?.focus();
23+
};
24+
25+
const onSelect = () => {
26+
setIsOpen(false);
27+
onFocus();
28+
};
29+
30+
const onToggleClick = () => {
31+
setIsOpen(!isOpen);
32+
};
33+
34+
return (
35+
<Dropdown
36+
onSelect={onSelect}
37+
onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)}
38+
toggle={(toggleRefCallback: React.Ref<MenuToggleElement>) => (
39+
<MenuToggle
40+
ref={(node) => {
41+
// Handle both callback ref and useRef
42+
if (typeof toggleRefCallback === 'function') {
43+
toggleRefCallback(node);
44+
} else if (toggleRefCallback) {
45+
(toggleRefCallback as React.MutableRefObject<MenuToggleElement | null>).current = node;
46+
}
47+
(toggleRef as React.MutableRefObject<MenuToggleElement | null>).current = node;
48+
}}
49+
splitButtonItems={[
50+
<MenuToggleCheckbox id="split-button-checkbox-example" key="split-checkbox" aria-label="Select all" />
51+
]}
52+
aria-label="Dropdown with checkbox split button"
53+
onClick={onToggleClick}
54+
isExpanded={isOpen}
55+
/>
56+
)}
57+
isOpen={isOpen}
58+
>
59+
<DropdownList>
60+
<DropdownItem value={0} key="action">
61+
Action
62+
</DropdownItem>
63+
<DropdownItem
64+
value={1}
65+
key="link"
66+
to="#default-link2"
67+
// Prevent the default onClick functionality for example purposes
68+
onClick={(ev: any) => ev.preventDefault()}
69+
>
70+
Link
71+
</DropdownItem>
72+
<DropdownItem value={2} isDisabled key="disabled action">
73+
Disabled Action
74+
</DropdownItem>
75+
<DropdownItem value={3} isDisabled key="disabled link" to="#default-link4">
76+
Disabled Link
77+
</DropdownItem>
78+
<DropdownItem
79+
value={4}
80+
isAriaDisabled
81+
key="aria-disabled link"
82+
to="#default-link5"
83+
tooltipProps={{ content: 'aria-disabled link', position: 'top' }}
84+
>
85+
Aria-disabled Link
86+
</DropdownItem>
87+
<Divider component="li" key="separator" />
88+
<DropdownItem value={5} key="separated action">
89+
Separated Action
90+
</DropdownItem>
91+
<DropdownItem value={6} key="separated link" to="#default-link6" onClick={(ev) => ev.preventDefault()}>
92+
Separated Link
93+
</DropdownItem>
94+
</DropdownList>
95+
</Dropdown>
96+
);
97+
};

0 commit comments

Comments
 (0)