Skip to content

Commit 931c009

Browse files
MarkShawn2020claude
andcommitted
refactor(header): 优化折叠状态下的 tab group 显示
- 折叠时移除 feature 数量显示,减少视觉噪音 - 折叠时移除项目名称,仅显示 logo(默认 box 图标) - 将原生 title 属性替换为 Tooltip 组件,延迟从 ~500ms 降至 100ms - 清理未使用的 useState/useEffect 代码 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d15405c commit 931c009

1 file changed

Lines changed: 65 additions & 57 deletions

File tree

src/components/GlobalHeader/FeatureTabGroup.tsx

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { useEffect } from "react";
21
import { useAtom } from "jotai";
32
import { PlusIcon, ArchiveIcon, DashboardIcon } from "@radix-ui/react-icons";
43
import { SortableContext, horizontalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
@@ -16,10 +15,14 @@ import {
1615
ContextMenuSubContent,
1716
ContextMenuSeparator,
1817
} from "@/components/ui/context-menu";
18+
import {
19+
Tooltip,
20+
TooltipContent,
21+
TooltipTrigger,
22+
} from "@/components/ui/tooltip";
1923
import { ProjectLogo } from "@/views/Workspace/ProjectLogo";
2024
import { SortableFeatureTab } from "./FeatureTab";
2125
import { CreateFeatureDialog } from "./CreateFeatureDialog";
22-
import { useState } from "react";
2326
import type { WorkspaceProject, Feature, WorkspaceData } from "@/views/Workspace/types";
2427

2528
interface FeatureTabGroupProps {
@@ -42,7 +45,6 @@ export function FeatureTabGroup({
4245
const [workspace, setWorkspace] = useAtom(workspaceDataAtom);
4346
const [collapsedGroups, setCollapsedGroups] = useAtom(collapsedProjectGroupsAtom);
4447
const navigate = useNavigate();
45-
const [hasLogo, setHasLogo] = useState(true); // Default true to hide name initially
4648
const {
4749
showCreateDialog,
4850
setShowCreateDialog,
@@ -51,12 +53,6 @@ export function FeatureTabGroup({
5153
createFeature,
5254
} = useFeatureCreation(project);
5355

54-
useEffect(() => {
55-
invoke<string | null>("get_project_logo", { projectPath: project.path })
56-
.then((logo) => setHasLogo(!!logo))
57-
.catch(() => setHasLogo(false));
58-
}, [project.path]);
59-
6056
const archivedFeatures = project.features.filter(f => f.archived);
6157

6258
const toggleCollapsed = () => {
@@ -218,31 +214,31 @@ export function FeatureTabGroup({
218214
return (
219215
<>
220216
<div className={`flex items-center flex-shrink-0 ${isDragging ? "opacity-50" : ""}`}>
221-
<ContextMenu>
222-
<ContextMenuTrigger asChild>
223-
<button
224-
onClick={features.length > 0 ? toggleCollapsed : handleSelectProject}
225-
className={`flex items-center gap-1.5 px-2 py-1 rounded-lg transition-colors cursor-grab active:cursor-grabbing ${
226-
isDragging
227-
? "bg-primary/20 shadow-lg"
228-
: isActiveProject
229-
? "bg-primary/10 text-primary"
230-
: "text-muted-foreground hover:text-ink hover:bg-card-alt"
231-
}`}
232-
title={projectDisplayName}
233-
{...dragHandleProps}
234-
>
235-
<ProjectLogo projectPath={project.path} size="sm" />
236-
{!hasLogo && (
237-
<span className="text-xs font-medium truncate max-w-[80px]">{projectDisplayName}</span>
238-
)}
239-
{features.length > 0 && (
240-
<span className="text-xs text-muted-foreground">{features.length}</span>
241-
)}
242-
</button>
243-
</ContextMenuTrigger>
244-
{contextMenuContent}
245-
</ContextMenu>
217+
<Tooltip delayDuration={100}>
218+
<ContextMenu>
219+
<TooltipTrigger asChild>
220+
<ContextMenuTrigger asChild>
221+
<button
222+
onClick={features.length > 0 ? toggleCollapsed : handleSelectProject}
223+
className={`flex items-center gap-1.5 px-2 py-1 rounded-lg transition-colors cursor-grab active:cursor-grabbing ${
224+
isDragging
225+
? "bg-primary/20 shadow-lg"
226+
: isActiveProject
227+
? "bg-primary/10 text-primary"
228+
: "text-muted-foreground hover:text-ink hover:bg-card-alt"
229+
}`}
230+
{...dragHandleProps}
231+
>
232+
<ProjectLogo projectPath={project.path} size="sm" />
233+
</button>
234+
</ContextMenuTrigger>
235+
</TooltipTrigger>
236+
{contextMenuContent}
237+
</ContextMenu>
238+
<TooltipContent side="bottom" className="text-xs">
239+
{projectDisplayName}
240+
</TooltipContent>
241+
</Tooltip>
246242
<div className="h-4 border-l border-border mx-1" />
247243
</div>
248244
<CreateFeatureDialog
@@ -269,21 +265,27 @@ export function FeatureTabGroup({
269265
}`}
270266
>
271267
{/* Project header with context menu */}
272-
<ContextMenu>
273-
<ContextMenuTrigger asChild>
274-
<button
275-
onClick={features.length > 0 ? toggleCollapsed : handleSelectProject}
276-
className={`flex items-center px-1 py-1 rounded transition-colors flex-shrink-0 cursor-grab active:cursor-grabbing ${
277-
isActiveProject ? "text-primary" : "text-muted-foreground hover:text-ink"
278-
}`}
279-
title={projectDisplayName}
280-
{...dragHandleProps}
281-
>
282-
<ProjectLogo projectPath={project.path} size="sm" />
283-
</button>
284-
</ContextMenuTrigger>
285-
{contextMenuContent}
286-
</ContextMenu>
268+
<Tooltip delayDuration={100}>
269+
<ContextMenu>
270+
<TooltipTrigger asChild>
271+
<ContextMenuTrigger asChild>
272+
<button
273+
onClick={features.length > 0 ? toggleCollapsed : handleSelectProject}
274+
className={`flex items-center px-1 py-1 rounded transition-colors flex-shrink-0 cursor-grab active:cursor-grabbing ${
275+
isActiveProject ? "text-primary" : "text-muted-foreground hover:text-ink"
276+
}`}
277+
{...dragHandleProps}
278+
>
279+
<ProjectLogo projectPath={project.path} size="sm" />
280+
</button>
281+
</ContextMenuTrigger>
282+
</TooltipTrigger>
283+
{contextMenuContent}
284+
</ContextMenu>
285+
<TooltipContent side="bottom" className="text-xs">
286+
{projectDisplayName}
287+
</TooltipContent>
288+
</Tooltip>
287289

288290
{/* Feature tabs */}
289291
{features.length > 0 && (
@@ -308,14 +310,20 @@ export function FeatureTabGroup({
308310
)}
309311

310312
{/* Add button */}
311-
<button
312-
onClick={openCreateDialog}
313-
onPointerDown={(e) => e.stopPropagation()}
314-
className="p-1 text-muted-foreground hover:text-ink hover:bg-card-alt rounded transition-colors"
315-
title="New Feature"
316-
>
317-
<PlusIcon className="w-3.5 h-3.5" />
318-
</button>
313+
<Tooltip delayDuration={100}>
314+
<TooltipTrigger asChild>
315+
<button
316+
onClick={openCreateDialog}
317+
onPointerDown={(e) => e.stopPropagation()}
318+
className="p-1 text-muted-foreground hover:text-ink hover:bg-card-alt rounded transition-colors"
319+
>
320+
<PlusIcon className="w-3.5 h-3.5" />
321+
</button>
322+
</TooltipTrigger>
323+
<TooltipContent side="bottom" className="text-xs">
324+
New Feature
325+
</TooltipContent>
326+
</Tooltip>
319327
</div>
320328

321329
{/* Separator between project groups */}

0 commit comments

Comments
 (0)