Skip to content

Commit

Permalink
fix(useCombobox): tab to body should select element (#1517)
Browse files Browse the repository at this point in the history
  • Loading branch information
silviuaavram authored Jul 12, 2023
1 parent 0d0bc32 commit 1730fbe
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 14 deletions.
48 changes: 41 additions & 7 deletions src/hooks/useCombobox/__tests__/getInputProps.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ describe('getInputProps', () => {
})

describe('on blur', () => {
test('the open menu will be closed and highlighted item will be selected', async () => {
test('by tab the open menu will be closed and highlighted item will be selected', async () => {
const initialHighlightedIndex = 2
renderCombobox({
initialIsOpen: true,
Expand All @@ -1366,7 +1366,7 @@ describe('getInputProps', () => {
expect(getInput()).toHaveValue(items[initialHighlightedIndex])
})

test('the open menu will be closed and highlighted item will not be selected if the highlight by mouse leaves the menu', async () => {
test('by tab the open menu will be closed and highlighted item will not be selected if the highlight by mouse leaves the menu', async () => {
const initialHighlightedIndex = 2
renderCombobox({
initialIsOpen: true,
Expand All @@ -1381,7 +1381,7 @@ describe('getInputProps', () => {
expect(getInput()).toHaveValue('')
})

test('the value in the input will stay the same', async () => {
test('by tab the value in the input will stay the same', async () => {
const inputValue = 'test me'
renderCombobox({
initialIsOpen: true,
Expand Down Expand Up @@ -1470,17 +1470,51 @@ describe('getInputProps', () => {
)
})

test('the open menu will be closed and highlighted item will not be selected if the blur event related target is null', () => {
test('from the last element in the tab order, the open menu will be closed and highlighted item will be selected', () => {
const stateReducer = jest.fn().mockImplementation(s => s)
const {container} = renderCombobox({
renderCombobox({
isOpen: true,
highlightedIndex: 0,
stateReducer,
})

// tab from the last element in the tab order ends up on the body.
const body = {}
const actualBody = document.body
global.document = {...document, activeElement: body, body}
fireEvent.blur(getInput(), {relatedTarget: null}) // and also has relatedTarget: null, like when blur is performed by tab change

expect(stateReducer).toHaveBeenCalledTimes(1)
expect(stateReducer).toHaveBeenCalledWith(
{
highlightedIndex: 0,
inputValue: '',
isOpen: true,
selectedItem: null,
},
expect.objectContaining({
type: stateChangeTypes.InputBlur,
changes: {
highlightedIndex: -1,
inputValue: '',
isOpen: false,
selectedItem: null,
},
}),
)
global.document = {...document, body: actualBody}
})

test('by tab change the open menu will be closed and highlighted item will not be selected', () => {
const stateReducer = jest.fn().mockImplementation(s => s)
renderCombobox({
isOpen: true,
highlightedIndex: 0,
stateReducer,
})
const input = getInput()
document.body.appendChild(container)

fireEvent.blur(input, {relatedTarget: null})
fireEvent.blur(input, {relatedTarget: null}) // to simulate blur by tab change

expect(stateReducer).toHaveBeenCalledTimes(1)
expect(stateReducer).toHaveBeenCalledWith(
Expand Down
20 changes: 13 additions & 7 deletions src/hooks/useCombobox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,10 @@ function useCombobox(userProps = {}) {
'Pass either item or index to getItemProps!',
)

const onSelectKey = isReactNative || isReactNativeWeb
? /* istanbul ignore next (react-native) */ 'onPress'
: 'onClick'
const onSelectKey =
isReactNative || isReactNativeWeb
? /* istanbul ignore next (react-native) */ 'onPress'
: 'onClick'
const customClickHandler = isReactNative
? /* istanbul ignore next (react-native) */ onPress
: onClick
Expand Down Expand Up @@ -412,9 +413,10 @@ function useCombobox(userProps = {}) {
const inputHandleChange = event => {
dispatch({
type: stateChangeTypes.InputChange,
inputValue: isReactNative || isReactNativeWeb
? /* istanbul ignore next (react-native) */ event.nativeEvent.text
: event.target.value,
inputValue:
isReactNative || isReactNativeWeb
? /* istanbul ignore next (react-native) */ event.nativeEvent.text
: event.target.value,
})
}
const inputHandleBlur = event => {
Expand All @@ -423,9 +425,13 @@ function useCombobox(userProps = {}) {
latestState.isOpen &&
!mouseAndTouchTrackersRef.current.isMouseDown
) {
const isBlurByTabChange =
event.relatedTarget === null &&
environment.document.activeElement !== environment.document.body

dispatch({
type: stateChangeTypes.InputBlur,
selectItem: event.relatedTarget !== null,
selectItem: !isBlurByTabChange,
})
}
}
Expand Down

0 comments on commit 1730fbe

Please sign in to comment.