From d2a99e01c21760f16031b8e6b93c89992483f979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Thu, 4 Jun 2026 19:51:18 +0800 Subject: [PATCH] fix(desktop): clarify sidebar project hierarchy (#733) Indent session rows under their project group and switch project folder icons between open and closed states when collapsed. Tested: cd desktop && bun run test --run src/components/layout/Sidebar.test.tsx -t "groups sessions by project|collapses a project group" Tested: cd desktop && bun run test --run src/components/layout/Sidebar.test.tsx Tested: bun run check:desktop Tested: Browser plugin smoke on http://127.0.0.1:3456/ confirmed first project open -> closed state, icon state, and pl-6 session indentation. Confidence: high Scope-risk: narrow --- .../src/components/layout/Sidebar.test.tsx | 6 ++++- desktop/src/components/layout/Sidebar.tsx | 27 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/desktop/src/components/layout/Sidebar.test.tsx b/desktop/src/components/layout/Sidebar.test.tsx index 55fdc2b8..7edb3c62 100644 --- a/desktop/src/components/layout/Sidebar.test.tsx +++ b/desktop/src/components/layout/Sidebar.test.tsx @@ -282,7 +282,9 @@ describe('Sidebar', () => { expect(screen.getByText('beta')).toBeInTheDocument() expect(screen.getByRole('button', { name: /Alpha newest/ })).toBeInTheDocument() expect(screen.queryByRole('button', { name: /Alpha hidden/ })).not.toBeInTheDocument() - expect(screen.getByRole('button', { name: /Alpha newest/ }).closest('[class*="pl-0"]')).toBeInTheDocument() + expect(screen.getByTestId('sidebar-project-session-list-workspace-alpha').parentElement).toHaveClass('pl-6') + expect(screen.getByRole('button', { name: 'Collapse alpha' })).toHaveAttribute('data-state', 'open') + expect(screen.getByTestId('sidebar-project-icon-workspace-alpha')).toHaveAttribute('data-icon-state', 'open') fireEvent.click(screen.getByRole('button', { name: 'Expand display' })) @@ -378,6 +380,8 @@ describe('Sidebar', () => { expect(screen.queryByRole('button', { name: /Alpha Session/ })).not.toBeInTheDocument() expect(screen.getByRole('button', { name: /Beta Session/ })).toBeInTheDocument() expect(screen.getByRole('button', { name: 'Expand alpha' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Expand alpha' })).toHaveAttribute('data-state', 'closed') + expect(screen.getByTestId('sidebar-project-icon-workspace-alpha')).toHaveAttribute('data-icon-state', 'closed') }) it('uses a bounded per-project session scroller for large expanded groups', () => { diff --git a/desktop/src/components/layout/Sidebar.tsx b/desktop/src/components/layout/Sidebar.tsx index 1a6bc7e5..0e468ac8 100644 --- a/desktop/src/components/layout/Sidebar.tsx +++ b/desktop/src/components/layout/Sidebar.tsx @@ -853,15 +853,32 @@ export function Sidebar({ isMobile = false, onRequestClose }: SidebarProps) { onDragStart={(event) => handleProjectDragStart(event, project.key)} onDragEnd={clearProjectDragState} onClick={() => toggleProjectCollapsed(project.key)} - className="flex min-w-0 flex-1 cursor-grab items-center gap-2 rounded-xl px-1.5 py-2 text-left transition-colors active:cursor-grabbing hover:bg-[var(--color-sidebar-item-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)]" + data-state={projectCollapsed ? 'closed' : 'open'} + className="flex min-w-0 flex-1 cursor-grab items-center gap-2 rounded-xl px-1.5 py-2 text-left transition-[background,color] active:cursor-grabbing hover:bg-[var(--color-sidebar-item-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)]" aria-expanded={!projectCollapsed} aria-label={t(projectCollapsed ? 'sidebar.expandProject' : 'sidebar.collapseProject', { project: project.title })} title={project.subtitle || project.title} > - -