feat(ui): IA redesign → production · יישום נאמן של 16 הדפים הנותרים למוקאפים
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 6s
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 6s
תיקון הגישה: יישום מלא ונאמן של עיצוב-המוקאפים המאושרים (Claude Design) על כל הדפים — שינוי-הרכב אמיתי פר-מוקאפ, לא ליטוש-טוקנים. כל hook/query/mutation/טאב/ טופס/נתון נשמר (אומת: tsc נקי + בדיקת-נוכחות hooks קריטיים; 0 פונקציונליות נמחקה). דפים (← מוקאפ): - בית — לוח: KPI + "תיקים לפי סטטוס" (bars) + כרטיס-אישורים + CTA כפול. - ארכיון — filter-bar שטוח + טבלה נקייה + צ'יפי-סוג/תוצאה. - הערות יו״ר — פריסה דו-טורית + טופס-הוספה חי + כרטיסי-הערה. - ספריית-פסיקה — tabs קו-תחתון + כרטיסי-תוצאה halacha/קטע + AuthorityBadge. - דף-תקדים — באנר-meta parchment + דו-טורי + provenance pills. - פסיקה-חסרה — pill פתוחים + צ'יפי-סטטוס + CTA העלאה. - יומונים — אזור-העלאה מקווקו + כרטיסי-digest + "ממתין" כתווית פסיבית. - גרף — פאנל-צד שכבות/אנליטיקה + canvas parchment. - אימון-סגנון — פורטרט: banner + KPI + אנטומיה + ביטויי-חתימה. - מתודולוגיה — עורך-צ'קליסט + "חל על:" + canon chip. - מיומנויות/סקריפטים — טבלאות אמיתיות + צ'יפי-סטטוס. - הגדרות — sidenav דו-טורי + env-rows עם "ממתין ל-redeploy". - דף-תיק — באנר-תיק parchment + tabs + timeline + "פתח עורך החלטה". - תפעול — SectionHeaders + טבלת-שירותים + כרטיסי-שער gold-wash. - compose — באנר-תיק + SOT pill + פריסה דו-טורית + "השלמה והעברה". תיקונים שלי אחרי הסוכנים: documents-panel (הוצאת רכיב Shell מ-render — React Compiler), scripts useMemo deps. /approvals כבר נבנה מחדש נאמנה (commit קודם). בדיקות: npx tsc --noEmit ✓ · eslint ✓ (לבד מ-learning-panel:109 קיים-מראש). שימור-פונקציונליות אומת. CI Docker build = שער סופי לפני deploy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { AlertTriangle, CheckCircle2, HelpCircle } from "lucide-react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
|
||||
type Props = {
|
||||
drift: boolean;
|
||||
@@ -9,31 +8,31 @@ type Props = {
|
||||
coolifyAvailable?: boolean;
|
||||
};
|
||||
|
||||
// Filled pill chips matching IA-redesign mockup 15 (.c-synced / .c-drift).
|
||||
export function DriftBadge({ drift, coolifyAvailable = true }: Props) {
|
||||
if (!coolifyAvailable) {
|
||||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="text-ink-muted border-rule gap-1"
|
||||
<span
|
||||
className="inline-flex items-center gap-1 rounded-full bg-rule-soft text-ink-muted text-[0.72rem] font-semibold px-2.5 py-0.5"
|
||||
title="Coolify לא זמין — מצב ה-drift לא ידוע"
|
||||
>
|
||||
<HelpCircle className="w-3 h-3" />
|
||||
Unknown
|
||||
</Badge>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (drift) {
|
||||
return (
|
||||
<Badge variant="outline" className="text-warn border-warn/40 gap-1">
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-warn-bg text-warn text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
<AlertTriangle className="w-3 h-3" />
|
||||
Drift
|
||||
</Badge>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Badge variant="outline" className="text-success border-success/40 gap-1">
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-success-bg text-success text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
<CheckCircle2 className="w-3 h-3" />
|
||||
Synced
|
||||
</Badge>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { useState } from "react";
|
||||
import { ExternalLink, Save, Lock } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import type { McpEnvVar } from "@/lib/api/settings";
|
||||
import { useUpdateMcpEnv } from "@/lib/api/settings";
|
||||
import { toast } from "sonner";
|
||||
@@ -44,36 +43,38 @@ export function EnvVarRow({
|
||||
`https://coolify.nautilus.marcusgroup.org/project/applications/${coolifyAppUuid}/environment-variables`;
|
||||
|
||||
return (
|
||||
<div className="rounded-md border border-rule p-4 bg-rule-soft/20 hover:bg-rule-soft/40 transition-colors">
|
||||
<div className="flex items-start justify-between gap-3 mb-3">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<code className="font-mono text-sm font-medium text-navy" dir="ltr">
|
||||
{spec.key}
|
||||
</code>
|
||||
<Badge variant="outline" className="text-[0.7rem]">
|
||||
{spec.type}
|
||||
</Badge>
|
||||
{spec.is_secret && (
|
||||
<Badge variant="outline" className="text-[0.7rem] text-warn border-warn/40 gap-1">
|
||||
<Lock className="w-3 h-3" />
|
||||
secret
|
||||
</Badge>
|
||||
)}
|
||||
<DriftBadge drift={spec.drift} coolifyAvailable={coolifyAvailable} />
|
||||
{spec.has_duplicates && (
|
||||
<Badge variant="outline" className="text-[0.7rem] text-warn border-warn/40">
|
||||
duplicates
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-ink-muted mt-1">{spec.description}</p>
|
||||
</div>
|
||||
<div className="px-5 py-4 border-b border-rule-soft last:border-b-0">
|
||||
{/* envtop — key + type chip + secret chip + drift/synced chip */}
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<code className="font-mono text-[0.84rem] font-semibold text-navy" dir="ltr">
|
||||
{spec.key}
|
||||
</code>
|
||||
<span className="inline-flex items-center rounded-full bg-info-bg text-info text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
{spec.type}
|
||||
</span>
|
||||
{spec.is_secret && (
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-navy text-white text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
<Lock className="w-3 h-3" />
|
||||
secret
|
||||
</span>
|
||||
)}
|
||||
<DriftBadge drift={spec.drift} coolifyAvailable={coolifyAvailable} />
|
||||
{spec.has_duplicates && (
|
||||
<span className="inline-flex items-center rounded-full bg-warn-bg text-warn text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
duplicates
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{spec.description && (
|
||||
<p className="text-[0.82rem] text-ink-muted mt-1">{spec.description}</p>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[0.72rem] text-ink-muted w-20">Coolify:</span>
|
||||
{/* vals — Coolify value | Container value (+pending) | save (mockup .vals 3-col) */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-[1fr_1fr_auto] gap-3.5 items-end mt-3.5">
|
||||
<div>
|
||||
<span className="block text-[0.72rem] text-ink-muted font-semibold mb-1">
|
||||
Coolify:
|
||||
</span>
|
||||
{spec.is_editable ? (
|
||||
<EnvVarEditor
|
||||
spec={spec}
|
||||
@@ -82,53 +83,61 @@ export function EnvVarRow({
|
||||
disabled={update.isPending}
|
||||
/>
|
||||
) : (
|
||||
<span className="font-mono text-ink" dir="ltr">
|
||||
{spec.coolify_value ?? <em className="text-ink-muted">— לא מוגדר —</em>}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="text-[0.72rem] text-ink-muted w-20">Container:</span>
|
||||
<span className="font-mono text-ink" dir="ltr">
|
||||
{spec.container_value ?? <em className="text-ink-muted">— לא מוגדר —</em>}
|
||||
</span>
|
||||
{/* ADM-5 (INV-IA5/INV-IA6): when Coolify ≠ Container the container is
|
||||
running a stale value until a redeploy — say so in plain Hebrew
|
||||
right here, not only via the top "Drift" badge. */}
|
||||
{coolifyAvailable && spec.drift && (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="text-[0.7rem] text-warn border-warn/40"
|
||||
title="הערך נשמר ב-Coolify אך הקונטיינר עדיין מריץ את הקודם — נדרש redeploy"
|
||||
<a
|
||||
href={coolifyEnvUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-mono text-[0.81rem] text-gold-deep hover:underline flex items-center gap-1"
|
||||
dir="ltr"
|
||||
>
|
||||
ממתין ל-redeploy
|
||||
</Badge>
|
||||
{spec.coolify_value ?? "— לא מוגדר —"}
|
||||
<ExternalLink className="w-3 h-3 shrink-0" />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<span className="block text-[0.72rem] text-ink-muted font-semibold mb-1">
|
||||
Container:
|
||||
</span>
|
||||
<div className="font-mono text-[0.81rem] text-ink-soft bg-rule-soft rounded-md px-3 py-2 flex items-center gap-2 flex-wrap" dir="ltr">
|
||||
<span>{spec.container_value ?? "— לא מוגדר —"}</span>
|
||||
{/* ADM-5 (INV-IA5/INV-IA6): Coolify ≠ Container ⇒ container is stale
|
||||
until a redeploy — say so in plain Hebrew right here. */}
|
||||
{coolifyAvailable && spec.drift && (
|
||||
<span
|
||||
className="inline-flex items-center rounded-full bg-warn-bg text-warn border border-warn text-[0.7rem] font-semibold px-2 py-0.5"
|
||||
dir="rtl"
|
||||
title="הערך נשמר ב-Coolify אך הקונטיינר עדיין מריץ את הקודם — נדרש redeploy"
|
||||
>
|
||||
ממתין ל-redeploy
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex md:block items-end">
|
||||
{spec.is_editable ? (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={handleSave}
|
||||
disabled={!dirty || update.isPending}
|
||||
variant={dirty ? "default" : "outline"}
|
||||
className={dirty ? "bg-gold text-white hover:bg-gold-deep border-transparent" : ""}
|
||||
>
|
||||
<Save className="w-3.5 h-3.5" data-icon="inline-start" />
|
||||
{update.isPending ? "שומר..." : "שמור"}
|
||||
</Button>
|
||||
) : (
|
||||
<a
|
||||
href={coolifyEnvUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 rounded-md border border-rule text-navy px-4 py-1.5 text-[0.81rem] font-semibold hover:bg-gold-wash"
|
||||
>
|
||||
ערוך ב-Coolify
|
||||
<ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end gap-2 mt-3">
|
||||
{!spec.is_editable && (
|
||||
<a
|
||||
href={coolifyEnvUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-[0.78rem] text-gold-deep hover:underline flex items-center gap-1"
|
||||
>
|
||||
ערוך ב-Coolify
|
||||
<ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
)}
|
||||
{spec.is_editable && (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={handleSave}
|
||||
disabled={!dirty || update.isPending}
|
||||
>
|
||||
<Save className="w-3.5 h-3.5" data-icon="inline-start" />
|
||||
{update.isPending ? "שומר..." : "שמור"}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -72,37 +72,39 @@ export function EnvironmentTab() {
|
||||
const duplicatesCount = data.vars.filter((v) => v.has_duplicates).length;
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Card className="bg-surface border-rule">
|
||||
<div className="space-y-5">
|
||||
{/* summary band — Coolify app id + drift/dup counts + redeploy CTA */}
|
||||
<Card className="bg-surface border-rule shadow-sm">
|
||||
<CardContent className="px-6 py-4 flex items-center justify-between gap-4 flex-wrap">
|
||||
<div className="flex items-center gap-3 flex-wrap text-sm">
|
||||
<Badge variant="outline">
|
||||
Coolify app: <code dir="ltr" className="ms-1">{data.coolify_app_uuid.slice(0, 8)}…</code>
|
||||
</Badge>
|
||||
{driftCount > 0 && (
|
||||
<Badge variant="outline" className="text-warn border-warn/40">
|
||||
{driftCount} drift
|
||||
</Badge>
|
||||
<span className="inline-flex items-center rounded-full bg-warn-bg text-warn text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
{driftCount} ב-Drift
|
||||
</span>
|
||||
)}
|
||||
{duplicatesCount > 0 && (
|
||||
<Badge variant="outline" className="text-warn border-warn/40">
|
||||
<span className="inline-flex items-center rounded-full bg-warn-bg text-warn text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
{duplicatesCount} duplicates
|
||||
</Badge>
|
||||
</span>
|
||||
)}
|
||||
{data.errors.length > 0 && (
|
||||
<Badge variant="outline" className="text-danger border-danger/40">
|
||||
<span className="inline-flex items-center rounded-full bg-danger-bg text-danger text-[0.72rem] font-semibold px-2.5 py-0.5">
|
||||
{data.errors.join(", ")}
|
||||
</Badge>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleRedeploy}
|
||||
disabled={redeploy.isPending}
|
||||
variant={pendingRedeploy ? "default" : "outline"}
|
||||
size="sm"
|
||||
className={pendingRedeploy ? "bg-gold text-white hover:bg-gold-deep border-transparent" : ""}
|
||||
variant={pendingRedeploy ? "default" : "outline"}
|
||||
>
|
||||
<RefreshCw className={redeploy.isPending ? "w-3.5 h-3.5 animate-spin" : "w-3.5 h-3.5"} data-icon="inline-start" />
|
||||
{redeploy.isPending ? "Redeploying..." : "Redeploy now"}
|
||||
{redeploy.isPending ? "פורס מחדש..." : "פרוס מחדש"}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -110,28 +112,41 @@ export function EnvironmentTab() {
|
||||
{CATEGORY_ORDER.map((cat) => {
|
||||
const vars = grouped.get(cat);
|
||||
if (!vars || vars.length === 0) return null;
|
||||
const catDrift = vars.filter((v) => v.drift).length;
|
||||
return (
|
||||
<Card key={cat} className="bg-surface border-rule">
|
||||
<CardContent className="px-6 py-5">
|
||||
<h2 className="text-navy text-lg mb-4 flex items-center gap-2">
|
||||
{CATEGORY_LABELS[cat]}
|
||||
<Badge variant="outline" className="text-[0.7rem] tabular-nums">
|
||||
{vars.length}
|
||||
</Badge>
|
||||
</h2>
|
||||
<div className="space-y-3">
|
||||
{vars.map((v) => (
|
||||
<EnvVarRow
|
||||
key={v.key}
|
||||
spec={v}
|
||||
coolifyAppUuid={data.coolify_app_uuid}
|
||||
coolifyAvailable={coolifyAvailable}
|
||||
onPendingRedeploy={() => setPendingRedeploy(true)}
|
||||
/>
|
||||
))}
|
||||
<div
|
||||
key={cat}
|
||||
className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden"
|
||||
>
|
||||
{/* panel header (.ph) — parchment band: title + count + drift chip */}
|
||||
<div className="flex items-center justify-between gap-3 px-5 py-4 border-b border-rule bg-parchment">
|
||||
<div>
|
||||
<h2 className="text-navy text-base font-semibold mb-0 flex items-center gap-2">
|
||||
{CATEGORY_LABELS[cat]}
|
||||
<span className="text-[0.72rem] text-ink-muted font-medium tabular-nums">
|
||||
({vars.length})
|
||||
</span>
|
||||
</h2>
|
||||
<p className="text-[0.78rem] text-ink-muted mt-0.5">
|
||||
מקור-האמת הוא Coolify. שינוי נכנס לתוקף רק לאחר redeploy של הקונטיינר.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{coolifyAvailable && catDrift > 0 && (
|
||||
<span className="inline-flex items-center rounded-full bg-warn-bg text-warn text-[0.72rem] font-semibold px-2.5 py-0.5 shrink-0">
|
||||
{catDrift} ב-Drift
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{vars.map((v) => (
|
||||
<EnvVarRow
|
||||
key={v.key}
|
||||
spec={v}
|
||||
coolifyAppUuid={data.coolify_app_uuid}
|
||||
coolifyAvailable={coolifyAvailable}
|
||||
onPendingRedeploy={() => setPendingRedeploy(true)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -11,60 +11,92 @@ import { RegistrationsTab } from "./_components/registrations-tab";
|
||||
import { BlocksTab } from "./_components/blocks-tab";
|
||||
import { AgentsTab } from "./_components/agents-tab";
|
||||
|
||||
/*
|
||||
* Settings — IA-redesign composition (mockup 15): a header band with a
|
||||
* top-end "redeploy" deep-link, then a two-column layout — a vertical
|
||||
* sidenav (section list) + the active section panel. Implemented on top of
|
||||
* shadcn Tabs so all six sections and their logic-heavy contents
|
||||
* (Paperclip, agents, env vars w/ drift+redeploy, tools, blocks,
|
||||
* registrations) are preserved verbatim; only the chrome is restyled from
|
||||
* a horizontal tab strip to the approved sidenav layout.
|
||||
*/
|
||||
|
||||
const COOLIFY_APP_UUID = "gyjo0mtw2c42ej3xxvbz8zio";
|
||||
const COOLIFY_REDEPLOY_URL = `https://coolify.nautilus.marcusgroup.org/project/applications/${COOLIFY_APP_UUID}`;
|
||||
|
||||
const SECTIONS = [
|
||||
{ value: "paperclip", label: "Paperclip / סוכנים", icon: Building2 },
|
||||
{ value: "agents", label: "סוכנים", icon: Bot },
|
||||
{ value: "environment", label: "משתני סביבה", icon: Server },
|
||||
{ value: "tools", label: "כלי MCP", icon: Wrench },
|
||||
{ value: "blocks", label: "בלוקים", icon: Layers },
|
||||
{ value: "registrations", label: "רישומים", icon: Plug },
|
||||
] as const;
|
||||
|
||||
export default function SettingsPage() {
|
||||
return (
|
||||
<AppShell>
|
||||
<section className="space-y-6">
|
||||
<header>
|
||||
<nav className="text-[0.78rem] text-ink-muted mb-1">
|
||||
<Link href="/" className="hover:text-gold-deep">
|
||||
בית
|
||||
</Link>
|
||||
<span aria-hidden> · </span>
|
||||
<span className="text-navy">הגדרות</span>
|
||||
</nav>
|
||||
<h1 className="text-navy mb-0">הגדרות</h1>
|
||||
<p className="text-ink-muted text-sm mt-1 max-w-2xl">
|
||||
תצורת המערכת, MCP server, ו-Paperclip integration.
|
||||
</p>
|
||||
<header className="flex items-end justify-between gap-4 flex-wrap">
|
||||
<div>
|
||||
<nav className="text-[0.78rem] text-ink-muted mb-1">
|
||||
<Link href="/" className="hover:text-gold-deep">
|
||||
בית
|
||||
</Link>
|
||||
<span aria-hidden> · </span>
|
||||
<span className="text-navy">הגדרות</span>
|
||||
</nav>
|
||||
<h1 className="text-navy mb-0">הגדרות</h1>
|
||||
<p className="text-ink-muted text-sm mt-1 max-w-2xl">
|
||||
תצורת הפלטפורמה — סוכנים, סביבה, כלים ובלוקים.
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
href={COOLIFY_REDEPLOY_URL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="shrink-0 rounded-lg bg-gold text-white hover:bg-gold-deep px-5 py-2.5 text-sm font-semibold transition-colors"
|
||||
>
|
||||
פרוס מחדש (redeploy)
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<div className="h-[2px] bg-gradient-to-l from-transparent via-gold to-transparent" />
|
||||
|
||||
<Tabs dir="rtl" defaultValue="paperclip" className="space-y-4">
|
||||
<TabsList>
|
||||
<TabsTrigger value="paperclip">
|
||||
<Building2 className="w-4 h-4" data-icon="inline-start" />
|
||||
Paperclip
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="agents">
|
||||
<Bot className="w-4 h-4" data-icon="inline-start" />
|
||||
סוכנים
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="environment">
|
||||
<Server className="w-4 h-4" data-icon="inline-start" />
|
||||
סביבה
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="tools">
|
||||
<Wrench className="w-4 h-4" data-icon="inline-start" />
|
||||
כלים
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="blocks">
|
||||
<Layers className="w-4 h-4" data-icon="inline-start" />
|
||||
בלוקים
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="registrations">
|
||||
<Plug className="w-4 h-4" data-icon="inline-start" />
|
||||
רישומים
|
||||
</TabsTrigger>
|
||||
<Tabs
|
||||
dir="rtl"
|
||||
defaultValue="environment"
|
||||
orientation="vertical"
|
||||
className="flex-row gap-6 items-start"
|
||||
>
|
||||
{/* vertical sidenav (mockup .sidenav) */}
|
||||
<TabsList
|
||||
variant="line"
|
||||
className="w-[230px] shrink-0 items-stretch gap-0 rounded-lg border border-rule bg-surface shadow-sm overflow-hidden p-0"
|
||||
>
|
||||
{SECTIONS.map((s) => {
|
||||
const Icon = s.icon;
|
||||
return (
|
||||
<TabsTrigger
|
||||
key={s.value}
|
||||
value={s.value}
|
||||
className="relative justify-start gap-2 rounded-none border-b border-rule-soft last:border-b-0 px-4 py-3 text-sm font-medium text-ink-soft data-active:bg-gold-wash data-active:text-gold-deep data-active:font-semibold data-active:after:opacity-100 data-active:after:bg-gold hover:bg-gold-wash/40"
|
||||
>
|
||||
<Icon className="w-4 h-4 shrink-0" />
|
||||
{s.label}
|
||||
</TabsTrigger>
|
||||
);
|
||||
})}
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="paperclip"><PaperclipTab /></TabsContent>
|
||||
<TabsContent value="agents"><AgentsTab /></TabsContent>
|
||||
<TabsContent value="environment"><EnvironmentTab /></TabsContent>
|
||||
<TabsContent value="tools"><ToolsTab /></TabsContent>
|
||||
<TabsContent value="blocks"><BlocksTab /></TabsContent>
|
||||
<TabsContent value="registrations"><RegistrationsTab /></TabsContent>
|
||||
<div className="flex-1 min-w-0">
|
||||
<TabsContent value="paperclip" className="mt-0"><PaperclipTab /></TabsContent>
|
||||
<TabsContent value="agents" className="mt-0"><AgentsTab /></TabsContent>
|
||||
<TabsContent value="environment" className="mt-0"><EnvironmentTab /></TabsContent>
|
||||
<TabsContent value="tools" className="mt-0"><ToolsTab /></TabsContent>
|
||||
<TabsContent value="blocks" className="mt-0"><BlocksTab /></TabsContent>
|
||||
<TabsContent value="registrations" className="mt-0"><RegistrationsTab /></TabsContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
</section>
|
||||
</AppShell>
|
||||
|
||||
Reference in New Issue
Block a user