Skip to content

Commit c40b16e

Browse files
committed
handled printable keys
1 parent 0a06d3e commit c40b16e

File tree

1 file changed

+47
-33
lines changed

1 file changed

+47
-33
lines changed

src/use-dropdown-menu.ts

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -140,49 +140,63 @@ export default function useDropdownMenu(itemCount: number): DropdownMenuResponse
140140
// Destructure the key property from the event object
141141
const { key } = e;
142142

143-
// Ignore keys that we shouldn't handle
144-
if (!['Tab', 'Shift', 'Enter', 'Escape', 'ArrowUp', 'ArrowDown', ' '].includes(key)) {
145-
return;
146-
}
143+
// Handle keyboard controls
144+
if (['Tab', 'Shift', 'Enter', 'Escape', 'ArrowUp', 'ArrowDown', ' '].includes(key)) {
145+
// Create mutable value that initializes as the currentFocusIndex value
146+
let newFocusIndex = currentFocusIndex.current;
147147

148-
// Create mutable value that initializes as the currentFocusIndex value
149-
let newFocusIndex = currentFocusIndex.current;
148+
// Controls whether the menu is open or closed, if the button should regain focus on close, and if a handler function should be called
149+
if (key === 'Escape') {
150+
setIsOpen(false);
151+
buttonRef.current?.focus();
152+
return;
153+
} else if (key === 'Tab') {
154+
setIsOpen(false);
155+
return;
156+
} else if (key === 'Enter' || key === ' ') {
157+
if (!e.currentTarget.href) {
158+
e.currentTarget.click();
159+
}
150160

151-
// Controls whether the menu is open or closed, if the button should regain focus on close, and if a handler function should be called
152-
if (key === 'Escape') {
153-
setIsOpen(false);
154-
buttonRef.current?.focus();
155-
return;
156-
} else if (key === 'Tab') {
157-
setIsOpen(false);
158-
return;
159-
} else if (key === 'Enter' || key === ' ') {
160-
if (!e.currentTarget.href) {
161-
e.currentTarget.click();
161+
setIsOpen(false);
162+
return;
162163
}
163164

164-
setIsOpen(false);
165-
return;
166-
}
165+
// Controls the current index to focus
166+
if (newFocusIndex !== null) {
167+
if (key === 'ArrowUp') {
168+
newFocusIndex -= 1;
169+
} else if (key === 'ArrowDown') {
170+
newFocusIndex += 1;
171+
}
167172

168-
// Controls the current index to focus
169-
if (newFocusIndex !== null) {
170-
if (key === 'ArrowUp') {
171-
newFocusIndex -= 1;
172-
} else if (key === 'ArrowDown') {
173-
newFocusIndex += 1;
173+
if (newFocusIndex > itemRefs.length - 1) {
174+
newFocusIndex = 0;
175+
} else if (newFocusIndex < 0) {
176+
newFocusIndex = itemRefs.length - 1;
177+
}
174178
}
175179

176-
if (newFocusIndex > itemRefs.length - 1) {
177-
newFocusIndex = 0;
178-
} else if (newFocusIndex < 0) {
179-
newFocusIndex = itemRefs.length - 1;
180+
// After any modification set state to the modified value
181+
if (newFocusIndex !== null) {
182+
moveFocus(newFocusIndex);
180183
}
184+
185+
return;
181186
}
182187

183-
// After any modification set state to the modified value
184-
if (newFocusIndex !== null) {
185-
moveFocus(newFocusIndex);
188+
// Handle printable keys
189+
if (/[a-zA-Z0-9./<>?;:"'`!@#$%^&*()\\[\]{}_+=|\\-~,]/.test(key)) {
190+
const index = itemRefs.findIndex(
191+
(ref) =>
192+
ref.current?.innerText?.toLowerCase().startsWith(key.toLowerCase()) ||
193+
ref.current?.textContent?.toLowerCase().startsWith(key.toLowerCase()) ||
194+
ref.current?.getAttribute('aria-label')?.toLowerCase().startsWith(key.toLowerCase())
195+
);
196+
197+
if (index !== -1) {
198+
moveFocus(index);
199+
}
186200
}
187201
};
188202

0 commit comments

Comments
 (0)