From 82c9851db2ae4a0602d1b6ab56a638778b597894 Mon Sep 17 00:00:00 2001 From: cyber_stanny Date: Wed, 18 Feb 2026 21:49:31 +0800 Subject: [PATCH] feat: add keyboard shortcuts help dialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a keyboard shortcuts help dialog accessible from the sidebar. - Shows available shortcuts with visual key representations - Accessible via 'Shortcuts' button in sidebar footer - Adapts key display for Mac (⌘) vs Windows/Linux (Ctrl) Closes # --- .../screens/chat/components/chat-sidebar.tsx | 41 ++++++ .../components/keyboard-shortcuts-dialog.tsx | 124 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 apps/webclaw/src/screens/chat/components/keyboard-shortcuts-dialog.tsx diff --git a/apps/webclaw/src/screens/chat/components/chat-sidebar.tsx b/apps/webclaw/src/screens/chat/components/chat-sidebar.tsx index 58f5d7a..d184b27 100644 --- a/apps/webclaw/src/screens/chat/components/chat-sidebar.tsx +++ b/apps/webclaw/src/screens/chat/components/chat-sidebar.tsx @@ -1,6 +1,7 @@ import { HugeiconsIcon } from '@hugeicons/react' import { PencilEdit02Icon, + QuestionMarkIcon, Search01Icon, Settings01Icon, SidebarLeft01Icon, @@ -13,6 +14,7 @@ import { useDeleteSession } from '../hooks/use-delete-session' import { useRenameSession } from '../hooks/use-rename-session' import { useSessionShortcuts } from '../hooks/use-session-shortcuts' import { SettingsDialog } from './settings-dialog' +import { KeyboardShortcutsDialog } from './keyboard-shortcuts-dialog' import { SessionRenameDialog } from './sidebar/session-rename-dialog' import { SessionDeleteDialog } from './sidebar/session-delete-dialog' import { SidebarSessions } from './sidebar/sidebar-sessions' @@ -76,6 +78,7 @@ function ChatSidebarComponent({ const [deleteFriendlyId, setDeleteFriendlyId] = useState(null) const [deleteSessionTitle, setDeleteSessionTitle] = useState('') const [searchDialogOpen, setSearchDialogOpen] = useState(false) + const [shortcutsDialogOpen, setShortcutsDialogOpen] = useState(false) const navigate = useNavigate() useSessionShortcuts({ @@ -344,6 +347,39 @@ function ChatSidebarComponent({ + + + + + + description: string + icon?: typeof CommandIcon +} + +const SHORTCUTS: Array = [ + { + keys: ['Mod', 'K'], + description: 'Search sessions', + icon: Search01Icon, + }, + { + keys: ['Mod', 'Shift', 'O'], + description: 'Create new session', + icon: Add01Icon, + }, +] + +type KeyboardShortcutsDialogProps = { + open: boolean + onOpenChange: (open: boolean) => void +} + +function formatKey(key: string): string { + if (key === 'Mod') { + return typeof navigator !== 'undefined' && navigator.platform.includes('Mac') + ? '⌘' + : 'Ctrl' + } + return key +} + +export function KeyboardShortcutsDialog({ + open, + onOpenChange, +}: KeyboardShortcutsDialogProps) { + return ( + + +
+ + + Keyboard Shortcuts + + + + +
+ + + List of available keyboard shortcuts for WebClaw + + +
+
+ {SHORTCUTS.map((shortcut, index) => ( +
+
+ {shortcut.icon && ( + + )} + + {shortcut.description} + +
+
+ {shortcut.keys.map((key, keyIndex) => ( + + + {formatKey(key)} + + {keyIndex < shortcut.keys.length - 1 && ( + + + )} + + ))} +
+
+ ))} +
+
+ +
+

+ Press ? anytime to show this dialog +

+
+
+
+ ) +}