/* eslint-disable jsx-a11y/no-static-element-interactions */ import type { RefObject } from 'react' import React, { useEffect } from 'react' import { useRovingTabIndex } from '../react-roving-tabindex' import { useMergeRefs } from '../utils/refs' function findFocusable(container: HTMLDivElement | null) { if (!container) { return null } const item = container.querySelector('[tabindex="-1"]') return item == null ? null : (item as HTMLElement) } export type ToolbarItemBridgeProps = { children?: React.ReactNode } /** * This component is meant to be used with a Dovetail component. * It provides a bridge between the dovetail component and the single tab * stop navigation provided in the NavigationBar. When using this component, * be sure to pass `singleTabStop: true` to the render method of the * Dovetail component if required. * * **Important:** The nested component (likely a button) must have a tabindex="-1" * for this to properly forward and manage focus state. It must also be the first * item with tabindex="-1" nested within the bridge. * * You can either render the dovetail container as a child of this component * or by using the ref to wire it up. * * Here is an example that uses the ref: * * ```tsx * const MainNavigation = () => { * const ref = useRef(null) * React.useEffect(() => { * const notificationComponent = lib.components.Notification({ * element: ref.current, * }) * notificationComponent.render({ * platformaAuthTokenClosure, * singleTabStop: true, * }) * return () => { * notificationComponent.unmount() * } * }, []) * * return ( * }> * *
Example Application
*
* * * *
* ) * } * ``` */ export const ToolbarItemBridge = React.forwardRef< HTMLDivElement, ToolbarItemBridgeProps >(function ToolbarItemBridgeImpl({ children }, forwardedRef) { const ref = React.useRef(null) const mergedRef = useMergeRefs([ref, forwardedRef]) const [tabIndex, focused, handleKeyDown, handleClick] = useRovingTabIndex( ref as RefObject, false ) const handleFocus = React.useCallback(() => { const item = findFocusable(ref.current) item?.focus() }, []) useEffect(() => { if (focused) { handleFocus() } }, [focused, handleFocus]) return (
{children}
) })