feat(ui): improve theme consistency and add diff panel shortcut

This commit is contained in:
Bohdan Triapitsyn
2025-12-19 16:48:25 +02:00
parent 22a10f020c
commit 0b091c6c15
13 changed files with 81 additions and 27 deletions
+1 -1
View File
@@ -2847,7 +2847,7 @@ dependencies = [
[[package]]
name = "openchamber-desktop"
version = "1.2.5"
version = "1.2.6"
dependencies = [
"anyhow",
"axum",
@@ -109,7 +109,7 @@ export const AgentMentionAutocomplete = React.forwardRef<AgentMentionAutocomplet
key={agent.name}
className={cn(
'flex items-start gap-2 px-3 py-1.5 cursor-pointer rounded-lg typography-ui-label',
index === selectedIndex && 'bg-accent'
index === selectedIndex && 'bg-muted'
)}
onClick={() => onAgentSelect(agent.name)}
onMouseEnter={() => setSelectedIndex(index)}
@@ -130,7 +130,7 @@ export const AgentMentionAutocomplete = React.forwardRef<AgentMentionAutocomplet
return (
<div
ref={containerRef}
className="absolute z-[100] min-w-0 w-full max-w-[360px] max-h-60 bg-popover border border-border rounded-xl shadow-none bottom-full mb-2 left-0 flex flex-col"
className="absolute z-[100] min-w-0 w-full max-w-[360px] max-h-60 bg-background border border-border rounded-xl shadow-none bottom-full mb-2 left-0 flex flex-col"
>
<ScrollableOverlay outerClassName="flex-1 min-h-0" className="px-0">
{agents.length ? (
@@ -201,7 +201,7 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
return (
<div
ref={containerRef}
className="absolute z-[100] min-w-0 w-full max-w-[450px] max-h-64 bg-popover border border-border rounded-xl shadow-none bottom-full mb-2 left-0 flex flex-col"
className="absolute z-[100] min-w-0 w-full max-w-[450px] max-h-64 bg-background border border-border rounded-xl shadow-none bottom-full mb-2 left-0 flex flex-col"
>
<ScrollableOverlay outerClassName="flex-1 min-h-0" className="px-0">
{loading ? (
@@ -216,7 +216,7 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
ref={(el) => { 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)}
@@ -234,7 +234,7 @@ export const FileMentionAutocomplete = React.forwardRef<FileMentionHandle, FileM
return (
<div
ref={containerRef}
className="absolute z-[100] min-w-0 w-full max-w-[520px] max-h-64 bg-popover border border-border rounded-xl shadow-none bottom-full mb-2 left-0 flex flex-col"
className="absolute z-[100] min-w-0 w-full max-w-[520px] max-h-64 bg-background border border-border rounded-xl shadow-none bottom-full mb-2 left-0 flex flex-col"
>
<ScrollableOverlay outerClassName="flex-1 min-h-0" className="px-0">
{loading ? (
@@ -255,7 +255,7 @@ export const FileMentionAutocomplete = React.forwardRef<FileMentionHandle, FileM
ref={(el) => { 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)}
@@ -1180,7 +1180,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({ 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'
)}
>
<div className="flex items-center gap-2 min-w-0">
@@ -1225,7 +1225,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({ 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'
)}
>
<div className="flex items-center gap-2 min-w-0">
@@ -1309,7 +1309,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({ 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'
)}
>
<div className="flex min-w-0 flex-col">
@@ -361,7 +361,7 @@ export const ServerFilePicker: React.FC<ServerFilePickerProps> = ({
const row = (
<div
className={cn(
"flex w-full items-center justify-start gap-1 px-2 py-1.5 rounded hover:bg-accent cursor-pointer typography-ui-label text-foreground text-left",
"flex w-full items-center justify-start gap-1 px-2 py-1.5 rounded hover:bg-muted cursor-pointer typography-ui-label text-foreground text-left",
file.type === 'file' && selectedFiles.has(file.path) && "bg-primary/10"
)}
style={{ paddingLeft: `${level * 12}px` }}
@@ -494,7 +494,7 @@ export const ServerFilePicker: React.FC<ServerFilePickerProps> = ({
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"
>
<RiCloseLine className="h-3 w-3"/>
</button>
+37 -1
View File
@@ -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 = () => {
{}
<div className="flex-1" />
{}
<div className="flex items-center gap-1 pr-3">
<Tooltip delayDuration={500}>
<TooltipTrigger asChild>
<button
type="button"
onClick={toggleCommandPalette}
aria-label="Open command palette"
className={headerIconButtonClass}
>
<RiCommandLine className="h-5 w-5" />
</button>
</TooltipTrigger>
<TooltipContent>
<p>Command Palette (Ctrl+X)</p>
</TooltipContent>
</Tooltip>
<Tooltip delayDuration={500}>
<TooltipTrigger asChild>
<button
type="button"
onClick={toggleHelpDialog}
aria-label="Keyboard shortcuts"
className={headerIconButtonClass}
>
<RiQuestionLine className="h-5 w-5" />
</button>
</TooltipTrigger>
<TooltipContent>
<p>Keyboard Shortcuts (Ctrl+H)</p>
</TooltipContent>
</Tooltip>
</div>
</div>
);
@@ -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 = () => {
<span>Keyboard Shortcuts</span>
<CommandShortcut>Ctrl + H</CommandShortcut>
</CommandItem>
<CommandItem onSelect={handleOpenDiffPanel}>
<RiCodeLine className="mr-2 h-4 w-4" />
<span>Open Diff Panel</span>
<CommandShortcut>Ctrl + E</CommandShortcut>
</CommandItem>
<CommandItem onSelect={handleOpenGitPanel}>
<RiGitBranchLine className="mr-2 h-4 w-4" />
<span>Open Git Panel</span>
+3 -2
View File
@@ -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 },
+2 -2
View File
@@ -22,7 +22,7 @@ function Command({
<CommandPrimitive
data-slot="command"
className={cn(
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-xl",
"bg-background text-foreground flex h-full w-full flex-col overflow-hidden rounded-xl",
className
)}
{...props}
@@ -154,7 +154,7 @@ function CommandItem({
<CommandPrimitive.Item
data-slot="command-item"
className={cn(
"hover:bg-accent hover:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-lg px-2 py-1.5 typography-meta outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"data-[selected=true]:bg-muted hover:bg-muted [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-lg px-2 py-1.5 typography-meta outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
@@ -40,7 +40,7 @@ function DropdownMenuContent({
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-visible rounded-xl border p-1 shadow-none",
"bg-background text-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-visible rounded-xl border p-1 shadow-none",
className
)}
{...props}
@@ -72,7 +72,7 @@ function DropdownMenuItem({
data-inset={inset}
data-variant={variant}
className={cn(
"hover:bg-accent hover:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:hover:bg-destructive/10 dark:data-[variant=destructive]:hover:bg-destructive/20 data-[variant=destructive]:hover:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
"hover:bg-muted data-[variant=destructive]:text-destructive data-[variant=destructive]:hover:bg-destructive/10 dark:data-[variant=destructive]:hover:bg-destructive/20 data-[variant=destructive]:hover:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className
)}
{...props}
@@ -90,7 +90,7 @@ function DropdownMenuCheckboxItem({
<DropdownMenuPrimitive.CheckboxItem
data-slot="dropdown-menu-checkbox-item"
className={cn(
"hover:bg-accent hover:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-lg py-1 px-2 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
"hover:bg-muted relative flex cursor-default items-center gap-2 rounded-lg py-1 px-2 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className
)}
checked={checked}
@@ -126,7 +126,7 @@ function DropdownMenuRadioItem({
<DropdownMenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
"relative flex cursor-default items-start gap-2 rounded-lg py-1 pl-2 pr-8 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-accent hover:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
"relative flex cursor-default items-start gap-2 rounded-lg py-1 pl-2 pr-8 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-muted [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
className
)}
{...props}
@@ -209,7 +209,7 @@ function DropdownMenuSubTrigger({
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
"hover:bg-accent hover:text-accent-foreground flex cursor-default items-center rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[inset]:pl-8",
"hover:bg-muted flex cursor-default items-center rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[inset]:pl-8",
className
)}
{...props}
@@ -228,7 +228,7 @@ function DropdownMenuSubContent({
<DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-visible rounded-xl border p-1 shadow-none",
"bg-background text-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-visible rounded-xl border p-1 shadow-none",
className
)}
{...props}
+3 -3
View File
@@ -38,7 +38,7 @@ function SelectTrigger({
data-slot="select-trigger"
data-size={size}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-lg border bg-transparent px-2 py-2 typography-ui-label whitespace-nowrap shadow-none outline-none focus-visible:outline-none hover:bg-accent hover:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-6 data-[size=sm]:h-6 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-lg border bg-transparent px-2 py-2 typography-ui-label whitespace-nowrap shadow-none outline-none focus-visible:outline-none hover:bg-muted data-[state=open]:bg-muted focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-6 data-[size=sm]:h-6 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
@@ -62,7 +62,7 @@ function SelectContent({
<SelectPrimitive.Content
data-slot="select-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden rounded-xl border shadow-none transform-gpu will-change-transform",
"bg-background text-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden rounded-xl border shadow-none transform-gpu will-change-transform",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
@@ -110,7 +110,7 @@ function SelectItem({
<SelectPrimitive.Item
data-slot="select-item"
className={cn(
"hover:bg-accent hover:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-lg py-1.5 pr-8 pl-2 typography-ui-label outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
"hover:bg-muted [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-lg py-1.5 pr-8 pl-2 typography-ui-label outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className
)}
{...props}
@@ -107,6 +107,13 @@ export const useKeyboardShortcuts = () => {
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();