Skip to content

Commit

Permalink
Merge pull request #66 from i-like-robots/focus-root
Browse files Browse the repository at this point in the history
Switch cursor focus to root after removing a tag with focus
  • Loading branch information
i-like-robots authored Feb 14, 2024
2 parents 9bcf004 + e9b9456 commit 528b278
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 8 deletions.
2 changes: 2 additions & 0 deletions src/components/ReactTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ function ReactTags(
const comboBoxRef = useRef<HTMLDivElement>(null)
const inputRef = useRef<HTMLInputElement>(null)
const listBoxRef = useRef<HTMLDivElement>(null)
const rootRef = useRef<HTMLDivElement>(null)

const managerRef = useManager({
activateFirstOption,
Expand Down Expand Up @@ -194,6 +195,7 @@ function ReactTags(
isInvalid,
listBoxRef,
managerRef,
rootRef,
}}
>
<Root onBlur={onBlur} onFocus={onFocus} render={renderRoot}>
Expand Down
1 change: 1 addition & 0 deletions src/contexts/GlobalContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type GlobalContextValue = {
isInvalid: boolean
listBoxRef: React.MutableRefObject<HTMLDivElement | null>
managerRef: React.MutableRefObject<UseManagerState>
rootRef: React.MutableRefObject<HTMLDivElement | null>
}

export const GlobalContext = React.createContext<GlobalContextValue | undefined>(undefined)
5 changes: 2 additions & 3 deletions src/hooks/useRoot.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useMemo, useRef, useState } from 'react'
import React, { useContext, useMemo, useState } from 'react'
import { GlobalContext } from '../contexts'
import { labelId, rootId } from '../lib'
import type { OnBlur, OnFocus } from '../sharedTypes'
Expand All @@ -15,8 +15,7 @@ export type UseRootState = {

export function useRoot({ onBlur, onFocus }: UseRootArgs): UseRootState {
const [isActive, setIsActive] = useState<boolean>(false)
const { id, inputRef } = useContext(GlobalContext)
const rootRef = useRef<HTMLDivElement>(null)
const { id, inputRef, rootRef } = useContext(GlobalContext)

const rootProps = useMemo(() => {
return {
Expand Down
8 changes: 4 additions & 4 deletions src/hooks/useTagList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ export type UseTagListState = {
}

export function useTagList(): UseTagListState {
const { inputRef, managerRef } = useContext(GlobalContext)
const { rootRef, managerRef } = useContext(GlobalContext)

const listRef = useRef<HTMLUListElement>()

const tagDeleted = managerRef.current.flags.tagsDeleted.length
const tagDeleted = managerRef.current.flags.tagsDeleted[0]
const isFocusInList = listRef.current?.contains(document.activeElement)

useLayoutEffect(() => {
if (tagDeleted) {
const isFocusInListNow = listRef.current?.contains(document.activeElement)

if (isFocusInList && !isFocusInListNow) {
inputRef.current?.focus({ preventScroll: true })
rootRef.current?.focus({ preventScroll: true })
}
}
}, [inputRef, isFocusInList, listRef, tagDeleted])
}, [isFocusInList, listRef, rootRef, tagDeleted])

return { listRef }
}
2 changes: 1 addition & 1 deletion src/test/ReactTags.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('React Tags Autocomplete', () => {

harness.rerender({ selected: harness.props.selected.slice(1) })

expect(document.activeElement).toBe(harness.input)
expect(document.activeElement).toBe(harness.root)
})
})

Expand Down

0 comments on commit 528b278

Please sign in to comment.