diff --git a/src/frontend/src/features/pip/components/PipView.tsx b/src/frontend/src/features/pip/components/PipView.tsx index 77e0f7b8..d73d7238 100644 --- a/src/frontend/src/features/pip/components/PipView.tsx +++ b/src/frontend/src/features/pip/components/PipView.tsx @@ -8,6 +8,7 @@ import { pipLayoutStore } from '../stores/pipLayoutStore' import { useEscapeDismiss } from '../hooks/useEscapeDismiss' import { usePipKeyboardShortcuts } from '../hooks/usePipKeyboardShortcuts' import { usePipRestoreFocus } from '../hooks/usePipRestoreFocus' +import { usePipFocusModality } from '../hooks/usePipFocusModality' import { PipControlBar } from './PipControlBar' import { PipReactionsToolbar } from './PipReactionsToolbar' import { PipStage } from './layouts/PipStage' @@ -29,6 +30,9 @@ export const PipView = () => { // Forward keyboard shortcuts (Ctrl+D, Ctrl+E, etc.) to the main store. usePipKeyboardShortcuts(containerRef) + // Sync React Aria's focus-visible modality with the PiP document. + usePipFocusModality(containerRef) + // Side panels open via a menu item that unmounts on click; fall back to the // options button so focus returns somewhere visible. const resolveTrigger = useCallback((activeEl: HTMLElement | null) => { diff --git a/src/frontend/src/features/pip/hooks/usePipFocusModality.ts b/src/frontend/src/features/pip/hooks/usePipFocusModality.ts new file mode 100644 index 00000000..8b57ef13 --- /dev/null +++ b/src/frontend/src/features/pip/hooks/usePipFocusModality.ts @@ -0,0 +1,26 @@ +import { useEffect, type RefObject } from 'react' +import { setInteractionModality } from '@react-aria/interactions' + +/** + * Sync React Aria's interaction modality with the PiP document. + * React Aria only installs keyboard/mouse listeners on the main document, + * so focus-visible rings never appear in PiP without this bridge. + */ +export const usePipFocusModality = ( + containerRef: RefObject +) => { + useEffect(() => { + const doc = containerRef.current?.ownerDocument + if (!doc || doc === document) return + + const onKeyDown = () => setInteractionModality('keyboard') + const onMouseDown = () => setInteractionModality('pointer') + + doc.addEventListener('keydown', onKeyDown, true) + doc.addEventListener('mousedown', onMouseDown, true) + return () => { + doc.removeEventListener('keydown', onKeyDown, true) + doc.removeEventListener('mousedown', onMouseDown, true) + } + }, [containerRef]) +}