From 139aeda89bce9415cb8e496e8834995bad0e5101 Mon Sep 17 00:00:00 2001 From: Cyril Date: Mon, 13 Jul 2026 13:59:36 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BF=EF=B8=8F(frontend)=20close=20side=20p?= =?UTF-8?q?anel=20with=20Escape=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit useEscapeToClose: close panel on Escape, restore focus, let chat input bubble --- CHANGELOG.md | 1 + .../features/chat/components/ChatTextArea.tsx | 2 +- .../rooms/livekit/components/SidePanel.tsx | 3 +++ src/frontend/src/hooks/useEscapeToClose.ts | 26 +++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/frontend/src/hooks/useEscapeToClose.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a086cd7..f207b0d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to - ⬆️(frontend) upgrade @tanstack/react-query from 5.101.1 to 5.101.4 - ⬆️(frontend) upgrade @pandacss/preset-panda from 1.11.3 to 1.12.0 - ⬆️(frontend) upgrade posthog-js from 1.404.1 to 1.409.5 +- ♿️(frontend) close side panel with Escape key #1507 ## [1.28.0] - 2026-08-24 diff --git a/src/frontend/src/features/chat/components/ChatTextArea.tsx b/src/frontend/src/features/chat/components/ChatTextArea.tsx index d5c4fb5d..d37503f4 100644 --- a/src/frontend/src/features/chat/components/ChatTextArea.tsx +++ b/src/frontend/src/features/chat/components/ChatTextArea.tsx @@ -49,7 +49,7 @@ export const ChatTextArea = () => { const isDisabled = !textAreaValue.trim() || isSending const onKeyDown = async (e: React.KeyboardEvent) => { - e.stopPropagation() + if (e.key !== 'Escape') e.stopPropagation() if (e.key !== 'Enter' || (e.key === 'Enter' && e.shiftKey) || isDisabled) return e.preventDefault() diff --git a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx index 9936dd05..5fdcd119 100644 --- a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx +++ b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx @@ -16,6 +16,7 @@ import { Info } from './Info' import { HStack } from '@/styled-system/jsx' import { useReactionsToolbar } from '@/features/reactions/hooks/useReactionsToolbar' import { useRestoreFocus } from '@/hooks/useRestoreFocus' +import { useEscapeToClose } from '@/hooks/useEscapeToClose' type StyledSidePanelProps = { title: string @@ -194,6 +195,8 @@ export const SidePanel = () => { activeKey: activePanelId, }) + useEscapeToClose(isSidePanelOpen, asideRef, closeSidePanel) + return ( , + onClose: () => void +) => { + const onCloseRef = useRef(onClose) + useEffect(() => { + onCloseRef.current = onClose + }) + + useEffect(() => { + if (!isActive) return + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key !== 'Escape') return + if (!containerRef.current?.contains(document.activeElement)) return + e.stopPropagation() + onCloseRef.current() + } + + document.addEventListener('keydown', handleKeyDown) + return () => document.removeEventListener('keydown', handleKeyDown) + }, [isActive, containerRef]) +}