feat: add main features

Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
This commit is contained in:
2026-06-06 01:27:01 +02:00
parent 55b3bee2c8
commit 307ae71857
273 changed files with 48740 additions and 0 deletions

View File

@ -0,0 +1,76 @@
/** Tabs — a horizontal, optionally closable tab bar (LD).
*
* Presentation-only and controlled: the parent owns the active id and the open
* set. Used for the project tab bar (one tab per open project, ARCHITECTURE §10)
* but generic enough for any tabbed surface.
*/
import { cn } from "../lib/cn";
import { IconButton } from "./IconButton";
export interface TabItem {
/** Stable id, returned by `onSelect`/`onClose`. */
id: string;
/** Visible label. */
label: string;
}
export interface TabsProps {
/** Tabs to render, left to right. */
items: TabItem[];
/** Currently-active tab id. */
value: string | null;
/** Called with the id of the tab the user activates. */
onSelect: (id: string) => void;
/** When provided, each tab shows a close (×) control. */
onClose?: (id: string) => void;
className?: string;
}
/** A themed tab strip with selection and optional per-tab close. */
export function Tabs({ items, value, onSelect, onClose, className }: TabsProps) {
return (
<div
role="tablist"
className={cn("flex flex-wrap items-stretch gap-1", className)}
>
{items.map((tab) => {
const active = tab.id === value;
return (
<div
key={tab.id}
className={cn(
"group flex items-center gap-1 rounded-md border px-1 transition-colors",
active
? "border-border-strong bg-raised"
: "border-transparent hover:bg-raised",
)}
>
<button
type="button"
role="tab"
aria-selected={active}
onClick={() => onSelect(tab.id)}
className={cn(
"px-2 py-1 text-sm focus-visible:outline-none",
active ? "font-semibold text-content" : "text-muted hover:text-content",
)}
>
{tab.label}
</button>
{onClose && (
<IconButton
size="sm"
aria-label={`close ${tab.label}`}
onClick={() => onClose(tab.id)}
className="opacity-60 group-hover:opacity-100"
>
×
</IconButton>
)}
</div>
);
})}
</div>
);
}