Skip to content

Commit d3fb718

Browse files
committed
feat: enhance MainLayout and TabBar with sidebar integration
1 parent ad8e8c6 commit d3fb718

File tree

4 files changed

+92
-18
lines changed

4 files changed

+92
-18
lines changed

src/renderer/components/tasks/TaskList.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,15 @@ export function TaskList({ onSelectTask }: TaskListProps) {
215215
const bar = e.currentTarget.querySelector(
216216
".drag-bar",
217217
) as HTMLElement;
218-
if (bar) bar.style.backgroundColor = "var(--gray-a6)";
218+
if (bar) bar.style.backgroundColor = "var(--gray-a8)";
219219
}
220220
}}
221221
onMouseLeave={(e) => {
222222
if (!isResizing) {
223223
const bar = e.currentTarget.querySelector(
224224
".drag-bar",
225225
) as HTMLElement;
226-
if (bar) bar.style.backgroundColor = "transparent";
226+
if (bar) bar.style.backgroundColor = "var(--gray-a4)";
227227
}
228228
}}
229229
>
@@ -233,7 +233,7 @@ export function TaskList({ onSelectTask }: TaskListProps) {
233233
style={{
234234
width: "1px",
235235
height: "100%",
236-
backgroundColor: isResizing ? "var(--accent-9)" : "var(--gray-a6)",
236+
backgroundColor: isResizing ? "var(--accent-9)" : "var(--gray-a4)",
237237
transition: "background-color 0.2s",
238238
}}
239239
/>

src/renderer/components/ui/sidebar/SidebarContent.tsx

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Box } from "@radix-ui/themes";
1+
import { ArrowsInSimpleIcon, ArrowsOutSimpleIcon } from "@phosphor-icons/react";
2+
import { Box, Flex, IconButton, Tooltip } from "@radix-ui/themes";
23
import type { Task } from "@shared/types";
34
import type React from "react";
45
import { useEffect, useMemo, useState } from "react";
@@ -10,12 +11,17 @@ import { useSidebarStore } from "../../../stores/sidebarStore";
1011
import { useTabStore } from "../../../stores/tabStore";
1112
import { SidebarTreeItem } from "./SidebarTreeItem";
1213
import { useSidebarMenuData } from "./UseSidebarMenuData";
13-
import { buildTreeLines } from "./Utils";
14+
import { buildTreeLines, getAllNodeIds } from "./Utils";
1415

1516
export const SidebarContent: React.FC = () => {
1617
const { client } = useAuthStore();
1718
const { tabs, createTab, setActiveTab, activeTabId } = useTabStore();
18-
const { expandedNodes: expandedNodesArray, toggleNode } = useSidebarStore();
19+
const {
20+
expandedNodes: expandedNodesArray,
21+
toggleNode,
22+
expandAll,
23+
collapseAll,
24+
} = useSidebarStore();
1925
const { setCliMode } = useLayoutStore();
2026
const { saveRecording } = useRecordings();
2127
const { startRecording, stopRecording } = useAudioRecorder(saveRecording);
@@ -101,6 +107,20 @@ export const SidebarContent: React.FC = () => {
101107
});
102108

103109
const treeLines = buildTreeLines([menuData], "", "", expandedNodes, 0);
110+
const allNodeIds = useMemo(
111+
() => getAllNodeIds([menuData], "", 0),
112+
[menuData],
113+
);
114+
const allExpanded =
115+
allNodeIds.length > 0 && allNodeIds.every((id) => expandedNodes.has(id));
116+
117+
const handleToggleExpandAll = () => {
118+
if (allExpanded) {
119+
collapseAll();
120+
} else {
121+
expandAll(allNodeIds);
122+
}
123+
};
104124

105125
return (
106126
<Box
@@ -111,18 +131,45 @@ export const SidebarContent: React.FC = () => {
111131
>
112132
<Box p="2">
113133
<div className="sidebar-tree">
114-
{treeLines.map((line, index) => (
115-
<SidebarTreeItem
116-
key={line.nodeId}
117-
line={line}
118-
index={index}
119-
isHovered={hoveredLineIndex === index}
120-
expandedNodes={expandedNodes}
121-
onMouseEnter={() => setHoveredLineIndex(index)}
122-
onMouseLeave={() => setHoveredLineIndex(null)}
123-
onToggle={toggleNode}
124-
/>
125-
))}
134+
{treeLines.map((line, index) => {
135+
const isRoot = index === 0;
136+
if (isRoot) {
137+
return (
138+
<Flex key={line.nodeId} align="center" justify="between" mb="1">
139+
<span style={{ fontWeight: 500 }}>{line.label}</span>
140+
<Tooltip
141+
content={allExpanded ? "Collapse all" : "Expand all"}
142+
>
143+
<IconButton
144+
size="1"
145+
variant="ghost"
146+
color="gray"
147+
onClick={handleToggleExpandAll}
148+
style={{ cursor: "pointer" }}
149+
>
150+
{allExpanded ? (
151+
<ArrowsInSimpleIcon size={12} />
152+
) : (
153+
<ArrowsOutSimpleIcon size={12} />
154+
)}
155+
</IconButton>
156+
</Tooltip>
157+
</Flex>
158+
);
159+
}
160+
return (
161+
<SidebarTreeItem
162+
key={line.nodeId}
163+
line={line}
164+
index={index}
165+
isHovered={hoveredLineIndex === index}
166+
expandedNodes={expandedNodes}
167+
onMouseEnter={() => setHoveredLineIndex(index)}
168+
onMouseLeave={() => setHoveredLineIndex(null)}
169+
onToggle={toggleNode}
170+
/>
171+
);
172+
})}
126173
</div>
127174
</Box>
128175
</Box>

src/renderer/components/ui/sidebar/Utils.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,26 @@ export function buildTreeLines(
6262

6363
return lines;
6464
}
65+
66+
export function getAllNodeIds(
67+
nodes: TreeNode[],
68+
parentId = "",
69+
depth = 0,
70+
): string[] {
71+
const nodeIds: string[] = [];
72+
73+
nodes.forEach((node, index) => {
74+
const nodeId = parentId ? `${parentId}.${index}` : `${index}`;
75+
const hasChildren = !!(node.children && node.children.length > 0);
76+
77+
if (hasChildren && depth > 0) {
78+
nodeIds.push(nodeId);
79+
}
80+
81+
if (hasChildren && node.children) {
82+
nodeIds.push(...getAllNodeIds(node.children, nodeId, depth + 1));
83+
}
84+
});
85+
86+
return nodeIds;
87+
}

src/renderer/stores/sidebarStore.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ interface SidebarStore {
1010
setWidth: (width: number) => void;
1111
setIsResizing: (isResizing: boolean) => void;
1212
toggleNode: (nodeId: string) => void;
13+
expandAll: (allNodeIds: string[]) => void;
14+
collapseAll: () => void;
1315
}
1416

1517
export const useSidebarStore = create<SidebarStore>()(
@@ -28,6 +30,8 @@ export const useSidebarStore = create<SidebarStore>()(
2830
? state.expandedNodes.filter((id) => id !== nodeId)
2931
: [...state.expandedNodes, nodeId],
3032
})),
33+
expandAll: (allNodeIds) => set({ expandedNodes: allNodeIds }),
34+
collapseAll: () => set({ expandedNodes: [] }),
3135
}),
3236
{
3337
name: "sidebar-storage",

0 commit comments

Comments
 (0)