Skip to content

Commit 30fb517

Browse files
authored
fix: allow internal tabbing in dropdown menu (#939)
* fix: allow internal tabbing in dropdown menu * Update src/Dropdown.tsx
1 parent 0fb5e57 commit 30fb517

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

src/Dropdown.tsx

+22-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import matches from 'dom-helpers/matches';
22
import qsa from 'dom-helpers/querySelectorAll';
3+
import addEventListener from 'dom-helpers/addEventListener';
34
import React, { useCallback, useRef, useEffect, useMemo } from 'react';
45
import PropTypes from 'prop-types';
56
import { useUncontrolledProp } from 'uncontrollable';
@@ -266,12 +267,28 @@ function Dropdown({
266267
if (next && next.focus) next.focus();
267268
}
268269
return;
269-
case 'Escape':
270270
case 'Tab':
271-
if (key === 'Escape') {
272-
event.preventDefault();
273-
event.stopPropagation();
274-
}
271+
// on keydown the target is the element being tabbed FROM, we need that
272+
// to know if this event is relevant to this dropdown (e.g. in this menu).
273+
// On `keyup` the target is the element being tagged TO which we use to check
274+
// if focus has left the menu
275+
addEventListener(
276+
document as any,
277+
'keyup',
278+
(e) => {
279+
if (
280+
(e.key === 'Tab' && !e.target) ||
281+
!menuRef.current!.contains(e.target as HTMLElement)
282+
) {
283+
onToggle(false, event);
284+
}
285+
},
286+
{ once: true },
287+
);
288+
break;
289+
case 'Escape':
290+
event.preventDefault();
291+
event.stopPropagation();
275292

276293
onToggle(false, event);
277294
break;

test/DropdownSpec.js

+3
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@ describe('<Dropdown>', () => {
324324
key: 'Tab',
325325
});
326326

327+
simulant.fire(document, 'keyup', {
328+
key: 'Tab',
329+
});
327330
toggle.getAttribute('aria-expanded').should.equal('false');
328331

329332
// simulating a tab event doesn't actually shift focus.

0 commit comments

Comments
 (0)