cc-haha/docs/superpowers/specs/2026-04-07-sidebar-redesign-design.md
程序员阿江(Relakkes) d601bbf968 docs: add sidebar redesign spec — project filter + time-grouped list
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 00:40:21 +08:00

5.7 KiB

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):

type TimeGroup = 'Today' | 'Yesterday' | 'Last 7 days' | 'Last 30 days' | 'Older'

function groupByTime(sessions: SessionListItem[]): Map<TimeGroup, SessionListItem[]> {
  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:

selectedProjects: string[]        // empty = all projects (no filter)
availableProjects: string[]       // unique project paths from all sessions

New actions:

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