Skip to content

Commit bc3c6d8

Browse files
author
Eric Olkowski
committed
fix(Select-next,Dropdown-next): updated logic for keyboard interaction
1 parent 6cc92de commit bc3c6d8

File tree

2 files changed

+24
-26
lines changed

2 files changed

+24
-26
lines changed

packages/react-core/src/next/components/Dropdown/Dropdown.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,27 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
5858
const menuRef = (innerRef as React.RefObject<HTMLDivElement>) || localMenuRef;
5959
React.useEffect(() => {
6060
const handleMenuKeys = (event: KeyboardEvent) => {
61-
if (!isOpen && toggleRef.current?.contains(event.target as Node)) {
62-
// toggle was clicked open, focus on first menu item
63-
if (event.key === 'Enter') {
64-
setTimeout(() => {
65-
const firstElement = menuRef.current.querySelector('li > button:not(:disabled)');
66-
firstElement && (firstElement as HTMLElement).focus();
67-
}, 0);
68-
}
69-
}
7061
// Close the menu on tab or escape if onOpenChange is provided
7162
if (
7263
(isOpen && onOpenChange && menuRef.current?.contains(event.target as Node)) ||
7364
toggleRef.current?.contains(event.target as Node)
7465
) {
7566
if (event.key === 'Escape' || event.key === 'Tab') {
76-
onOpenChange(!isOpen);
67+
onOpenChange(false);
7768
toggleRef.current?.focus();
7869
}
7970
}
8071
};
8172

82-
const handleClickOutside = (event: MouseEvent) => {
73+
const handleClick = (event: MouseEvent) => {
74+
// toggle was clicked open via keyboard, focus on first menu item
75+
if (isOpen && toggleRef.current?.contains(event.target as Node) && event.detail === 0) {
76+
setTimeout(() => {
77+
const firstElement = menuRef?.current?.querySelector('li button:not(:disabled),li input:not(:disabled)');
78+
firstElement && (firstElement as HTMLElement).focus();
79+
}, 0);
80+
}
81+
8382
// If the event is not on the toggle and onOpenChange callback is provided, close the menu
8483
if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) {
8584
if (isOpen && !menuRef.current?.contains(event.target as Node)) {
@@ -89,11 +88,11 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
8988
};
9089

9190
window.addEventListener('keydown', handleMenuKeys);
92-
window.addEventListener('click', handleClickOutside);
91+
window.addEventListener('click', handleClick);
9392

9493
return () => {
9594
window.removeEventListener('keydown', handleMenuKeys);
96-
window.removeEventListener('click', handleClickOutside);
95+
window.removeEventListener('click', handleClick);
9796
};
9897
}, [isOpen, menuRef, onOpenChange]);
9998

packages/react-core/src/next/components/Select/Select.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,27 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
5151
const menuRef = (innerRef as React.RefObject<HTMLDivElement>) || localMenuRef;
5252
React.useEffect(() => {
5353
const handleMenuKeys = (event: KeyboardEvent) => {
54-
if (!isOpen && toggleRef.current?.contains(event.target as Node)) {
55-
// toggle was clicked open, focus on first menu item
56-
if (event.key === 'Enter' || event.key === 'Space') {
57-
setTimeout(() => {
58-
const firstElement = menuRef?.current?.querySelector('li button:not(:disabled),li input:not(:disabled)');
59-
firstElement && (firstElement as HTMLElement).focus();
60-
}, 0);
61-
}
62-
}
6354
// Close the menu on tab or escape if onOpenChange is provided
6455
if (
6556
(isOpen && onOpenChange && menuRef.current?.contains(event.target as Node)) ||
6657
toggleRef.current?.contains(event.target as Node)
6758
) {
6859
if (event.key === 'Escape' || event.key === 'Tab') {
69-
onOpenChange(!isOpen);
60+
onOpenChange(false);
7061
toggleRef.current?.focus();
7162
}
7263
}
7364
};
7465

75-
const handleClickOutside = (event: MouseEvent) => {
66+
const handleClick = (event: MouseEvent) => {
67+
// toggle was clicked open via keyboard, focus on first menu item
68+
if (isOpen && toggleRef.current?.contains(event.target as Node) && event.detail === 0) {
69+
setTimeout(() => {
70+
const firstElement = menuRef?.current?.querySelector('li button:not(:disabled),li input:not(:disabled)');
71+
firstElement && (firstElement as HTMLElement).focus();
72+
}, 0);
73+
}
74+
7675
// If the event is not on the toggle and onOpenChange callback is provided, close the menu
7776
if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) {
7877
if (isOpen && !menuRef.current?.contains(event.target as Node)) {
@@ -82,11 +81,11 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
8281
};
8382

8483
window.addEventListener('keydown', handleMenuKeys);
85-
window.addEventListener('click', handleClickOutside);
84+
window.addEventListener('click', handleClick);
8685

8786
return () => {
8887
window.removeEventListener('keydown', handleMenuKeys);
89-
window.removeEventListener('click', handleClickOutside);
88+
window.removeEventListener('click', handleClick);
9089
};
9190
}, [isOpen, menuRef, onOpenChange]);
9291

0 commit comments

Comments
 (0)