From 6e20bc1f439b1378992f78c0798dd6f3ee3272e4 Mon Sep 17 00:00:00 2001 From: Cyril Date: Tue, 6 Jan 2026 23:33:29 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BF=EF=B8=8F(frontend)=20restore=20focus?= =?UTF-8?q?=20to=20trigger=20button=20when=20panel=20closes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit improves keyboard navigation and accessibility consistency Signed-off-by: Cyril --- .../rooms/livekit/components/SidePanel.tsx | 2 +- .../rooms/livekit/components/Tools.tsx | 43 ++++++++++++++++++- .../controls/Options/OptionsButton.tsx | 1 + .../prefabs/ControlBar/MobileControlBar.tsx | 1 + .../prefabs/ControlBar/MoreOptions.tsx | 1 + 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx index 2c80e2fe..3ca50e6e 100644 --- a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx +++ b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx @@ -164,7 +164,7 @@ export const SidePanel = () => { - + diff --git a/src/frontend/src/features/rooms/livekit/components/Tools.tsx b/src/frontend/src/features/rooms/livekit/components/Tools.tsx index bd5cfb7a..dfdae586 100644 --- a/src/frontend/src/features/rooms/livekit/components/Tools.tsx +++ b/src/frontend/src/features/rooms/livekit/components/Tools.tsx @@ -2,7 +2,7 @@ import { A, Div, Text } from '@/primitives' import { css } from '@/styled-system/css' import { Button as RACButton } from 'react-aria-components' import { useTranslation } from 'react-i18next' -import { ReactNode } from 'react' +import { ReactNode, useEffect, useRef } from 'react' import { SubPanelId, useSidePanel } from '../hooks/useSidePanel' import { useIsRecordingModeEnabled, @@ -94,10 +94,49 @@ const ToolButton = ({ export const Tools = () => { const { data } = useConfig() - const { openTranscript, openScreenRecording, activeSubPanelId } = + const { openTranscript, openScreenRecording, activeSubPanelId, isToolsOpen } = useSidePanel() const { t } = useTranslation('rooms', { keyPrefix: 'moreTools' }) + // Restore focus to the element that opened the Tools panel + // following the same pattern as Chat. + const toolsTriggerRef = useRef(null) + const prevIsToolsOpenRef = useRef(false) + + useEffect(() => { + const wasOpen = prevIsToolsOpenRef.current + const isOpen = isToolsOpen + + // Tools just opened + if (!wasOpen && isOpen) { + const activeEl = document.activeElement as HTMLElement | null + + // If the active element is a MenuItem (DIV) that will be unmounted when the menu closes, + // find the "more options" button ("Plus d'options") that opened the menu + if (activeEl?.tagName === 'DIV') { + toolsTriggerRef.current = document.querySelector( + '#room-options-trigger' + ) + } else { + // For direct button clicks (e.g. "Plus d'outils"), use the active element as is + toolsTriggerRef.current = activeEl + } + } + + // Tools just closed + if (wasOpen && !isOpen) { + const trigger = toolsTriggerRef.current + if (trigger && document.contains(trigger)) { + requestAnimationFrame(() => { + trigger.focus({ preventScroll: true }) + }) + } + toolsTriggerRef.current = null + } + + prevIsToolsOpenRef.current = isOpen + }, [isToolsOpen]) + const isTranscriptEnabled = useIsRecordingModeEnabled( RecordingMode.Transcript ) diff --git a/src/frontend/src/features/rooms/livekit/components/controls/Options/OptionsButton.tsx b/src/frontend/src/features/rooms/livekit/components/controls/Options/OptionsButton.tsx index 5bf7d92b..715dcd30 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/Options/OptionsButton.tsx +++ b/src/frontend/src/features/rooms/livekit/components/controls/Options/OptionsButton.tsx @@ -9,6 +9,7 @@ export const OptionsButton = () => { return (