test(accordion): nav clavier ArrowUp + skip des sections désactivées [#MUI-37]
Ajoute aussi un commentaire sur l'hypothèse d'ordre de montage de focusSibling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -191,4 +191,34 @@ describe('MalioAccordion — defaultOpen, disabled & clavier', () => {
|
|||||||
wrapper.unmount()
|
wrapper.unmount()
|
||||||
root.remove()
|
root.remove()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('moves focus to the previous header on ArrowUp', async () => {
|
||||||
|
const root = document.createElement('div')
|
||||||
|
document.body.appendChild(root)
|
||||||
|
const wrapper = mountAccordion({}, TWO_ITEMS, root)
|
||||||
|
const headers = wrapper.findAll('button[aria-expanded]')
|
||||||
|
;(headers[1].element as HTMLElement).focus()
|
||||||
|
await headers[1].trigger('keydown', {key: 'ArrowUp'})
|
||||||
|
expect(document.activeElement).toBe(headers[0].element)
|
||||||
|
wrapper.unmount()
|
||||||
|
root.remove()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('skips disabled headers during keyboard navigation', async () => {
|
||||||
|
const root = document.createElement('div')
|
||||||
|
document.body.appendChild(root)
|
||||||
|
const slot = `
|
||||||
|
<MalioAccordionItem title="A" value="a"><p>A</p></MalioAccordionItem>
|
||||||
|
<MalioAccordionItem title="B" value="b" :disabled="true"><p>B</p></MalioAccordionItem>
|
||||||
|
<MalioAccordionItem title="C" value="c"><p>C</p></MalioAccordionItem>
|
||||||
|
`
|
||||||
|
const wrapper = mountAccordion({}, slot, root)
|
||||||
|
const headers = wrapper.findAll('button[aria-expanded]')
|
||||||
|
;(headers[0].element as HTMLElement).focus()
|
||||||
|
await headers[0].trigger('keydown', {key: 'ArrowDown'})
|
||||||
|
// saute le header désactivé (B) pour aller directement à C
|
||||||
|
expect(document.activeElement).toBe(headers[2].element)
|
||||||
|
wrapper.unmount()
|
||||||
|
root.remove()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -81,6 +81,10 @@ function unregister(value: string) {
|
|||||||
items.value = items.value.filter(i => i.value !== value)
|
items.value = items.value.filter(i => i.value !== value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `items` est ordonné par ordre de montage (= ordre du DOM pour des sections
|
||||||
|
// statiques/ajoutées en fin). Si un consommateur réordonne dynamiquement les
|
||||||
|
// items, cet ordre peut diverger de l'ordre visuel ; trier par position DOM
|
||||||
|
// serait alors nécessaire (hors périmètre v1).
|
||||||
function focusSibling(value: string, offset: 1 | -1) {
|
function focusSibling(value: string, offset: 1 | -1) {
|
||||||
const enabled = items.value.filter(i => !i.isDisabled())
|
const enabled = items.value.filter(i => !i.isDisabled())
|
||||||
const idx = enabled.findIndex(i => i.value === value)
|
const idx = enabled.findIndex(i => i.value === value)
|
||||||
|
|||||||
Reference in New Issue
Block a user