From 4fbcf8d64ee7e7b9c66935b786472bb2c683b5fa Mon Sep 17 00:00:00 2001 From: Cyril Date: Thu, 15 Jan 2026 11:18:09 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20add=20auto=20refocus=20fo?= =?UTF-8?q?r=20effects=20menu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore focus to options button on close, focus first element on open --- .../rooms/livekit/components/SidePanel.tsx | 2 +- .../livekit/components/effects/Effects.tsx | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx index e10bc126..4f08eb83 100644 --- a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx +++ b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx @@ -169,7 +169,7 @@ export const SidePanel = () => { - + diff --git a/src/frontend/src/features/rooms/livekit/components/effects/Effects.tsx b/src/frontend/src/features/rooms/livekit/components/effects/Effects.tsx index 0fe7a432..c6989520 100644 --- a/src/frontend/src/features/rooms/livekit/components/effects/Effects.tsx +++ b/src/frontend/src/features/rooms/livekit/components/effects/Effects.tsx @@ -5,14 +5,41 @@ import { EffectsConfiguration } from './EffectsConfiguration' import { usePersistentUserChoices } from '../../hooks/usePersistentUserChoices' import { useCanPublishTrack } from '@/features/rooms/livekit/hooks/useCanPublishTrack' import { TrackSource } from '@livekit/protocol' +import { useSidePanel } from '../../hooks/useSidePanel' +import { useRestoreFocus } from '@/hooks/useRestoreFocus' export const Effects = () => { const { cameraTrack } = useLocalParticipant() const localCameraTrack = cameraTrack?.track as LocalVideoTrack const { saveProcessorSerialized } = usePersistentUserChoices() + const { isEffectsOpen } = useSidePanel() const canPublishCamera = useCanPublishTrack(TrackSource.CAMERA) + useRestoreFocus(isEffectsOpen, { + resolveTrigger: (activeEl) => { + if (activeEl?.tagName === 'DIV') { + return document.querySelector('#room-options-trigger') + } + // For direct button clicks, use the active element as is + return activeEl + }, + // Focus the first focusable element when the panel opens + onOpened: () => { + requestAnimationFrame(() => { + // Find the first toggle button (blur light button) + const firstButton = document.querySelector( + '[data-attr="toggle-blur-light"]' + ) + if (firstButton) { + firstButton.focus({ preventScroll: true }) + } + }) + }, + restoreFocusRaf: true, + preventScroll: true, + }) + return (