Retire les utilitaires `flex-1` sur la liste d'onglets et sur le placeholder « No open tabs. » : le conteneur ne pousse plus la zone d'onglets sur toute la largeur, si bien que le bouton d'ajout de projet « + » vient directement à la suite des onglets au lieu d'être repoussé à l'extrémité droite de la barre. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
75 lines
2.2 KiB
TypeScript
75 lines
2.2 KiB
TypeScript
/**
|
|
* `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";
|
|
|
|
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;
|
|
className?: string;
|
|
}
|
|
|
|
export function ProjectTabs({
|
|
items,
|
|
activeTabId,
|
|
onSelect,
|
|
onClose,
|
|
projectsPanelOpen,
|
|
onOpenProjectsPanel,
|
|
className,
|
|
}: ProjectTabsProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"flex shrink-0 items-center gap-1 border-b border-border bg-surface px-2 py-1",
|
|
className,
|
|
)}
|
|
>
|
|
{items.length === 0 ? (
|
|
<p className="px-2 text-sm text-muted">No open tabs.</p>
|
|
) : (
|
|
<Tabs
|
|
items={items}
|
|
value={activeTabId}
|
|
onSelect={onSelect}
|
|
onClose={onClose}
|
|
/>
|
|
)}
|
|
{/* 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. */}
|
|
<Button
|
|
size="sm"
|
|
variant="secondary"
|
|
onClick={onOpenProjectsPanel}
|
|
aria-label="open projects panel"
|
|
aria-pressed={projectsPanelOpen}
|
|
title="Ajouter un projet"
|
|
className={cn(
|
|
"shrink-0",
|
|
projectsPanelOpen && "ring-1 ring-border-strong",
|
|
)}
|
|
>
|
|
+
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|