/** * `ProjectTabs` — the project tab bar rendered below the app header. * * Shows one tab per open project with a close control, and a "+" button to the * right that opens the **Projects** panel (floating) — the single entry point * for creating a project or switching to a known one (#26). Purely * presentational: all state lives in the parent (ProjectsView via useProjects). * * The bar is always present (even with no open project) so the "+" stays * reachable; the empty case shows a muted placeholder next to it. */ import type { TabItem } from "@/shared"; import { Button, Tabs, cn } from "@/shared"; import type { ProjectActivityStatus } from "./projectActivity"; export interface ProjectTabsProps { items: TabItem[]; activeTabId: string | null; onSelect: (id: string) => void; onClose: (id: string) => void; /** Whether the Projects panel is currently open (in any placement). */ projectsPanelOpen: boolean; /** Open the Projects panel (floating) — create/switch project. */ onOpenProjectsPanel: () => void; /** Per-project custom CLI activity, keyed by project id. Missing = none. */ activityByProjectId?: Record; className?: string; } export function ProjectTabs({ items, activeTabId, onSelect, onClose, projectsPanelOpen, onOpenProjectsPanel, activityByProjectId = {}, className, }: ProjectTabsProps) { const tabs = items.map((item) => ({ ...item, leading: ( ), })); return (
{items.length === 0 ? (

No open tabs.

) : ( )} {/* Add-project affordance (#46): always a bordered `secondary` button so it reads as a clickable control in every state — including zero open projects — instead of the near-invisible `ghost` glyph it used to be. When the Projects panel is open it also shows the pressed ring. */}
); } function ProjectActivityDot({ status, label, }: { status: ProjectActivityStatus; label: string; }) { const title = status === "busy" ? `${label} : Échange en cours` : `${label} : Prêt`; return (