Skip to content

Commit d14bc0e

Browse files
jonathanlabclaude
andcommitted
feat: improve command menu and fix session view theming
Command Menu improvements: - Remove tasks list (was showing other users' tasks) - Remove "Go to tasks" navigation option - Add Navigation group with Home and Settings - Add Actions group with theme toggle, sidebar toggles, and new task - Add folder search - typing a folder name shows "New task in folder" options - Clean up code by replacing repetitive callbacks with runAndClose helper Session View: - Fix light mode background (was dark, now white in light mode) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 361ab37 commit d14bc0e

File tree

2 files changed

+105
-63
lines changed

2 files changed

+105
-63
lines changed

apps/array/src/renderer/features/command/components/CommandMenu.tsx

Lines changed: 104 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import { Command } from "@features/command/components/Command";
22
import { CommandKeyHints } from "@features/command/components/CommandKeyHints";
3-
import { useTasks } from "@features/tasks/hooks/useTasks";
4-
import { FileTextIcon, ListBulletIcon } from "@radix-ui/react-icons";
3+
import { useRightSidebarStore } from "@features/right-sidebar";
4+
import { useSidebarStore } from "@features/sidebar/stores/sidebarStore";
5+
import {
6+
FileTextIcon,
7+
GearIcon,
8+
HomeIcon,
9+
MoonIcon,
10+
SunIcon,
11+
ViewVerticalIcon,
12+
} from "@radix-ui/react-icons";
513
import { Flex, Text } from "@radix-ui/themes";
6-
import type { Task } from "@shared/types";
714
import { useNavigationStore } from "@stores/navigationStore";
8-
import { useCallback, useEffect, useRef } from "react";
15+
import { useRegisteredFoldersStore } from "@stores/registeredFoldersStore";
16+
import { useThemeStore } from "@stores/themeStore";
17+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
918
import { useHotkeys } from "react-hotkeys-hook";
1019

1120
interface CommandMenuProps {
@@ -14,38 +23,52 @@ interface CommandMenuProps {
1423
}
1524

1625
export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
17-
const { navigateToTaskList, navigateToTask, navigateToTaskInput } =
18-
useNavigationStore();
19-
const { data: tasks = [] } = useTasks();
26+
const { navigateToTaskInput, navigateToSettings } = useNavigationStore();
27+
const { folders } = useRegisteredFoldersStore();
28+
const { isDarkMode, toggleDarkMode } = useThemeStore();
29+
const toggleLeftSidebar = useSidebarStore((state) => state.toggle);
30+
const toggleRightSidebar = useRightSidebarStore((state) => state.toggle);
2031
const commandRef = useRef<HTMLDivElement>(null);
32+
const [searchQuery, setSearchQuery] = useState("");
2133

22-
// Close handlers
23-
const handleClose = useCallback(() => {
24-
onOpenChange(false);
25-
}, [onOpenChange]);
34+
const close = useCallback(() => onOpenChange(false), [onOpenChange]);
2635

27-
useHotkeys("escape", handleClose, {
36+
const runAndClose = useCallback(
37+
<T extends unknown[]>(fn: (...args: T) => void) =>
38+
(...args: T) => {
39+
fn(...args);
40+
close();
41+
},
42+
[close],
43+
);
44+
45+
useEffect(() => {
46+
if (!open) {
47+
setSearchQuery("");
48+
}
49+
}, [open]);
50+
51+
useHotkeys("escape", close, {
2852
enabled: open,
2953
enableOnContentEditable: true,
3054
enableOnFormTags: true,
3155
preventDefault: true,
3256
});
3357

34-
useHotkeys("mod+k", handleClose, {
58+
useHotkeys("mod+k", close, {
3559
enabled: open,
3660
enableOnContentEditable: true,
3761
enableOnFormTags: true,
3862
preventDefault: true,
3963
});
4064

41-
useHotkeys("mod+p", handleClose, {
65+
useHotkeys("mod+p", close, {
4266
enabled: open,
4367
enableOnContentEditable: true,
4468
enableOnFormTags: true,
4569
preventDefault: true,
4670
});
4771

48-
// Handle click outside
4972
useEffect(() => {
5073
if (!open) return;
5174

@@ -54,30 +77,21 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
5477
commandRef.current &&
5578
!commandRef.current.contains(event.target as Node)
5679
) {
57-
onOpenChange(false);
80+
close();
5881
}
5982
};
6083

6184
document.addEventListener("mousedown", handleClickOutside);
62-
return () => {
63-
document.removeEventListener("mousedown", handleClickOutside);
64-
};
65-
}, [open, onOpenChange]);
66-
67-
const handleNavigateToTasks = () => {
68-
navigateToTaskList();
69-
onOpenChange(false);
70-
};
71-
72-
const handleCreateTask = () => {
73-
navigateToTaskInput();
74-
onOpenChange(false);
75-
};
85+
return () => document.removeEventListener("mousedown", handleClickOutside);
86+
}, [open, close]);
7687

77-
const handleNavigateToTaskClick = (task: Task) => {
78-
navigateToTask(task);
79-
onOpenChange(false);
80-
};
88+
const matchingFolders = useMemo(() => {
89+
if (!searchQuery.trim()) return [];
90+
const query = searchQuery.toLowerCase();
91+
return folders.filter((folder) =>
92+
folder.name.toLowerCase().includes(query),
93+
);
94+
}, [folders, searchQuery]);
8195

8296
if (!open) return null;
8397

@@ -95,53 +109,81 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
95109
<Command.Root className="min-h-0 flex-1">
96110
<div className="flex items-center border-gray-6 border-b px-3">
97111
<Command.Input
98-
placeholder="Search for tasks, navigate to sections..."
112+
placeholder="Search commands..."
99113
autoFocus={true}
100114
style={{ fontSize: "12px" }}
101115
className="w-full bg-transparent py-3 outline-none placeholder:text-gray-9"
116+
onValueChange={setSearchQuery}
102117
/>
103118
</div>
104119

105120
<Command.List style={{ maxHeight: "400px" }}>
106121
<Command.Empty>No results found.</Command.Empty>
107122

108-
<Command.Group heading="Actions">
109-
<Command.Item value="Create new task" onSelect={handleCreateTask}>
110-
<FileTextIcon className="mr-3 h-3 w-3 text-gray-11" />
111-
<Text size="1">Create new task</Text>
123+
<Command.Group heading="Navigation">
124+
<Command.Item
125+
value="Home"
126+
onSelect={runAndClose(navigateToTaskInput)}
127+
>
128+
<HomeIcon className="mr-3 h-3 w-3 text-gray-11" />
129+
<Text size="1">Home</Text>
130+
</Command.Item>
131+
<Command.Item
132+
value="Settings"
133+
onSelect={runAndClose(navigateToSettings)}
134+
>
135+
<GearIcon className="mr-3 h-3 w-3 text-gray-11" />
136+
<Text size="1">Settings</Text>
112137
</Command.Item>
113138
</Command.Group>
114139

115-
<Command.Group heading="Navigation">
140+
<Command.Group heading="Actions">
116141
<Command.Item
117-
value="Go to tasks"
118-
onSelect={handleNavigateToTasks}
142+
value="Toggle theme dark light mode"
143+
onSelect={runAndClose(toggleDarkMode)}
119144
>
120-
<ListBulletIcon className="mr-3 h-3 w-3 text-gray-11" />
121-
<Text size="1">Go to tasks</Text>
145+
{isDarkMode ? (
146+
<SunIcon className="mr-3 h-3 w-3 text-gray-11" />
147+
) : (
148+
<MoonIcon className="mr-3 h-3 w-3 text-gray-11" />
149+
)}
150+
<Text size="1">Toggle theme</Text>
151+
</Command.Item>
152+
<Command.Item
153+
value="Toggle left sidebar"
154+
onSelect={runAndClose(toggleLeftSidebar)}
155+
>
156+
<ViewVerticalIcon className="mr-3 h-3 w-3 text-gray-11" />
157+
<Text size="1">Toggle left sidebar</Text>
158+
</Command.Item>
159+
<Command.Item
160+
value="Toggle right sidebar"
161+
onSelect={runAndClose(toggleRightSidebar)}
162+
>
163+
<ViewVerticalIcon className="mr-3 h-3 w-3 rotate-180 text-gray-11" />
164+
<Text size="1">Toggle right sidebar</Text>
165+
</Command.Item>
166+
<Command.Item
167+
value="Create new task"
168+
onSelect={runAndClose(navigateToTaskInput)}
169+
>
170+
<FileTextIcon className="mr-3 h-3 w-3 text-gray-11" />
171+
<Text size="1">New task</Text>
122172
</Command.Item>
123173
</Command.Group>
124174

125-
{tasks.length > 0 && (
126-
<Command.Group heading="Tasks">
127-
{tasks.map((task) => (
175+
{matchingFolders.length > 0 && (
176+
<Command.Group heading="New task in folder">
177+
{matchingFolders.map((folder) => (
128178
<Command.Item
129-
key={task.id}
130-
value={`${task.id} ${task.title}`}
131-
onSelect={() => handleNavigateToTaskClick(task)}
132-
className="items-start"
179+
key={folder.id}
180+
value={`New task in ${folder.name} folder`}
181+
onSelect={runAndClose(() => navigateToTaskInput(folder.id))}
133182
>
134-
<FileTextIcon className="mt-0.5 mr-3 h-4 w-4 flex-shrink-0 text-gray-11" />
135-
<Flex direction="column" flexGrow="1" className="min-w-0">
136-
<Text size="1" weight="medium" className="truncate">
137-
{task.title}
138-
</Text>
139-
{task.description && (
140-
<Text size="1" color="gray" className="mt-1 truncate">
141-
{task.description}
142-
</Text>
143-
)}
144-
</Flex>
183+
<FileTextIcon className="mr-3 h-3 w-3 text-gray-11" />
184+
<Text size="1">
185+
New task in <Text weight="bold">{folder.name}</Text>
186+
</Text>
145187
</Command.Item>
146188
))}
147189
</Command.Group>

apps/array/src/renderer/features/sessions/components/ConversationView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function ConversationView({
6060
<TurnView turn={turn} repoPath={repoPath} isCloud={isCloud} />
6161
)}
6262
autoScrollToBottom
63-
className="flex-1 bg-blackA-5 p-2 pb-16"
63+
className="flex-1 bg-white p-2 pb-16 dark:bg-gray-1"
6464
gap={12}
6565
footer={
6666
<SessionFooter

0 commit comments

Comments
 (0)