Skip to content

Commit

Permalink
fix(hooks): do not highlight disabled items on menu open (#1587)
Browse files Browse the repository at this point in the history
  • Loading branch information
silviuaavram authored Apr 2, 2024
1 parent 57981b2 commit 87a8137
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 6 deletions.
65 changes: 65 additions & 0 deletions src/hooks/useCombobox/__tests__/props.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,71 @@ describe('props', () => {
expect(input).toHaveAttribute('aria-activedescendant', expectedItemId)
})

test('initialHighlightedIndex is ignored if item is disabled', async () => {
const initialHighlightedIndex = 2
renderCombobox({
initialHighlightedIndex,
isItemDisabled(item) {
return items.indexOf(item) === initialHighlightedIndex
},
})

await clickOnInput()

expect(getInput()).toHaveAttribute('aria-activedescendant', '')
})

test('initialHighlightedIndex is ignored and defaultHighlightedIndex is chosen if enabled', async () => {
const initialHighlightedIndex = 0
const defaultHighlightedIndex = 2
renderCombobox({
initialHighlightedIndex,
defaultHighlightedIndex,
isItemDisabled(item) {
return items.indexOf(item) === initialHighlightedIndex
},
})

await clickOnInput()

expect(getInput()).toHaveAttribute(
'aria-activedescendant',
defaultIds.getItemId(defaultHighlightedIndex),
)
})

test('defaultHighlightedIndex is ignored if item is disabled', async () => {
const defaultHighlightedIndex = 2
renderCombobox({
defaultHighlightedIndex,
isItemDisabled(item) {
return items.indexOf(item) === defaultHighlightedIndex
},
})

await clickOnInput()

expect(getInput()).toHaveAttribute('aria-activedescendant', '')
})

test('both defaultHighlightedIndex and initialHighlightedIndex are ignored if items are disabled', async () => {
const initialHighlightedIndex = 0
const defaultHighlightedIndex = 2
renderCombobox({
initialHighlightedIndex,
defaultHighlightedIndex,
isItemDisabled(item) {
return [initialHighlightedIndex, defaultHighlightedIndex].includes(
items.indexOf(item),
)
},
})

await clickOnInput()

expect(getInput()).toHaveAttribute('aria-activedescendant', '')
})

describe('inputValue', () => {
test('controls the state property if passed', async () => {
renderCombobox({isOpen: true, inputValue: 'Dohn Joe'})
Expand Down
69 changes: 67 additions & 2 deletions src/hooks/useSelect/__tests__/props.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ describe('props', () => {
inputValue: 'h',
highlightedIndex: 15,
isOpen: true,
selectedItem: null
selectedItem: null,
})
expect(getA11yStatusMessage).toHaveBeenCalledTimes(1)

Expand Down Expand Up @@ -234,7 +234,72 @@ describe('props', () => {
}
})

test('controls the state property if passed', async () => {
test('initialHighlightedIndex is ignored if item is disabled', async () => {
const initialHighlightedIndex = 2
renderSelect({
initialHighlightedIndex,
isItemDisabled(item) {
return items.indexOf(item) === initialHighlightedIndex
},
})

await clickOnToggleButton()

expect(getToggleButton()).toHaveAttribute('aria-activedescendant', '')
})

test('initialHighlightedIndex is ignored and defaultHighlightedIndex is chosen if enabled', async () => {
const initialHighlightedIndex = 0
const defaultHighlightedIndex = 2
renderSelect({
initialHighlightedIndex,
defaultHighlightedIndex,
isItemDisabled(item) {
return items.indexOf(item) === initialHighlightedIndex
},
})

await clickOnToggleButton()

expect(getToggleButton()).toHaveAttribute(
'aria-activedescendant',
defaultIds.getItemId(defaultHighlightedIndex),
)
})

test('defaultHighlightedIndex is ignored if item is disabled', async () => {
const defaultHighlightedIndex = 2
renderSelect({
defaultHighlightedIndex,
isItemDisabled(item) {
return items.indexOf(item) === defaultHighlightedIndex
},
})

await clickOnToggleButton()

expect(getToggleButton()).toHaveAttribute('aria-activedescendant', '')
})

test('both defaultHighlightedIndex and initialHighlightedIndex are ignored if items are disabled', async () => {
const initialHighlightedIndex = 0
const defaultHighlightedIndex = 2
renderSelect({
initialHighlightedIndex,
defaultHighlightedIndex,
isItemDisabled(item) {
return [initialHighlightedIndex, defaultHighlightedIndex].includes(
items.indexOf(item),
)
},
})

await clickOnToggleButton()

expect(getToggleButton()).toHaveAttribute('aria-activedescendant', '')
})

test('isOpen controls the state property if passed', async () => {
renderSelect({isOpen: true})
expect(getItems()).toHaveLength(items.length)
await tab() // focus toggle button
Expand Down
17 changes: 13 additions & 4 deletions src/hooks/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,13 @@ function getInitialState(props) {
}

function getHighlightedIndexOnOpen(props, state, offset) {
const {items, initialHighlightedIndex, defaultHighlightedIndex, itemToKey} =
props
const {
items,
initialHighlightedIndex,
defaultHighlightedIndex,
isItemDisabled,
itemToKey,
} = props
const {selectedItem, highlightedIndex} = state

if (items.length === 0) {
Expand All @@ -321,11 +326,15 @@ function getHighlightedIndexOnOpen(props, state, offset) {
// initialHighlightedIndex will give value to highlightedIndex on initial state only.
if (
initialHighlightedIndex !== undefined &&
highlightedIndex === initialHighlightedIndex
highlightedIndex === initialHighlightedIndex &&
!isItemDisabled(items[initialHighlightedIndex])
) {
return initialHighlightedIndex
}
if (defaultHighlightedIndex !== undefined) {
if (
defaultHighlightedIndex !== undefined &&
!isItemDisabled(items[defaultHighlightedIndex])
) {
return defaultHighlightedIndex
}
if (selectedItem) {
Expand Down

0 comments on commit 87a8137

Please sign in to comment.