Skip to content

Commit d99d68c

Browse files
committed
Add nested menu support
1 parent 3b65d05 commit d99d68c

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

focus-group.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ function getItems(target, group) {
3030
return group.querySelectorAll(`[role=${target.role}]`)
3131
}
3232

33+
function filterNested(allItems, group) {
34+
return Array.from(allItems).filter(item => {
35+
let current = item.parentElement
36+
while (current && current !== group) {
37+
if (current.getAttribute('aria-hidden') === 'true') {
38+
return false
39+
}
40+
current = current.parentElement
41+
}
42+
return true
43+
})
44+
}
45+
3346
function getToolbarItems(group) {
3447
let items = [...group.querySelectorAll('*')]
3548
return items.filter(item => {
@@ -65,7 +78,8 @@ export function focusGroupKeyUX(options) {
6578
return
6679
}
6780

68-
let items = getItems(event.target, group)
81+
let allItems = getItems(event.target, group)
82+
let items = filterNested(allItems, group)
6983
let index = Array.from(items).indexOf(event.target)
7084

7185
let nextKey = 'ArrowDown'
@@ -100,7 +114,7 @@ export function focusGroupKeyUX(options) {
100114
}
101115
lastTyped = event.timeStamp
102116

103-
let found = Array.from(items).find(item => {
117+
let found = Array.from(allItems).find(item => {
104118
return item.textContent
105119
?.trim()
106120
?.toLowerCase()

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"import": {
8686
"./index.js": "{ startKeyUX, hotkeyKeyUX, pressKeyUX, focusGroupKeyUX, jumpKeyUX, hiddenKeyUX, likelyWithKeyboard, getHotKeyHint, hotkeyOverrides, hotkeyMacCompat }"
8787
},
88-
"limit": "2210 B"
88+
"limit": "2268 B"
8989
}
9090
],
9191
"clean-publish": {

test/focus-group.test.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import { equal } from 'node:assert'
33
import { describe, test } from 'node:test'
44
import { setTimeout } from 'node:timers/promises'
55

6-
import { focusGroupKeyUX, hotkeyKeyUX, startKeyUX } from '../index.js'
6+
import {
7+
focusGroupKeyUX,
8+
hotkeyKeyUX,
9+
jumpKeyUX,
10+
startKeyUX
11+
} from '../index.js'
712
import { press } from './utils.js'
813

914
describe('focus-group', () => {
@@ -457,4 +462,41 @@ describe('focus-group', () => {
457462
press(window, 'ArrowRight')
458463
equal(window.document.activeElement, buttons[0])
459464
})
465+
466+
test('supports nested menu', async () => {
467+
let window = new JSDOM().window
468+
startKeyUX(window, [focusGroupKeyUX(), jumpKeyUX()])
469+
470+
window.document.body.innerHTML =
471+
'<nav role="menu">' +
472+
'<button role="menuitem" aria-controls="nested">1</button>' +
473+
'<div role="menu" id="nested" aria-hidden="true">' +
474+
'<button role="menuitem">1.1</button>' +
475+
'<button role="menuitem">1.2</button>' +
476+
'</div>' +
477+
'<button role="menuitem">2</button>' +
478+
'</nav>'
479+
let items = window.document.querySelectorAll('button')
480+
items[0].focus()
481+
equal(window.document.activeElement?.textContent, '1')
482+
483+
press(window, 'ArrowDown')
484+
equal(window.document.activeElement?.textContent, '2')
485+
486+
press(window, 'ArrowUp')
487+
equal(window.document.activeElement?.textContent, '1')
488+
489+
press(window, 'Enter')
490+
await setTimeout(100)
491+
equal(window.document.activeElement?.textContent, '1.1')
492+
493+
press(window, 'ArrowDown')
494+
equal(window.document.activeElement?.textContent, '1.2')
495+
496+
press(window, 'ArrowDown')
497+
equal(window.document.activeElement?.textContent, '1.1')
498+
499+
press(window, 'Escape')
500+
equal(window.document.activeElement?.textContent, '1')
501+
})
460502
})

0 commit comments

Comments
 (0)