From 0b091c6c151373e8f77d18c0ac17e2c7a9346514 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Fri, 19 Dec 2025 16:48:25 +0200 Subject: [PATCH] feat(ui): improve theme consistency and add diff panel shortcut --- packages/desktop/src-tauri/Cargo.lock | 2 +- .../chat/AgentMentionAutocomplete.tsx | 4 +- .../components/chat/CommandAutocomplete.tsx | 4 +- .../chat/FileMentionAutocomplete.tsx | 4 +- .../ui/src/components/chat/ModelControls.tsx | 6 +-- .../src/components/chat/ServerFilePicker.tsx | 4 +- packages/ui/src/components/layout/Header.tsx | 38 ++++++++++++++++++- .../ui/src/components/ui/CommandPalette.tsx | 12 +++++- packages/ui/src/components/ui/HelpDialog.tsx | 5 ++- packages/ui/src/components/ui/command.tsx | 4 +- .../ui/src/components/ui/dropdown-menu.tsx | 12 +++--- packages/ui/src/components/ui/select.tsx | 6 +-- packages/ui/src/hooks/useKeyboardShortcuts.ts | 7 ++++ 13 files changed, 81 insertions(+), 27 deletions(-) diff --git a/packages/desktop/src-tauri/Cargo.lock b/packages/desktop/src-tauri/Cargo.lock index 8344b205..f9d7b8d7 100644 --- a/packages/desktop/src-tauri/Cargo.lock +++ b/packages/desktop/src-tauri/Cargo.lock @@ -2847,7 +2847,7 @@ dependencies = [ [[package]] name = "openchamber-desktop" -version = "1.2.5" +version = "1.2.6" dependencies = [ "anyhow", "axum", diff --git a/packages/ui/src/components/chat/AgentMentionAutocomplete.tsx b/packages/ui/src/components/chat/AgentMentionAutocomplete.tsx index 28279319..d1600c7a 100644 --- a/packages/ui/src/components/chat/AgentMentionAutocomplete.tsx +++ b/packages/ui/src/components/chat/AgentMentionAutocomplete.tsx @@ -109,7 +109,7 @@ export const AgentMentionAutocomplete = React.forwardRef onAgentSelect(agent.name)} onMouseEnter={() => setSelectedIndex(index)} @@ -130,7 +130,7 @@ export const AgentMentionAutocomplete = React.forwardRef {agents.length ? ( diff --git a/packages/ui/src/components/chat/CommandAutocomplete.tsx b/packages/ui/src/components/chat/CommandAutocomplete.tsx index 604ab54e..83e3d7e5 100644 --- a/packages/ui/src/components/chat/CommandAutocomplete.tsx +++ b/packages/ui/src/components/chat/CommandAutocomplete.tsx @@ -201,7 +201,7 @@ export const CommandAutocomplete = React.forwardRef {loading ? ( @@ -216,7 +216,7 @@ export const CommandAutocomplete = React.forwardRef { itemRefs.current[index] = el; }} className={cn( "flex items-start gap-2 px-3 py-2 cursor-pointer rounded-lg", - index === selectedIndex && "bg-accent" + index === selectedIndex && "bg-muted" )} onClick={() => onCommandSelect(command)} onMouseEnter={() => setSelectedIndex(index)} diff --git a/packages/ui/src/components/chat/FileMentionAutocomplete.tsx b/packages/ui/src/components/chat/FileMentionAutocomplete.tsx index efaf638d..4798b77c 100644 --- a/packages/ui/src/components/chat/FileMentionAutocomplete.tsx +++ b/packages/ui/src/components/chat/FileMentionAutocomplete.tsx @@ -234,7 +234,7 @@ export const FileMentionAutocomplete = React.forwardRef {loading ? ( @@ -255,7 +255,7 @@ export const FileMentionAutocomplete = React.forwardRef { itemRefs.current[index] = el; }} className={cn( "flex items-center gap-2 px-3 py-1.5 cursor-pointer typography-ui-label rounded-lg", - isSelected && "bg-accent" + isSelected && "bg-muted" )} onClick={() => handleFileSelect(file)} onMouseEnter={() => setSelectedIndex(index)} diff --git a/packages/ui/src/components/chat/ModelControls.tsx b/packages/ui/src/components/chat/ModelControls.tsx index d713063b..e5cd49ed 100644 --- a/packages/ui/src/components/chat/ModelControls.tsx +++ b/packages/ui/src/components/chat/ModelControls.tsx @@ -1180,7 +1180,7 @@ export const ModelControls: React.FC = ({ className }) => { className={cn( 'flex w-full items-start gap-2 border-b border-border/30 px-2 py-1.5 text-left last:border-b-0', 'focus:outline-none focus-visible:ring-1 focus-visible:ring-primary', - isSelected ? 'bg-primary/15 text-primary' : 'hover:bg-accent/40' + isSelected ? 'bg-primary/15 text-primary' : 'hover:bg-muted' )} >
@@ -1225,7 +1225,7 @@ export const ModelControls: React.FC = ({ className }) => { className={cn( 'flex w-full items-start gap-2 border-b border-border/30 px-2 py-1.5 text-left last:border-b-0', 'focus:outline-none focus-visible:ring-1 focus-visible:ring-primary', - isSelected ? 'bg-primary/15 text-primary' : 'hover:bg-accent/40' + isSelected ? 'bg-primary/15 text-primary' : 'hover:bg-muted' )} >
@@ -1309,7 +1309,7 @@ export const ModelControls: React.FC = ({ className }) => { className={cn( 'flex flex-1 min-w-0 items-start gap-2 text-left', 'focus:outline-none focus-visible:ring-1 focus-visible:ring-primary', - !isSelected && 'hover:bg-accent/40' + !isSelected && 'hover:bg-muted' )} >
diff --git a/packages/ui/src/components/chat/ServerFilePicker.tsx b/packages/ui/src/components/chat/ServerFilePicker.tsx index e8b77ef7..dc085bff 100644 --- a/packages/ui/src/components/chat/ServerFilePicker.tsx +++ b/packages/ui/src/components/chat/ServerFilePicker.tsx @@ -361,7 +361,7 @@ export const ServerFilePicker: React.FC = ({ const row = (
= ({ e.stopPropagation(); setSearchQuery(''); }} - className="absolute right-2 top-1/2 -translate-y-1/2 p-0.5 hover:bg-accent rounded" + className="absolute right-2 top-1/2 -translate-y-1/2 p-0.5 hover:bg-muted rounded" > diff --git a/packages/ui/src/components/layout/Header.tsx b/packages/ui/src/components/layout/Header.tsx index af2a9020..53f6715d 100644 --- a/packages/ui/src/components/layout/Header.tsx +++ b/packages/ui/src/components/layout/Header.tsx @@ -5,7 +5,7 @@ import { TooltipTrigger, } from '@/components/ui/tooltip'; -import { RiChat4Line, RiCodeLine, RiGitBranchLine, RiLayoutLeftLine, RiPlayListAddLine, RiSettings3Line, RiTerminalBoxLine, type RemixiconComponentType } from '@remixicon/react'; +import { RiChat4Line, RiCodeLine, RiCommandLine, RiGitBranchLine, RiLayoutLeftLine, RiPlayListAddLine, RiQuestionLine, RiSettings3Line, RiTerminalBoxLine, type RemixiconComponentType } from '@remixicon/react'; import { useUIStore, type MainTab } from '@/stores/useUIStore'; import { useConfigStore } from '@/stores/useConfigStore'; import { useSessionStore } from '@/stores/useSessionStore'; @@ -83,6 +83,8 @@ export const Header: React.FC = () => { const setSessionSwitcherOpen = useUIStore((state) => state.setSessionSwitcherOpen); const toggleSidebar = useUIStore((state) => state.toggleSidebar); const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen); + const toggleCommandPalette = useUIStore((state) => state.toggleCommandPalette); + const toggleHelpDialog = useUIStore((state) => state.toggleHelpDialog); const isSidebarOpen = useUIStore((state) => state.isSidebarOpen); const sidebarWidth = useUIStore((state) => state.sidebarWidth); const activeMainTab = useUIStore((state) => state.activeMainTab); @@ -384,6 +386,40 @@ export const Header: React.FC = () => { {}
+ + {} +
+ + + + + +

Command Palette (Ctrl+X)

+
+
+ + + + + +

Keyboard Shortcuts (Ctrl+H)

+
+
+
); diff --git a/packages/ui/src/components/ui/CommandPalette.tsx b/packages/ui/src/components/ui/CommandPalette.tsx index de6963bd..80960db6 100644 --- a/packages/ui/src/components/ui/CommandPalette.tsx +++ b/packages/ui/src/components/ui/CommandPalette.tsx @@ -15,7 +15,7 @@ import { useDirectoryStore } from '@/stores/useDirectoryStore'; import { useConfigStore } from '@/stores/useConfigStore'; import { useThemeSystem } from '@/contexts/useThemeSystem'; import { useDeviceInfo } from '@/lib/device'; -import { RiAddLine, RiChatAi3Line, RiCheckLine, RiComputerLine, RiGitBranchLine, RiLayoutLeftLine, RiMoonLine, RiQuestionLine, RiRestartLine, RiSettings3Line, RiSunLine, RiTerminalBoxLine } from '@remixicon/react'; +import { RiAddLine, RiChatAi3Line, RiCheckLine, RiCodeLine, RiComputerLine, RiGitBranchLine, RiLayoutLeftLine, RiMoonLine, RiQuestionLine, RiRestartLine, RiSettings3Line, RiSunLine, RiTerminalBoxLine } from '@remixicon/react'; import { reloadOpenCodeConfiguration } from '@/stores/useAgentsStore'; export const CommandPalette: React.FC = () => { @@ -85,6 +85,11 @@ export const CommandPalette: React.FC = () => { handleClose(); }; + const handleOpenDiffPanel = () => { + setActiveMainTab('diff'); + handleClose(); + }; + const handleOpenGitPanel = () => { setActiveMainTab('git'); handleClose(); @@ -137,6 +142,11 @@ export const CommandPalette: React.FC = () => { Keyboard Shortcuts Ctrl + H + + + Open Diff Panel + Ctrl + E + Open Git Panel diff --git a/packages/ui/src/components/ui/HelpDialog.tsx b/packages/ui/src/components/ui/HelpDialog.tsx index 76ed7930..e331ee28 100644 --- a/packages/ui/src/components/ui/HelpDialog.tsx +++ b/packages/ui/src/components/ui/HelpDialog.tsx @@ -7,7 +7,7 @@ import { DialogTitle, } from '@/components/ui/dialog'; import { useUIStore } from '@/stores/useUIStore'; -import { RiAddLine, RiArrowUpSLine, RiArrowUpWideLine, RiCloseCircleLine, RiCommandLine, RiGitBranchLine, RiLayoutLeftLine, RiPaletteLine, RiQuestionLine, RiSettings3Line, RiTerminalBoxLine, RiText } from '@remixicon/react'; +import { RiAddLine, RiArrowUpSLine, RiArrowUpWideLine, RiCloseCircleLine, RiCodeLine, RiCommandLine, RiGitBranchLine, RiLayoutLeftLine, RiPaletteLine, RiQuestionLine, RiSettings3Line, RiTerminalBoxLine, RiText } from '@remixicon/react'; const renderKeyToken = (token: string, index: number) => { const normalized = token.trim().toLowerCase(); @@ -70,7 +70,7 @@ export const HelpDialog: React.FC = () => { category: "Session Management", items: [ { keys: ["Ctrl + N"], description: "Create New Session", icon: RiAddLine }, - { keys: ["Shift + Ctrl + N"], description: "Open Session Creator (worktree support)", icon: RiGitBranchLine }, + { keys: ["Shift + Ctrl + N"], description: "Open Worktree Creator", icon: RiGitBranchLine }, { keys: ["Ctrl + I"], description: "Focus Chat Input", icon: RiText }, { keys: ["Esc + Esc"], description: "Abort active run (double press)", icon: RiCloseCircleLine }, ] @@ -79,6 +79,7 @@ export const HelpDialog: React.FC = () => { category: "Interface", items: [ { keys: ["⌘ + /", "Ctrl + /"], description: "Cycle Theme (Light → Dark → System)", icon: RiPaletteLine }, + { keys: ["Ctrl + E"], description: "Open Diff Panel", icon: RiCodeLine }, { keys: ["Ctrl + G"], description: "Open Git Panel", icon: RiGitBranchLine }, { keys: ["Ctrl + T"], description: "Open Terminal", icon: RiTerminalBoxLine }, { keys: ["Ctrl + ,"], description: "Open Settings", icon: RiSettings3Line }, diff --git a/packages/ui/src/components/ui/command.tsx b/packages/ui/src/components/ui/command.tsx index 567b070a..a5e8507e 100644 --- a/packages/ui/src/components/ui/command.tsx +++ b/packages/ui/src/components/ui/command.tsx @@ -22,7 +22,7 @@ function Command({ { return; } + if (e.ctrlKey && !e.metaKey && !e.shiftKey && e.key.toLowerCase() === 'e') { + e.preventDefault(); + const { activeMainTab } = useUIStore.getState(); + setActiveMainTab(activeMainTab === 'diff' ? 'chat' : 'diff'); + return; + } + if (e.ctrlKey && !e.metaKey && !e.shiftKey && e.key.toLowerCase() === 't') { e.preventDefault(); const { activeMainTab } = useUIStore.getState();