From deec10e7d5b373b56d7cf0c0fcdb7a9f9fc7b02e Mon Sep 17 00:00:00 2001 From: Ovgodd Date: Tue, 1 Sep 2026 11:59:33 +0200 Subject: [PATCH] =?UTF-8?q?fixup!=20=E2=99=BB=EF=B8=8F(frontend)=20refacto?= =?UTF-8?q?r=20screen=20share=20zoom=20pan=20with=20useMove=20and=20impera?= =?UTF-8?q?tive=20DOM=20updates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ScreenShareZoomControls.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/frontend/src/features/rooms/livekit/components/ScreenShareZoomControls.tsx b/src/frontend/src/features/rooms/livekit/components/ScreenShareZoomControls.tsx index 1f8dd1be..7cb35142 100644 --- a/src/frontend/src/features/rooms/livekit/components/ScreenShareZoomControls.tsx +++ b/src/frontend/src/features/rooms/livekit/components/ScreenShareZoomControls.tsx @@ -38,6 +38,9 @@ export const ScreenShareZoomControls = ({ const { t } = useTranslation('rooms', { keyPrefix: 'screenShareZoom' }) const announce = useScreenReaderAnnounce() + const zoomInButtonRef = useRef(null) + const hadFocusInCollapsibleRef = useRef(false) + const [isFullscreen, setIsFullscreen] = useState(false) // Tracks whether this tile's container triggered fullscreen (vs another share's). const wasThisTileFullscreen = useRef(false) @@ -63,6 +66,15 @@ export const ScreenShareZoomControls = ({ return () => document.removeEventListener('fullscreenchange', onChange) }, [announce, t, containerRef]) + // Back at 100 % the collapsible controls are disabled and hidden, which drops + // keyboard focus on the body. Hand it to the zoom in button instead, the only + // control of that group still reachable. + useEffect(() => { + if (isZoomed || !hadFocusInCollapsibleRef.current) return + hadFocusInCollapsibleRef.current = false + zoomInButtonRef.current?.focus() + }, [isZoomed]) + const toggleFullScreen = useCallback(async () => { try { if (document.fullscreenElement === containerRef.current) { @@ -123,6 +135,14 @@ export const ScreenShareZoomControls = ({ opacity: isZoomed ? 1 : 0, }} aria-hidden={!isZoomed} + onFocus={() => { + hadFocusInCollapsibleRef.current = true + }} + onBlur={(e) => { + // Disabling a focused button blurs it with no relatedTarget, so the + // flag must survive that case for the effect above to rescue focus. + if (e.relatedTarget) hadFocusInCollapsibleRef.current = false + }} >