From b6405dd6a4ba65fc5dc6746db7be7be7d0bb29f3 Mon Sep 17 00:00:00 2001 From: bndw Date: Wed, 4 Mar 2026 21:21:22 -0800 Subject: feat: replace header dropdowns with collapsible sidebar tree - Add Sidebar.tsx: project/session tree with inline rename, collapse/resize - App.tsx: load all sessions at startup, sync selectedProject on session click - Header.tsx: strip project/session UI, keep only right-side controls - globals.css: add .main-layout, sidebar, item, and activity-dot styles - Chat pane: move toggle button to left, use triangle icons matching sidebar --- renderer/src/components/Header.tsx | 172 +++++-------------------------------- 1 file changed, 21 insertions(+), 151 deletions(-) (limited to 'renderer/src/components/Header.tsx') diff --git a/renderer/src/components/Header.tsx b/renderer/src/components/Header.tsx index dc88a73..4e193e8 100644 --- a/renderer/src/components/Header.tsx +++ b/renderer/src/components/Header.tsx @@ -1,27 +1,18 @@ import React, { useState, useEffect } from "react"; -import type { Project, Session, Phase } from "../types"; -import { formatSessionLabel } from "../utils/timeFormat"; +import type { Session, Phase } from "../types"; const api = window.api; type Theme = "dark" | "light"; interface HeaderProps { - projects: Project[]; - sessions: Session[]; - selectedProject: Project | null; selectedSession: Session | null; - onSelectProject: (project: Project | null) => void; - onSelectSession: (session: Session | null) => void; - onCreateProject: () => void; - onCreateSession: () => void; - onDeleteProject?: (id: string) => void; - onDeleteSession?: (id: string) => void; - onRenameSession?: (id: string, name: string) => void; theme: Theme; onToggleTheme: () => void; gitBranch: string | null; onOpenSettings: () => void; + viewPhase: Phase; + onViewPhase: (phase: Phase) => void; } const phaseLabels: Record = { @@ -33,69 +24,18 @@ const phaseLabels: Record = { const phases: Phase[] = ["research", "plan", "implement"]; export function Header({ - projects, - sessions, - selectedProject, selectedSession, - onSelectProject, - onSelectSession, - onCreateProject, - onCreateSession, - onDeleteProject, - onDeleteSession, - onRenameSession, theme, onToggleTheme, gitBranch, onOpenSettings, + viewPhase, + onViewPhase, }: HeaderProps) { - const handleDeleteProject = () => { - if (!selectedProject || !onDeleteProject) return; - if (confirm(`Delete project "${selectedProject.name}"? This cannot be undone.`)) { - onDeleteProject(selectedProject.id); - } - }; - - const handleDeleteSession = () => { - if (!selectedSession || !onDeleteSession) return; - if (confirm(`Delete session "${selectedSession.name}"? This cannot be undone.`)) { - onDeleteSession(selectedSession.id); - } - }; - - const [isRenamingSession, setIsRenamingSession] = useState(false); - const [renameValue, setRenameValue] = useState(""); - // Guard against double-commit (onKeyDown Enter → unmount → onBlur) - const renameCommitted = React.useRef(false); - - const startRename = () => { - if (!selectedSession) return; - renameCommitted.current = false; - setRenameValue(selectedSession.name); - setIsRenamingSession(true); - }; - - const commitRename = () => { - if (renameCommitted.current) return; - renameCommitted.current = true; - if (selectedSession && onRenameSession && renameValue.trim()) { - onRenameSession(selectedSession.id, renameValue.trim()); - } - setIsRenamingSession(false); - }; - - const cancelRename = () => { - renameCommitted.current = true; // prevent blur from committing after cancel - setIsRenamingSession(false); - }; - // ── Maximize ───────────────────────────────────────────────── const [isMaximized, setIsMaximized] = useState(false); useEffect(() => { - // Returns the unsubscribe function; React cleanup calls it on unmount. - // On macOS, clicking the native green traffic light also fires this, - // keeping the glyph accurate when native controls are used. return api.onWindowMaximized(setIsMaximized); }, []); @@ -112,89 +52,7 @@ export function Header({ return (
- {/* ── Wordmark ── */} Claude Flow - - - - {selectedProject && onDeleteProject && ( - - )} - - {selectedProject && ( - <> - {isRenamingSession ? ( - setRenameValue(e.target.value)} - onKeyDown={(e) => { - if (e.key === "Enter") commitRename(); - if (e.key === "Escape") cancelRename(); - }} - onBlur={commitRename} - className="session-rename-input" - /> - ) : ( - - )} - - {selectedSession && - onRenameSession && - !isRenamingSession && - selectedSession.phase !== "implement" && ( - - )} - {selectedSession && onDeleteSession && ( - - )} - - )}
@@ -205,15 +63,27 @@ export function Header({ const currentIndex = phases.indexOf(selectedSession.phase); const isComplete = phaseIndex < currentIndex; const isActive = phase === selectedSession.phase; + const isReachable = phaseIndex <= currentIndex; + const isViewing = phase === viewPhase && !isActive; - return ( - onViewPhase(phase)} + title={ + isActive + ? `Viewing ${phaseLabels[phase]} (current)` + : `View ${phaseLabels[phase]} artifact` + } > {phaseLabels[phase]} + + ) : ( + + {phaseLabels[phase]} ); })} @@ -244,7 +114,7 @@ export function Header({ onClick={() => api.toggleMaximize()} title={isMaximized ? "Restore window" : "Maximize window"} > - {isMaximized ? '⊡' : '□'} + {isMaximized ? "⊡" : "□"} {/* ── Settings button ── */} -- cgit v1.2.3