UNPKG

@hakuna-matata-ui/hooks

Version:
59 lines (47 loc) 1.41 kB
import { contains, focus, FocusableElement, getActiveElement, isTabbable, } from "@hakuna-matata-ui/utils" import { RefObject } from "react" import { useUpdateEffect } from "./use-update-effect" export interface UseFocusOnHideOptions { focusRef: RefObject<FocusableElement> shouldFocus?: boolean visible?: boolean } function preventReturnFocus(containerRef: React.RefObject<HTMLElement>) { const el = containerRef.current if (!el) return false const activeElement = getActiveElement(el) if (!activeElement) return false if (contains(el, activeElement)) return false if (isTabbable(activeElement)) return true return false } /** * Popover hook to manage the focus when the popover closes or hides. * * We either want to return focus back to the popover trigger or * let focus proceed normally if user moved to another interactive * element in the viewport. */ export function useFocusOnHide( containerRef: RefObject<HTMLElement>, options: UseFocusOnHideOptions, ) { const { shouldFocus: shouldFocusProp, visible, focusRef } = options const shouldFocus = shouldFocusProp && !visible useUpdateEffect(() => { if (!shouldFocus) return if (preventReturnFocus(containerRef)) { return } const el = focusRef?.current || containerRef.current if (el) { focus(el, { nextTick: true }) } }, [shouldFocus, containerRef, focusRef]) }