From 45b939da5c2ab4d66b7334423b41e1e5d5c5004f Mon Sep 17 00:00:00 2001 From: Cyril Date: Wed, 6 May 2026 13:02:49 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BF=EF=B8=8F(frontend)=20restore=20focus-?= =?UTF-8?q?visible=20rings=20inside=20PiP=20window?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sync React Aria interaction modality with PiP keyboard and mouse events. --- .../src/features/pip/components/PipView.tsx | 4 +++ .../features/pip/hooks/usePipFocusModality.ts | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/frontend/src/features/pip/hooks/usePipFocusModality.ts 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]) +}