Skip to content

Commit 87a8137

Browse files
authored
fix(hooks): do not highlight disabled items on menu open (#1587)
1 parent 57981b2 commit 87a8137

File tree

3 files changed

+145
-6
lines changed

3 files changed

+145
-6
lines changed

src/hooks/useCombobox/__tests__/props.test.js

+65
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,71 @@ describe('props', () => {
334334
expect(input).toHaveAttribute('aria-activedescendant', expectedItemId)
335335
})
336336

337+
test('initialHighlightedIndex is ignored if item is disabled', async () => {
338+
const initialHighlightedIndex = 2
339+
renderCombobox({
340+
initialHighlightedIndex,
341+
isItemDisabled(item) {
342+
return items.indexOf(item) === initialHighlightedIndex
343+
},
344+
})
345+
346+
await clickOnInput()
347+
348+
expect(getInput()).toHaveAttribute('aria-activedescendant', '')
349+
})
350+
351+
test('initialHighlightedIndex is ignored and defaultHighlightedIndex is chosen if enabled', async () => {
352+
const initialHighlightedIndex = 0
353+
const defaultHighlightedIndex = 2
354+
renderCombobox({
355+
initialHighlightedIndex,
356+
defaultHighlightedIndex,
357+
isItemDisabled(item) {
358+
return items.indexOf(item) === initialHighlightedIndex
359+
},
360+
})
361+
362+
await clickOnInput()
363+
364+
expect(getInput()).toHaveAttribute(
365+
'aria-activedescendant',
366+
defaultIds.getItemId(defaultHighlightedIndex),
367+
)
368+
})
369+
370+
test('defaultHighlightedIndex is ignored if item is disabled', async () => {
371+
const defaultHighlightedIndex = 2
372+
renderCombobox({
373+
defaultHighlightedIndex,
374+
isItemDisabled(item) {
375+
return items.indexOf(item) === defaultHighlightedIndex
376+
},
377+
})
378+
379+
await clickOnInput()
380+
381+
expect(getInput()).toHaveAttribute('aria-activedescendant', '')
382+
})
383+
384+
test('both defaultHighlightedIndex and initialHighlightedIndex are ignored if items are disabled', async () => {
385+
const initialHighlightedIndex = 0
386+
const defaultHighlightedIndex = 2
387+
renderCombobox({
388+
initialHighlightedIndex,
389+
defaultHighlightedIndex,
390+
isItemDisabled(item) {
391+
return [initialHighlightedIndex, defaultHighlightedIndex].includes(
392+
items.indexOf(item),
393+
)
394+
},
395+
})
396+
397+
await clickOnInput()
398+
399+
expect(getInput()).toHaveAttribute('aria-activedescendant', '')
400+
})
401+
337402
describe('inputValue', () => {
338403
test('controls the state property if passed', async () => {
339404
renderCombobox({isOpen: true, inputValue: 'Dohn Joe'})

src/hooks/useSelect/__tests__/props.test.js

+67-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ describe('props', () => {
9999
inputValue: 'h',
100100
highlightedIndex: 15,
101101
isOpen: true,
102-
selectedItem: null
102+
selectedItem: null,
103103
})
104104
expect(getA11yStatusMessage).toHaveBeenCalledTimes(1)
105105

@@ -234,7 +234,72 @@ describe('props', () => {
234234
}
235235
})
236236

237-
test('controls the state property if passed', async () => {
237+
test('initialHighlightedIndex is ignored if item is disabled', async () => {
238+
const initialHighlightedIndex = 2
239+
renderSelect({
240+
initialHighlightedIndex,
241+
isItemDisabled(item) {
242+
return items.indexOf(item) === initialHighlightedIndex
243+
},
244+
})
245+
246+
await clickOnToggleButton()
247+
248+
expect(getToggleButton()).toHaveAttribute('aria-activedescendant', '')
249+
})
250+
251+
test('initialHighlightedIndex is ignored and defaultHighlightedIndex is chosen if enabled', async () => {
252+
const initialHighlightedIndex = 0
253+
const defaultHighlightedIndex = 2
254+
renderSelect({
255+
initialHighlightedIndex,
256+
defaultHighlightedIndex,
257+
isItemDisabled(item) {
258+
return items.indexOf(item) === initialHighlightedIndex
259+
},
260+
})
261+
262+
await clickOnToggleButton()
263+
264+
expect(getToggleButton()).toHaveAttribute(
265+
'aria-activedescendant',
266+
defaultIds.getItemId(defaultHighlightedIndex),
267+
)
268+
})
269+
270+
test('defaultHighlightedIndex is ignored if item is disabled', async () => {
271+
const defaultHighlightedIndex = 2
272+
renderSelect({
273+
defaultHighlightedIndex,
274+
isItemDisabled(item) {
275+
return items.indexOf(item) === defaultHighlightedIndex
276+
},
277+
})
278+
279+
await clickOnToggleButton()
280+
281+
expect(getToggleButton()).toHaveAttribute('aria-activedescendant', '')
282+
})
283+
284+
test('both defaultHighlightedIndex and initialHighlightedIndex are ignored if items are disabled', async () => {
285+
const initialHighlightedIndex = 0
286+
const defaultHighlightedIndex = 2
287+
renderSelect({
288+
initialHighlightedIndex,
289+
defaultHighlightedIndex,
290+
isItemDisabled(item) {
291+
return [initialHighlightedIndex, defaultHighlightedIndex].includes(
292+
items.indexOf(item),
293+
)
294+
},
295+
})
296+
297+
await clickOnToggleButton()
298+
299+
expect(getToggleButton()).toHaveAttribute('aria-activedescendant', '')
300+
})
301+
302+
test('isOpen controls the state property if passed', async () => {
238303
renderSelect({isOpen: true})
239304
expect(getItems()).toHaveLength(items.length)
240305
await tab() // focus toggle button

src/hooks/utils.js

+13-4
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,13 @@ function getInitialState(props) {
310310
}
311311

312312
function getHighlightedIndexOnOpen(props, state, offset) {
313-
const {items, initialHighlightedIndex, defaultHighlightedIndex, itemToKey} =
314-
props
313+
const {
314+
items,
315+
initialHighlightedIndex,
316+
defaultHighlightedIndex,
317+
isItemDisabled,
318+
itemToKey,
319+
} = props
315320
const {selectedItem, highlightedIndex} = state
316321

317322
if (items.length === 0) {
@@ -321,11 +326,15 @@ function getHighlightedIndexOnOpen(props, state, offset) {
321326
// initialHighlightedIndex will give value to highlightedIndex on initial state only.
322327
if (
323328
initialHighlightedIndex !== undefined &&
324-
highlightedIndex === initialHighlightedIndex
329+
highlightedIndex === initialHighlightedIndex &&
330+
!isItemDisabled(items[initialHighlightedIndex])
325331
) {
326332
return initialHighlightedIndex
327333
}
328-
if (defaultHighlightedIndex !== undefined) {
334+
if (
335+
defaultHighlightedIndex !== undefined &&
336+
!isItemDisabled(items[defaultHighlightedIndex])
337+
) {
329338
return defaultHighlightedIndex
330339
}
331340
if (selectedItem) {

0 commit comments

Comments
 (0)