From d601bbf96879b81b11430d2244757317c3263ef4 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: Tue, 7 Apr 2026 00:40:21 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20add=20sidebar=20redesign=20spec=20?= =?UTF-8?q?=E2=80=94=20project=20filter=20+=20time-grouped=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- .../2026-04-07-sidebar-redesign-design.md | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-07-sidebar-redesign-design.md diff --git a/docs/superpowers/specs/2026-04-07-sidebar-redesign-design.md b/docs/superpowers/specs/2026-04-07-sidebar-redesign-design.md new file mode 100644 index 00000000..9a6279bf --- /dev/null +++ b/docs/superpowers/specs/2026-04-07-sidebar-redesign-design.md @@ -0,0 +1,145 @@ +# Sidebar Redesign — Project Filter + Time-Grouped Session List + +## Summary + +Redesign the desktop app sidebar to match the original Claude Code desktop app: +- Replace project-grouped session list with a **flat, time-grouped list** (Today / Yesterday / Last 7 days / Last 30 days / Older) +- Add a **ProjectFilter dropdown** at the top for multi-select project filtering +- Keep existing features: search, right-click menu (rename + delete), active session indicator, missing dir warning + +## Approach + +**Plan A: Frontend-only refactor** — modify `Sidebar.tsx`, add `ProjectFilter.tsx`, update `sessionStore.ts`. No backend API changes. + +## Components + +### 1. ProjectFilter (`desktop/src/components/layout/ProjectFilter.tsx`) + +New component providing a multi-select project dropdown. + +**UI structure:** +- **Trigger button**: displays current filter state + - All selected → "All projects" + - N selected → "N projects" + - Dropdown arrow (chevron) on the right +- **Dropdown panel** (absolute positioned, below trigger): + - "All projects" option (toggles select-all / deselect-all) + - Separator line + - Per-project items: folder icon + project name + checkmark when selected + - Project name extracted from sanitized projectPath (last segment) + +**Behavior:** +- Default state: "All projects" (empty `selectedProjects` array = show all) +- Click a project → toggle its selection +- Click "All projects" → select all (clear the filter) +- If all projects are individually selected → treat as "All projects" +- Clicking outside the dropdown closes it + +**Data source:** Extract unique `projectPath` values from the full session list (`sessions.map(s => s.projectPath)`), deduplicated and sorted alphabetically. + +### 2. Sidebar Layout (`desktop/src/components/layout/Sidebar.tsx`) + +**Layout (top to bottom):** +1. **+ New session** button (existing) +2. **Scheduled** button (existing) +3. **ProjectFilter** dropdown + settings icon (right side) +4. **Search sessions** input (existing) +5. **Time-grouped session list** (scrollable, main content area) +6. **Settings** button (bottom, existing) + +**Time grouping logic — `groupByTime(sessions)`:** + +```typescript +type TimeGroup = 'Today' | 'Yesterday' | 'Last 7 days' | 'Last 30 days' | 'Older' + +function groupByTime(sessions: SessionListItem[]): Map { + const now = new Date() + const startOfToday = startOfDay(now) + const startOfYesterday = startOfDay(subDays(now, 1)) + const sevenDaysAgo = startOfDay(subDays(now, 7)) + const thirtyDaysAgo = startOfDay(subDays(now, 30)) + + // Classify each session by modifiedAt into time buckets + // Within each bucket, sessions are already sorted by modifiedAt desc (from API) +} +``` + +No external date library needed — use native `Date` arithmetic. + +**Removed logic:** +- `getProjectDisplayName()` function +- `groupedSessions` useMemo that groups by projectPath +- Per-project group headers and collapsible groups + +**Preserved logic:** +- Search filtering (by title, case-insensitive) +- Active session highlighting (background color) +- Status dot (left side of each session item) +- Right-click context menu (rename + delete) +- "missing dir" warning badge +- Relative timestamp on hover + +### 3. Session Store Changes (`desktop/src/stores/sessionStore.ts`) + +**New state fields:** +```typescript +selectedProjects: string[] // empty = all projects (no filter) +availableProjects: string[] // unique project paths from all sessions +``` + +**New actions:** +```typescript +setSelectedProjects: (projects: string[]) => void +``` + +**Modified behavior:** +- `fetchSessions()` called without `project` parameter (fetch all sessions) +- `availableProjects` computed after fetching: `[...new Set(sessions.map(s => s.projectPath))]` +- Filtering by selectedProjects happens in `Sidebar.tsx` via useMemo, not in the store + +### 4. Session List Item Rendering + +Each session item renders as: + +``` +[status dot] Session title text... [4h] +``` + +- **Status dot**: small circle, brand color when active (connected), tertiary when inactive +- **Title**: single line, text-ellipsis overflow +- **Timestamp**: relative format (now / 5m / 2h / 3d / 1mo), shown on hover (matching current behavior) +- **Selected state**: `surface-selected` background color +- **Hover state**: `surface-hover` background color +- **Missing dir**: orange "missing dir" badge after title + +## What Does NOT Change + +- Backend API (`/api/sessions`, `/api/sessions/recent-projects`) — no changes +- Session CRUD operations (create, delete, rename, activate) +- WebSocket connection logic +- Right-click context menu items +- Search functionality (filter by title) +- Settings button at bottom +- Overall sidebar width and theme variables + +## File Change Summary + +| File | Change Type | Description | +|------|------------|-------------| +| `desktop/src/components/layout/ProjectFilter.tsx` | **New** | Multi-select project dropdown | +| `desktop/src/components/layout/Sidebar.tsx` | **Modify** | Replace project grouping with time grouping, integrate ProjectFilter | +| `desktop/src/stores/sessionStore.ts` | **Modify** | Add selectedProjects/availableProjects state | + +## Error Handling + +- Empty state: if no sessions match filter + search, show "No sessions found" message +- API failure: existing error handling in sessionStore remains unchanged +- Missing projects: if a session's projectPath doesn't match any known project, it still appears in "All projects" view + +## Testing + +- Verify time grouping correctly classifies sessions into Today/Yesterday/Last 7 days/Last 30 days/Older +- Verify ProjectFilter multi-select toggles work correctly +- Verify search + project filter work together (intersection) +- Verify right-click menu still works +- Verify active session highlighting persists across filter changes