diff --git a/frontend/index.html b/frontend/index.html index 2e41ef8..17653d7 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7,7 +7,7 @@
+ {children} ), diff --git a/frontend/src/components/ModelSelector.tsx b/frontend/src/components/ModelSelector.tsx index 54a767c..7646e16 100644 --- a/frontend/src/components/ModelSelector.tsx +++ b/frontend/src/components/ModelSelector.tsx @@ -40,14 +40,14 @@ export function ModelSelector({ onClick={() => setOpen((v) => !v)} className={ variant === "composer" - ? "flex h-8 min-w-0 max-w-[220px] items-center gap-1.5 border-2 border-line bg-accent px-2.5 text-[13px] text-white" - : "flex h-[34px] min-w-0 max-w-[260px] items-center gap-2 border-[3px] border-white bg-accent px-3 text-white shadow-accent-soft" + ? "flex h-8 min-w-0 max-w-[220px] items-center gap-1.5 border border-line bg-accent px-2.5 text-[13px] text-white" + : "flex h-[34px] min-w-0 max-w-[260px] items-center gap-2 border border-white bg-accent px-3 text-white shadow-accent-soft" } title={selectedModel || undefined} style={{ borderRadius: 7 }} > diff --git a/frontend/src/components/ProjectChip.tsx b/frontend/src/components/ProjectChip.tsx index 83cfbe4..3626702 100644 --- a/frontend/src/components/ProjectChip.tsx +++ b/frontend/src/components/ProjectChip.tsx @@ -52,7 +52,7 @@ export function ProjectChip() { setOpen((o) => !o)} - className="flex h-8 items-center gap-1.5 border-2 border-line bg-base px-2.5 text-[12px] text-ink-2" + className="flex h-8 items-center gap-1.5 border border-line bg-base px-2.5 text-[12px] text-ink-2" title="Projet de travail de cette session" > 📁 {active ?? "workspace"} @@ -60,7 +60,7 @@ export function ProjectChip() { {open && ( choose(p.name)} - className={`block w-full border-t-2 border-line-soft px-3 py-2 text-left text-[13px] text-ink-2 hover:bg-base ${ + className={`block w-full border-t border-line-soft px-3 py-2 text-left text-[13px] text-ink-2 hover:bg-base ${ active === p.name ? "bg-base font-bold" : "" }`} > @@ -85,7 +85,7 @@ export function ProjectChip() { ))} - + {creating ? ( ) : ( setOpen((o) => !o)} - className="flex cursor-pointer items-center gap-2 text-[13px] text-on-dark hover:text-white" + className="flex cursor-pointer items-center gap-2 text-[13px] text-on-dark hover:text-ink" title="Sessions" > @@ -66,7 +66,7 @@ export function SessionMenu() { {open && ( Nouvelle session @@ -97,7 +97,7 @@ export function SessionMenu() { setOpen(false); void openSession(s.id); }} - className={`group cursor-pointer border-b-2 border-chrome-3 px-3 py-2 last:border-b-0 ${ + className={`group cursor-pointer border-b border-chrome-3 px-3 py-2 last:border-b-0 ${ active ? "bg-chrome-3" : "hover:bg-chrome-3" }`} > @@ -116,12 +116,12 @@ export function SessionMenu() { } }} onBlur={() => setEditingId(null)} - className="min-w-0 flex-1 border-2 border-line bg-card-deep px-1.5 py-0.5 text-[13px] text-white outline-none" + className="min-w-0 flex-1 border border-line bg-card-deep px-1.5 py-0.5 text-[13px] text-ink outline-none" /> ) : ( {s.title} @@ -129,7 +129,7 @@ export function SessionMenu() { )} {working && ( EN COURS @@ -141,7 +141,7 @@ export function SessionMenu() { setEditingId(s.id); setDraft(s.title); }} - className="hidden flex-none text-[11px] text-on-dark-3 hover:text-white group-hover:block" + className="hidden flex-none text-[11px] text-on-dark-3 hover:text-ink group-hover:block" title="Renommer la session" > ✎ diff --git a/frontend/src/components/ToolCard.tsx b/frontend/src/components/ToolCard.tsx index 2c2abe0..045bdda 100644 --- a/frontend/src/components/ToolCard.tsx +++ b/frontend/src/components/ToolCard.tsx @@ -23,11 +23,11 @@ export function ToolCard({ call }: { call: ToolCall }) { const write = call.name === "write_file" || call.name === "edit_file"; return ( - + @@ -37,7 +37,7 @@ export function ToolCard({ call }: { call: ToolCall }) { {running ? ( - + en cours ) : pending ? ( @@ -53,7 +53,7 @@ export function ToolCard({ call }: { call: ToolCall }) { )} {call.summary && !running && ( - + → {call.summary} )} diff --git a/frontend/src/components/TopBar.tsx b/frontend/src/components/TopBar.tsx index 0520781..f11fc5a 100644 --- a/frontend/src/components/TopBar.tsx +++ b/frontend/src/components/TopBar.tsx @@ -16,10 +16,10 @@ export function TopBar() { }, []); return ( - + - LOKI + LOKI + CPU {stats.cpu_pct.toFixed(0)}% · RAM {stats.ram_pct.toFixed(0)}% @@ -58,11 +58,11 @@ export function TopBar() { {/* Statut Ollama */} diff --git a/frontend/src/index.css b/frontend/src/index.css index c124437..7cbb4fe 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -10,27 +10,47 @@ body, } body { - background: #ececef; - color: #18181b; - font-family: "DM Mono", ui-monospace, monospace; - letter-spacing: -0.01em; + background: #f7f8fa; + color: #1c2536; + font-family: "Inter", ui-sans-serif, system-ui, sans-serif; -webkit-font-smoothing: antialiased; } -/* Police pixel pour les libellés (utilitaire .font-pixel via Tailwind aussi) */ -.font-pixel { - font-family: "Press Start 2P", ui-monospace, monospace; +/* Titres : léger resserrement, comme dans la maquette Nocturne. */ +h1, +h2, +h3 { + letter-spacing: -0.025em; } -/* Barres de défilement néo-brutalistes */ +/* Ex-police pixel : « kicker » de la maquette (petites capitales espacées). */ +.font-pixel { + font-family: "Inter", ui-sans-serif, system-ui, sans-serif; + font-weight: 500; + letter-spacing: 0.14em; + text-transform: uppercase; +} + +/* Barres de défilement discrètes (règles .scr de la maquette) */ .scr::-webkit-scrollbar { - width: 12px; - height: 12px; + width: 10px; + height: 10px; } .scr::-webkit-scrollbar-thumb { - background: #18181b; - border: 2px solid #ececef; + background: #c3c9d2; + border-radius: 6px; + border: 3px solid transparent; + background-clip: content-box; } .scr::-webkit-scrollbar-track { - background: #e4e4e7; + background: transparent; +} + +/* Focus visible accentué, sélection teintée — repris de la maquette. */ +:focus-visible { + outline: 2px solid #2f4a7a; + outline-offset: 2px; +} +::selection { + background: rgba(47, 74, 122, 0.32); } diff --git a/frontend/src/panels/ActivityViews.tsx b/frontend/src/panels/ActivityViews.tsx index f6861e1..366fbe7 100644 --- a/frontend/src/panels/ActivityViews.tsx +++ b/frontend/src/panels/ActivityViews.tsx @@ -14,7 +14,7 @@ export function HistoryView({ onOpen }: { onOpen: () => void }) { {sessions.map((session) => ( - + {session.title} {session.message_count ?? 0} message(s) · {new Date(session.updated_at * 1000).toLocaleString("fr-FR")} @@ -25,13 +25,13 @@ export function HistoryView({ onOpen }: { onOpen: () => void }) { await openSession(session.id); onOpen(); }} - className="border-2 border-line bg-accent px-3 py-1.5 text-[12px] font-bold text-white" + className="border border-line bg-accent px-3 py-1.5 text-[12px] font-bold text-white" > Ouvrir removeSession(session.id)} - className="border-2 border-line bg-base px-3 py-1.5 text-[12px] text-warn" + className="border border-line bg-base px-3 py-1.5 text-[12px] text-warn" > Supprimer @@ -53,7 +53,7 @@ export function FilesView() { return ( - + {fileTree.length ? : } @@ -74,9 +74,9 @@ function WorkspaceTree({ nodes, depth }: { nodes: FileNode[]; depth: number }) { {nodes.map((node) => ( downloadFile(node.path, currentProject())} - className="flex items-center gap-1 border-2 border-line bg-base px-2 py-1 text-[11px] text-accent" + className="flex items-center gap-1 border border-line bg-base px-2 py-1 text-[11px] text-accent" title={`Télécharger ${node.name}`} > Télécharger @@ -102,7 +102,7 @@ function WorkspaceTree({ nodes, depth }: { nodes: FileNode[]; depth: number }) { )} confirmDelete(node)} - className="flex items-center gap-1 border-2 border-line bg-base px-2 py-1 text-[11px] text-warn" + className="flex items-center gap-1 border border-line bg-base px-2 py-1 text-[11px] text-warn" title={`Supprimer ${node.name}`} > Supprimer @@ -128,10 +128,10 @@ export function ToolsView({ onSettings }: { onSettings: () => void }) { {availableTools.map((name) => { const enabled = config?.tools[name] ?? false; return ( - + {name} - + {enabled ? "ACTIF" : "INACTIF"} @@ -141,7 +141,7 @@ export function ToolsView({ onSettings }: { onSettings: () => void }) { Configurer les outils @@ -162,7 +162,7 @@ function Page({ title, subtitle, children }: { title: string; subtitle: string; } function Empty({ text }: { text: string }) { - return {text}; + return {text}; } function formatSize(bytes: number): string { diff --git a/frontend/src/panels/ChatPanel.tsx b/frontend/src/panels/ChatPanel.tsx index 56eb73b..2ed87af 100644 --- a/frontend/src/panels/ChatPanel.tsx +++ b/frontend/src/panels/ChatPanel.tsx @@ -63,10 +63,10 @@ export function ChatPanel() { return ( {/* Barre de contexte */} - + ⚑ Invite système - + {activeTools} outil{activeTools > 1 ? "s" : ""} @@ -130,9 +130,9 @@ export function ChatPanel() { {/* Composer */} - + - + @@ -201,7 +201,7 @@ function ModeSelector() { setOpen((v) => !v)} - className={`flex h-8 items-center gap-1.5 border-2 border-line px-2.5 text-[13px] ${ + className={`flex h-8 items-center gap-1.5 border border-line px-2.5 text-[13px] ${ mode === "plan" ? "bg-info text-white" : mode === "yolo" @@ -215,7 +215,7 @@ function ModeSelector() { {open && ( - + {MODES.map((m) => ( - + PLAN {doneCount > 0 @@ -280,7 +280,7 @@ function PlanCard({ }`} > - + M @@ -332,7 +332,7 @@ function Bubble({ VOUS {time} - + {msg.content} @@ -342,8 +342,8 @@ function Bubble({ return ( - - + + @@ -364,7 +364,7 @@ function Bubble({ ))} {notice && ( - + {notice} )} @@ -416,7 +416,7 @@ function ReasoningPanel({ text, live }: { text: string; live: boolean }) { if (!text) return null; return ( - + setOpen((o) => !o)} className="flex w-full items-center gap-2 px-3 py-2 text-left" @@ -428,7 +428,7 @@ function ReasoningPanel({ text, live }: { text: string; live: boolean }) { Raisonnement {live && ( - + en cours… )} @@ -439,7 +439,7 @@ function ReasoningPanel({ text, live }: { text: string; live: boolean }) { {open && ( {text} @@ -458,26 +458,26 @@ function ShellConfirm({ onReject: () => void; }) { return ( - - + + run_shell · commande sensible à valider - + $ {command} Approuver & exécuter Refuser @@ -490,7 +490,7 @@ function ShellConfirm({ function Chip({ children }: { children: React.ReactNode }) { return ( - + {children} ); diff --git a/frontend/src/panels/LeftPanel.tsx b/frontend/src/panels/LeftPanel.tsx index 36cff1b..186112b 100644 --- a/frontend/src/panels/LeftPanel.tsx +++ b/frontend/src/panels/LeftPanel.tsx @@ -24,7 +24,7 @@ export function LeftPanel() { }, [refreshSessions, refreshFiles]); return ( - + {/* Historique */} HISTORIQUE @@ -50,7 +50,7 @@ export function LeftPanel() { openSession(s.id)} - className={`group cursor-pointer border-[3px] border-line px-3 py-2.5 ${ + className={`group cursor-pointer border border-line px-3 py-2.5 ${ active ? "bg-card-deep shadow-hard-accent" : "bg-card" }`} style={{ borderRadius: 7 }} @@ -58,14 +58,14 @@ export function LeftPanel() { {s.title} {working && ( EN COURS @@ -93,7 +93,7 @@ export function LeftPanel() { })} - + {/* Fichiers */} @@ -136,7 +136,7 @@ function FileTree({ nodes, depth }: { nodes: FileNode[]; depth: number }) { className={`group mb-[3px] flex items-center gap-2 px-2 py-[5px] ${ n.type === "file" ? active - ? "cursor-pointer border-2 border-line bg-card-deep text-white" + ? "cursor-pointer border border-line bg-card-deep text-ink" : "cursor-pointer text-ink-2 hover:bg-base" : "text-muted" }`} @@ -146,7 +146,7 @@ function FileTree({ nodes, depth }: { nodes: FileNode[]; depth: number }) { ▾ ) : ( diff --git a/frontend/src/panels/PreviewPanel.tsx b/frontend/src/panels/PreviewPanel.tsx index 16f1432..45c3411 100644 --- a/frontend/src/panels/PreviewPanel.tsx +++ b/frontend/src/panels/PreviewPanel.tsx @@ -63,7 +63,7 @@ export function PreviewPanel() { // Replié : barre fine, aucun contenu monté (pas d'iframe vivante). if (collapsed) { return ( - + {/* Onglets */} - + setTab("preview")}> Aperçu @@ -106,7 +106,7 @@ export function PreviewPanel() { setTab("logs")}> Logs - + {logs.length} @@ -125,7 +125,7 @@ export function PreviewPanel() { {/* URL bar */} - + 🔒 {previewPath ? `workspace/${previewPath}` : "workspace/"} @@ -135,7 +135,7 @@ export function PreviewPanel() { <> downloadFile(previewPath, useStore.getState().currentProject())} - className="flex h-8 items-center gap-1.5 border-[3px] border-line bg-card px-2.5 text-[12px] text-accent" + className="flex h-8 items-center gap-1.5 border border-line bg-card px-2.5 text-[12px] text-accent" title={`Télécharger ${previewPath}`} > @@ -147,7 +147,7 @@ export function PreviewPanel() { void removeFile(previewPath); } }} - className="flex h-8 items-center gap-1.5 border-[3px] border-line bg-card px-2.5 text-[12px] text-warn" + className="flex h-8 items-center gap-1.5 border border-line bg-card px-2.5 text-[12px] text-warn" title={`Supprimer ${previewPath}`} > @@ -162,7 +162,7 @@ export function PreviewPanel() { ) : /* Onglet Logs (fond sombre) */ tab === "logs" ? ( - + {logs.length === 0 ? ( Aucune activité d'outil pour cette session. @@ -171,7 +171,7 @@ export function PreviewPanel() { logs.map((l, i) => ( ) : ( /* Viewport Aperçu / Code (fond clair) */ - + {!previewPath ? ( L'aperçu s'affichera ici dès que l'agent générera un fichier (clique aussi un fichier à gauche). ) : tab === "code" ? ( - + {previewContent} ) : isHtml ? ( @@ -225,7 +225,7 @@ export function PreviewPanel() { sandbox="allow-scripts" /> ) : ( - + {previewContent} )} @@ -276,14 +276,14 @@ function GitPanel() { }; return ( - + {error && ( - + {error} )} {/* Liste des commits */} - + {commits.length === 0 ? ( Aucun commit. L'agent commitera chaque modification de code ici. @@ -310,7 +310,7 @@ function GitPanel() { doRevert(c.hash)} disabled={busy === c.hash} - className="flex-none border-2 border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" + className="flex-none border border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" title="Annuler ce commit (revert)" > {busy === c.hash ? "…" : "↶ Annuler"} @@ -357,8 +357,8 @@ function DiffView({ diff }: { diff: string }) { function Empty({ children }: { children: React.ReactNode }) { return ( - AUCUN APERÇU - {children} + AUCUN APERÇU + {children} ); } @@ -375,8 +375,8 @@ function Tab({ return ( {children} diff --git a/frontend/src/panels/SettingsView.tsx b/frontend/src/panels/SettingsView.tsx index 32057af..27af20b 100644 --- a/frontend/src/panels/SettingsView.tsx +++ b/frontend/src/panels/SettingsView.tsx @@ -130,13 +130,13 @@ export function SettingsView() { - + {status?.connected ? "Ollama connecté" : "Ollama déconnecté"} {saved ? "✓ ENREGISTRÉ" : dirty ? "ENREGISTRER" : "À JOUR"} @@ -159,7 +159,7 @@ export function SettingsView() { Actualiser @@ -168,7 +168,7 @@ export function SettingsView() { {models.length === 0 && ( - + Aucun modèle installé. Télécharge-en un ci-dessous. )} @@ -179,7 +179,7 @@ export function SettingsView() { return ( @@ -188,7 +188,7 @@ export function SettingsView() { className="flex min-w-0 flex-1 items-center gap-3 text-left" > @@ -196,11 +196,11 @@ export function SettingsView() { - + {m.name} {m.name === status?.default_model && ( - + DÉFAUT )} @@ -237,7 +237,7 @@ export function SettingsView() { doDeleteModel(m.name)} disabled={deletingModel === m.name} - className="flex-none border-2 border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" + className="flex-none border border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" title={`Supprimer ${m.name}`} > {deletingModel === m.name ? "…" : "Supprimer"} @@ -246,18 +246,18 @@ export function SettingsView() { ); })} {deleteError && ( - + {deleteError} )} {warmError && ( - + Préchargement : {warmError} )} - + TÉLÉCHARGER @@ -267,11 +267,11 @@ export function SettingsView() { value={pullName} onChange={(e) => setPullName(e.target.value)} placeholder="gemma2:9b" - className="h-9 flex-1 border-[3px] border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" + className="h-9 flex-1 border border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" /> Récupérer @@ -279,14 +279,14 @@ export function SettingsView() { {pullStatus && ( - + {pullName} {pullStatus} {pullPct ? `· ${pullPct}%` : ""} - + set("num_batch", Math.round(v))} last /> - + La précision KV (f16/q8_0) est un réglage global du serveur Ollama et nécessite son redémarrage. - + Mode réflexion @@ -405,7 +405,7 @@ export function SettingsView() { 0 ? "border-t-2 border-line-soft" : "" + i > 0 ? "border-t border-line-soft" : "" }`} > + Demander une validation avant chaque commande shell @@ -473,7 +473,7 @@ export function SettingsView() { onClick={() => set(key, !draft[key])} /> ))} - + Mémoire @@ -489,7 +489,7 @@ export function SettingsView() { e.target.value as AgentConfig["memory_mode"] ) } - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Désactivée Sur demande @@ -497,7 +497,7 @@ export function SettingsView() { - + Maintien en VRAM (préchargement) @@ -509,7 +509,7 @@ export function SettingsView() { set("keep_alive", e.target.value)} - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Décharger aussitôt 5 min @@ -542,7 +542,7 @@ export function SettingsView() { value={draft.system_prompt} onChange={(e) => set("system_prompt", e.target.value)} rows={6} - className="scr w-full resize-y border-[3px] border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" + className="scr w-full resize-y border border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" /> > @@ -595,10 +595,10 @@ function McpCard() { {servers.map((s) => ( - + doTest(s)} disabled={testing === s.id} - className="border-2 border-line bg-card px-2 py-1 text-[11px] text-ink-2" + className="border border-line bg-card px-2 py-1 text-[11px] text-ink-2" > {testing === s.id ? "test…" : "Tester"} @@ -636,7 +636,7 @@ function McpCard() { defaultValue={s.params.command ?? ""} onBlur={(e) => setParam(s, "command", e.target.value)} placeholder="commande stdio (ex. npx -y mon-mcp) ou URL" - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> )} {s.env_params.map((k) => ( @@ -645,7 +645,7 @@ function McpCard() { defaultValue={s.params[k] ?? ""} onBlur={(e) => setParam(s, k, e.target.value)} placeholder={k} - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> ))} @@ -685,7 +685,7 @@ function HardwareCard() { MATÉRIEL Rafraîchir @@ -698,7 +698,7 @@ function HardwareCard() { {hw?.loki_gpus.length ? ( hw.loki_gpus.map((g) => ( - + {g.name} @@ -709,7 +709,7 @@ function HardwareCard() { )) ) : hw?.gpu_override ? ( - + {hw.gpu_override.name} ·{" "} {(hw.gpu_override.vram_total_mb / 1024).toFixed(0)} Go{" "} (valeur déclarée) @@ -719,7 +719,7 @@ function HardwareCard() { ) : ( - + Aucun GPU visible depuis le conteneur — normal si Ollama tourne sur une autre machine. Déclare GPU_VRAM_MB pour l'auto-réglage. @@ -729,10 +729,10 @@ function HardwareCard() { Ollama {hw?.ollama_is_local ? "(local)" : "(distant)"} - + @@ -820,7 +820,7 @@ function BenchCard() { {running ? "ÉVALUATION…" : "TESTER CE MODÈLE"} @@ -833,7 +833,7 @@ function BenchCard() { {running && ( - + {progress.map((p) => ( {p.task} @@ -850,13 +850,13 @@ function BenchCard() { )} {error && ( - + Échec du test : {error} )} {!running && current && ( - + Score {children} @@ -911,7 +911,7 @@ function Toggle({ on, onClick }: { on: boolean; onClick: () => void }) { apply(e.target.value)} - className="h-[34px] border-[3px] border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" + className="h-[34px] border border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" title="Appliquer un preset" > @@ -983,7 +983,7 @@ function PresetBar({ + Preset @@ -1005,7 +1005,7 @@ function Advanced({ label?: string; }) { return ( - + ▸ {label} @@ -1032,7 +1032,7 @@ function ToggleRow({ return ( @@ -1070,13 +1070,13 @@ function Slider({ {label} {fmt(value)} - + encres sur surface claire + "chrome-2": "#e3e6eb", + "chrome-3": "#c3c9d2", + "on-dark": "#1c2536", + "on-dark-2": "#3d4a5e", + "on-dark-3": "#6b7686", }, fontFamily: { - sans: ['"DM Mono"', "ui-monospace", "monospace"], - mono: ['"DM Mono"', "ui-monospace", "monospace"], - pixel: ['"Press Start 2P"', "ui-monospace", "monospace"], + sans: ['"Inter"', "ui-sans-serif", "system-ui", "sans-serif"], + mono: ["ui-monospace", '"SF Mono"', "Menlo", "monospace"], + // Ex-police pixel : devient le « kicker » de la maquette — petites + // capitales très espacées. Les libellés existants suivent sans edit. + pixel: [ + '"Inter"', + { letterSpacing: "0.14em", fontWeight: "500" }, + ], }, borderRadius: { - card: "9px", + card: "10px", // --radius-md }, boxShadow: { - "hard-sm": "3px 3px 0 #18181b", - hard: "4px 4px 0 #18181b", - "hard-lg": "7px 7px 0 #18181b", - "hard-accent": "3px 3px 0 #ff5436", - "accent-soft": "3px 3px 0 rgba(255,84,54,.4)", - frame: "4px 4px 0 #18181b", + // Ombres douces diffuses (--shadow-sm/md/lg) au lieu des ombres dures. + "hard-sm": "0 1px 2px rgba(28, 37, 54, 0.06)", + hard: "0 2px 8px rgba(28, 37, 54, 0.08)", + "hard-lg": "0 8px 28px rgba(28, 37, 54, 0.10)", + "hard-accent": "0 2px 8px rgba(47, 74, 122, 0.18)", + "accent-soft": "0 1px 2px rgba(47, 74, 122, 0.14)", + frame: "0 2px 8px rgba(28, 37, 54, 0.08)", }, backgroundImage: { - "accent-grad": "linear-gradient(140deg, #ff6b50, #e23e22)", + "accent-grad": "linear-gradient(140deg, #4a6797, #2f4a7a)", }, }, },
{children}
+ $ {command} Approuver & exécuter Refuser @@ -490,7 +490,7 @@ function ShellConfirm({ function Chip({ children }: { children: React.ReactNode }) { return ( - + {children} ); diff --git a/frontend/src/panels/LeftPanel.tsx b/frontend/src/panels/LeftPanel.tsx index 36cff1b..186112b 100644 --- a/frontend/src/panels/LeftPanel.tsx +++ b/frontend/src/panels/LeftPanel.tsx @@ -24,7 +24,7 @@ export function LeftPanel() { }, [refreshSessions, refreshFiles]); return ( - + {/* Historique */} HISTORIQUE @@ -50,7 +50,7 @@ export function LeftPanel() { openSession(s.id)} - className={`group cursor-pointer border-[3px] border-line px-3 py-2.5 ${ + className={`group cursor-pointer border border-line px-3 py-2.5 ${ active ? "bg-card-deep shadow-hard-accent" : "bg-card" }`} style={{ borderRadius: 7 }} @@ -58,14 +58,14 @@ export function LeftPanel() { {s.title} {working && ( EN COURS @@ -93,7 +93,7 @@ export function LeftPanel() { })} - + {/* Fichiers */} @@ -136,7 +136,7 @@ function FileTree({ nodes, depth }: { nodes: FileNode[]; depth: number }) { className={`group mb-[3px] flex items-center gap-2 px-2 py-[5px] ${ n.type === "file" ? active - ? "cursor-pointer border-2 border-line bg-card-deep text-white" + ? "cursor-pointer border border-line bg-card-deep text-ink" : "cursor-pointer text-ink-2 hover:bg-base" : "text-muted" }`} @@ -146,7 +146,7 @@ function FileTree({ nodes, depth }: { nodes: FileNode[]; depth: number }) { ▾ ) : ( diff --git a/frontend/src/panels/PreviewPanel.tsx b/frontend/src/panels/PreviewPanel.tsx index 16f1432..45c3411 100644 --- a/frontend/src/panels/PreviewPanel.tsx +++ b/frontend/src/panels/PreviewPanel.tsx @@ -63,7 +63,7 @@ export function PreviewPanel() { // Replié : barre fine, aucun contenu monté (pas d'iframe vivante). if (collapsed) { return ( - + {/* Onglets */} - + setTab("preview")}> Aperçu @@ -106,7 +106,7 @@ export function PreviewPanel() { setTab("logs")}> Logs - + {logs.length} @@ -125,7 +125,7 @@ export function PreviewPanel() { {/* URL bar */} - + 🔒 {previewPath ? `workspace/${previewPath}` : "workspace/"} @@ -135,7 +135,7 @@ export function PreviewPanel() { <> downloadFile(previewPath, useStore.getState().currentProject())} - className="flex h-8 items-center gap-1.5 border-[3px] border-line bg-card px-2.5 text-[12px] text-accent" + className="flex h-8 items-center gap-1.5 border border-line bg-card px-2.5 text-[12px] text-accent" title={`Télécharger ${previewPath}`} > @@ -147,7 +147,7 @@ export function PreviewPanel() { void removeFile(previewPath); } }} - className="flex h-8 items-center gap-1.5 border-[3px] border-line bg-card px-2.5 text-[12px] text-warn" + className="flex h-8 items-center gap-1.5 border border-line bg-card px-2.5 text-[12px] text-warn" title={`Supprimer ${previewPath}`} > @@ -162,7 +162,7 @@ export function PreviewPanel() { ) : /* Onglet Logs (fond sombre) */ tab === "logs" ? ( - + {logs.length === 0 ? ( Aucune activité d'outil pour cette session. @@ -171,7 +171,7 @@ export function PreviewPanel() { logs.map((l, i) => ( ) : ( /* Viewport Aperçu / Code (fond clair) */ - + {!previewPath ? ( L'aperçu s'affichera ici dès que l'agent générera un fichier (clique aussi un fichier à gauche). ) : tab === "code" ? ( - + {previewContent} ) : isHtml ? ( @@ -225,7 +225,7 @@ export function PreviewPanel() { sandbox="allow-scripts" /> ) : ( - + {previewContent} )} @@ -276,14 +276,14 @@ function GitPanel() { }; return ( - + {error && ( - + {error} )} {/* Liste des commits */} - + {commits.length === 0 ? ( Aucun commit. L'agent commitera chaque modification de code ici. @@ -310,7 +310,7 @@ function GitPanel() { doRevert(c.hash)} disabled={busy === c.hash} - className="flex-none border-2 border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" + className="flex-none border border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" title="Annuler ce commit (revert)" > {busy === c.hash ? "…" : "↶ Annuler"} @@ -357,8 +357,8 @@ function DiffView({ diff }: { diff: string }) { function Empty({ children }: { children: React.ReactNode }) { return ( - AUCUN APERÇU - {children} + AUCUN APERÇU + {children} ); } @@ -375,8 +375,8 @@ function Tab({ return ( {children} diff --git a/frontend/src/panels/SettingsView.tsx b/frontend/src/panels/SettingsView.tsx index 32057af..27af20b 100644 --- a/frontend/src/panels/SettingsView.tsx +++ b/frontend/src/panels/SettingsView.tsx @@ -130,13 +130,13 @@ export function SettingsView() { - + {status?.connected ? "Ollama connecté" : "Ollama déconnecté"} {saved ? "✓ ENREGISTRÉ" : dirty ? "ENREGISTRER" : "À JOUR"} @@ -159,7 +159,7 @@ export function SettingsView() { Actualiser @@ -168,7 +168,7 @@ export function SettingsView() { {models.length === 0 && ( - + Aucun modèle installé. Télécharge-en un ci-dessous. )} @@ -179,7 +179,7 @@ export function SettingsView() { return ( @@ -188,7 +188,7 @@ export function SettingsView() { className="flex min-w-0 flex-1 items-center gap-3 text-left" > @@ -196,11 +196,11 @@ export function SettingsView() { - + {m.name} {m.name === status?.default_model && ( - + DÉFAUT )} @@ -237,7 +237,7 @@ export function SettingsView() { doDeleteModel(m.name)} disabled={deletingModel === m.name} - className="flex-none border-2 border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" + className="flex-none border border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" title={`Supprimer ${m.name}`} > {deletingModel === m.name ? "…" : "Supprimer"} @@ -246,18 +246,18 @@ export function SettingsView() { ); })} {deleteError && ( - + {deleteError} )} {warmError && ( - + Préchargement : {warmError} )} - + TÉLÉCHARGER @@ -267,11 +267,11 @@ export function SettingsView() { value={pullName} onChange={(e) => setPullName(e.target.value)} placeholder="gemma2:9b" - className="h-9 flex-1 border-[3px] border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" + className="h-9 flex-1 border border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" /> Récupérer @@ -279,14 +279,14 @@ export function SettingsView() { {pullStatus && ( - + {pullName} {pullStatus} {pullPct ? `· ${pullPct}%` : ""} - + set("num_batch", Math.round(v))} last /> - + La précision KV (f16/q8_0) est un réglage global du serveur Ollama et nécessite son redémarrage. - + Mode réflexion @@ -405,7 +405,7 @@ export function SettingsView() { 0 ? "border-t-2 border-line-soft" : "" + i > 0 ? "border-t border-line-soft" : "" }`} > + Demander une validation avant chaque commande shell @@ -473,7 +473,7 @@ export function SettingsView() { onClick={() => set(key, !draft[key])} /> ))} - + Mémoire @@ -489,7 +489,7 @@ export function SettingsView() { e.target.value as AgentConfig["memory_mode"] ) } - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Désactivée Sur demande @@ -497,7 +497,7 @@ export function SettingsView() { - + Maintien en VRAM (préchargement) @@ -509,7 +509,7 @@ export function SettingsView() { set("keep_alive", e.target.value)} - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Décharger aussitôt 5 min @@ -542,7 +542,7 @@ export function SettingsView() { value={draft.system_prompt} onChange={(e) => set("system_prompt", e.target.value)} rows={6} - className="scr w-full resize-y border-[3px] border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" + className="scr w-full resize-y border border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" /> > @@ -595,10 +595,10 @@ function McpCard() { {servers.map((s) => ( - + doTest(s)} disabled={testing === s.id} - className="border-2 border-line bg-card px-2 py-1 text-[11px] text-ink-2" + className="border border-line bg-card px-2 py-1 text-[11px] text-ink-2" > {testing === s.id ? "test…" : "Tester"} @@ -636,7 +636,7 @@ function McpCard() { defaultValue={s.params.command ?? ""} onBlur={(e) => setParam(s, "command", e.target.value)} placeholder="commande stdio (ex. npx -y mon-mcp) ou URL" - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> )} {s.env_params.map((k) => ( @@ -645,7 +645,7 @@ function McpCard() { defaultValue={s.params[k] ?? ""} onBlur={(e) => setParam(s, k, e.target.value)} placeholder={k} - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> ))} @@ -685,7 +685,7 @@ function HardwareCard() { MATÉRIEL Rafraîchir @@ -698,7 +698,7 @@ function HardwareCard() { {hw?.loki_gpus.length ? ( hw.loki_gpus.map((g) => ( - + {g.name} @@ -709,7 +709,7 @@ function HardwareCard() { )) ) : hw?.gpu_override ? ( - + {hw.gpu_override.name} ·{" "} {(hw.gpu_override.vram_total_mb / 1024).toFixed(0)} Go{" "} (valeur déclarée) @@ -719,7 +719,7 @@ function HardwareCard() { ) : ( - + Aucun GPU visible depuis le conteneur — normal si Ollama tourne sur une autre machine. Déclare GPU_VRAM_MB pour l'auto-réglage. @@ -729,10 +729,10 @@ function HardwareCard() { Ollama {hw?.ollama_is_local ? "(local)" : "(distant)"} - + @@ -820,7 +820,7 @@ function BenchCard() { {running ? "ÉVALUATION…" : "TESTER CE MODÈLE"} @@ -833,7 +833,7 @@ function BenchCard() { {running && ( - + {progress.map((p) => ( {p.task} @@ -850,13 +850,13 @@ function BenchCard() { )} {error && ( - + Échec du test : {error} )} {!running && current && ( - + Score {children} @@ -911,7 +911,7 @@ function Toggle({ on, onClick }: { on: boolean; onClick: () => void }) { apply(e.target.value)} - className="h-[34px] border-[3px] border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" + className="h-[34px] border border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" title="Appliquer un preset" > @@ -983,7 +983,7 @@ function PresetBar({ + Preset @@ -1005,7 +1005,7 @@ function Advanced({ label?: string; }) { return ( - + ▸ {label} @@ -1032,7 +1032,7 @@ function ToggleRow({ return ( @@ -1070,13 +1070,13 @@ function Slider({ {label} {fmt(value)} - + encres sur surface claire + "chrome-2": "#e3e6eb", + "chrome-3": "#c3c9d2", + "on-dark": "#1c2536", + "on-dark-2": "#3d4a5e", + "on-dark-3": "#6b7686", }, fontFamily: { - sans: ['"DM Mono"', "ui-monospace", "monospace"], - mono: ['"DM Mono"', "ui-monospace", "monospace"], - pixel: ['"Press Start 2P"', "ui-monospace", "monospace"], + sans: ['"Inter"', "ui-sans-serif", "system-ui", "sans-serif"], + mono: ["ui-monospace", '"SF Mono"', "Menlo", "monospace"], + // Ex-police pixel : devient le « kicker » de la maquette — petites + // capitales très espacées. Les libellés existants suivent sans edit. + pixel: [ + '"Inter"', + { letterSpacing: "0.14em", fontWeight: "500" }, + ], }, borderRadius: { - card: "9px", + card: "10px", // --radius-md }, boxShadow: { - "hard-sm": "3px 3px 0 #18181b", - hard: "4px 4px 0 #18181b", - "hard-lg": "7px 7px 0 #18181b", - "hard-accent": "3px 3px 0 #ff5436", - "accent-soft": "3px 3px 0 rgba(255,84,54,.4)", - frame: "4px 4px 0 #18181b", + // Ombres douces diffuses (--shadow-sm/md/lg) au lieu des ombres dures. + "hard-sm": "0 1px 2px rgba(28, 37, 54, 0.06)", + hard: "0 2px 8px rgba(28, 37, 54, 0.08)", + "hard-lg": "0 8px 28px rgba(28, 37, 54, 0.10)", + "hard-accent": "0 2px 8px rgba(47, 74, 122, 0.18)", + "accent-soft": "0 1px 2px rgba(47, 74, 122, 0.14)", + frame: "0 2px 8px rgba(28, 37, 54, 0.08)", }, backgroundImage: { - "accent-grad": "linear-gradient(140deg, #ff6b50, #e23e22)", + "accent-grad": "linear-gradient(140deg, #4a6797, #2f4a7a)", }, }, },
$ {command}
+ {previewContent} ) : isHtml ? ( @@ -225,7 +225,7 @@ export function PreviewPanel() { sandbox="allow-scripts" /> ) : ( - + {previewContent} )} @@ -276,14 +276,14 @@ function GitPanel() { }; return ( - + {error && ( - + {error} )} {/* Liste des commits */} - + {commits.length === 0 ? ( Aucun commit. L'agent commitera chaque modification de code ici. @@ -310,7 +310,7 @@ function GitPanel() { doRevert(c.hash)} disabled={busy === c.hash} - className="flex-none border-2 border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" + className="flex-none border border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" title="Annuler ce commit (revert)" > {busy === c.hash ? "…" : "↶ Annuler"} @@ -357,8 +357,8 @@ function DiffView({ diff }: { diff: string }) { function Empty({ children }: { children: React.ReactNode }) { return ( - AUCUN APERÇU - {children} + AUCUN APERÇU + {children} ); } @@ -375,8 +375,8 @@ function Tab({ return ( {children} diff --git a/frontend/src/panels/SettingsView.tsx b/frontend/src/panels/SettingsView.tsx index 32057af..27af20b 100644 --- a/frontend/src/panels/SettingsView.tsx +++ b/frontend/src/panels/SettingsView.tsx @@ -130,13 +130,13 @@ export function SettingsView() { - + {status?.connected ? "Ollama connecté" : "Ollama déconnecté"} {saved ? "✓ ENREGISTRÉ" : dirty ? "ENREGISTRER" : "À JOUR"} @@ -159,7 +159,7 @@ export function SettingsView() { Actualiser @@ -168,7 +168,7 @@ export function SettingsView() { {models.length === 0 && ( - + Aucun modèle installé. Télécharge-en un ci-dessous. )} @@ -179,7 +179,7 @@ export function SettingsView() { return ( @@ -188,7 +188,7 @@ export function SettingsView() { className="flex min-w-0 flex-1 items-center gap-3 text-left" > @@ -196,11 +196,11 @@ export function SettingsView() { - + {m.name} {m.name === status?.default_model && ( - + DÉFAUT )} @@ -237,7 +237,7 @@ export function SettingsView() { doDeleteModel(m.name)} disabled={deletingModel === m.name} - className="flex-none border-2 border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" + className="flex-none border border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" title={`Supprimer ${m.name}`} > {deletingModel === m.name ? "…" : "Supprimer"} @@ -246,18 +246,18 @@ export function SettingsView() { ); })} {deleteError && ( - + {deleteError} )} {warmError && ( - + Préchargement : {warmError} )} - + TÉLÉCHARGER @@ -267,11 +267,11 @@ export function SettingsView() { value={pullName} onChange={(e) => setPullName(e.target.value)} placeholder="gemma2:9b" - className="h-9 flex-1 border-[3px] border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" + className="h-9 flex-1 border border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" /> Récupérer @@ -279,14 +279,14 @@ export function SettingsView() { {pullStatus && ( - + {pullName} {pullStatus} {pullPct ? `· ${pullPct}%` : ""} - + set("num_batch", Math.round(v))} last /> - + La précision KV (f16/q8_0) est un réglage global du serveur Ollama et nécessite son redémarrage. - + Mode réflexion @@ -405,7 +405,7 @@ export function SettingsView() { 0 ? "border-t-2 border-line-soft" : "" + i > 0 ? "border-t border-line-soft" : "" }`} > + Demander une validation avant chaque commande shell @@ -473,7 +473,7 @@ export function SettingsView() { onClick={() => set(key, !draft[key])} /> ))} - + Mémoire @@ -489,7 +489,7 @@ export function SettingsView() { e.target.value as AgentConfig["memory_mode"] ) } - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Désactivée Sur demande @@ -497,7 +497,7 @@ export function SettingsView() { - + Maintien en VRAM (préchargement) @@ -509,7 +509,7 @@ export function SettingsView() { set("keep_alive", e.target.value)} - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Décharger aussitôt 5 min @@ -542,7 +542,7 @@ export function SettingsView() { value={draft.system_prompt} onChange={(e) => set("system_prompt", e.target.value)} rows={6} - className="scr w-full resize-y border-[3px] border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" + className="scr w-full resize-y border border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" /> > @@ -595,10 +595,10 @@ function McpCard() { {servers.map((s) => ( - + doTest(s)} disabled={testing === s.id} - className="border-2 border-line bg-card px-2 py-1 text-[11px] text-ink-2" + className="border border-line bg-card px-2 py-1 text-[11px] text-ink-2" > {testing === s.id ? "test…" : "Tester"} @@ -636,7 +636,7 @@ function McpCard() { defaultValue={s.params.command ?? ""} onBlur={(e) => setParam(s, "command", e.target.value)} placeholder="commande stdio (ex. npx -y mon-mcp) ou URL" - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> )} {s.env_params.map((k) => ( @@ -645,7 +645,7 @@ function McpCard() { defaultValue={s.params[k] ?? ""} onBlur={(e) => setParam(s, k, e.target.value)} placeholder={k} - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> ))} @@ -685,7 +685,7 @@ function HardwareCard() { MATÉRIEL Rafraîchir @@ -698,7 +698,7 @@ function HardwareCard() { {hw?.loki_gpus.length ? ( hw.loki_gpus.map((g) => ( - + {g.name} @@ -709,7 +709,7 @@ function HardwareCard() { )) ) : hw?.gpu_override ? ( - + {hw.gpu_override.name} ·{" "} {(hw.gpu_override.vram_total_mb / 1024).toFixed(0)} Go{" "} (valeur déclarée) @@ -719,7 +719,7 @@ function HardwareCard() { ) : ( - + Aucun GPU visible depuis le conteneur — normal si Ollama tourne sur une autre machine. Déclare GPU_VRAM_MB pour l'auto-réglage. @@ -729,10 +729,10 @@ function HardwareCard() { Ollama {hw?.ollama_is_local ? "(local)" : "(distant)"} - + @@ -820,7 +820,7 @@ function BenchCard() { {running ? "ÉVALUATION…" : "TESTER CE MODÈLE"} @@ -833,7 +833,7 @@ function BenchCard() { {running && ( - + {progress.map((p) => ( {p.task} @@ -850,13 +850,13 @@ function BenchCard() { )} {error && ( - + Échec du test : {error} )} {!running && current && ( - + Score {children} @@ -911,7 +911,7 @@ function Toggle({ on, onClick }: { on: boolean; onClick: () => void }) { apply(e.target.value)} - className="h-[34px] border-[3px] border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" + className="h-[34px] border border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" title="Appliquer un preset" > @@ -983,7 +983,7 @@ function PresetBar({ + Preset @@ -1005,7 +1005,7 @@ function Advanced({ label?: string; }) { return ( - + ▸ {label} @@ -1032,7 +1032,7 @@ function ToggleRow({ return ( @@ -1070,13 +1070,13 @@ function Slider({ {label} {fmt(value)} - + encres sur surface claire + "chrome-2": "#e3e6eb", + "chrome-3": "#c3c9d2", + "on-dark": "#1c2536", + "on-dark-2": "#3d4a5e", + "on-dark-3": "#6b7686", }, fontFamily: { - sans: ['"DM Mono"', "ui-monospace", "monospace"], - mono: ['"DM Mono"', "ui-monospace", "monospace"], - pixel: ['"Press Start 2P"', "ui-monospace", "monospace"], + sans: ['"Inter"', "ui-sans-serif", "system-ui", "sans-serif"], + mono: ["ui-monospace", '"SF Mono"', "Menlo", "monospace"], + // Ex-police pixel : devient le « kicker » de la maquette — petites + // capitales très espacées. Les libellés existants suivent sans edit. + pixel: [ + '"Inter"', + { letterSpacing: "0.14em", fontWeight: "500" }, + ], }, borderRadius: { - card: "9px", + card: "10px", // --radius-md }, boxShadow: { - "hard-sm": "3px 3px 0 #18181b", - hard: "4px 4px 0 #18181b", - "hard-lg": "7px 7px 0 #18181b", - "hard-accent": "3px 3px 0 #ff5436", - "accent-soft": "3px 3px 0 rgba(255,84,54,.4)", - frame: "4px 4px 0 #18181b", + // Ombres douces diffuses (--shadow-sm/md/lg) au lieu des ombres dures. + "hard-sm": "0 1px 2px rgba(28, 37, 54, 0.06)", + hard: "0 2px 8px rgba(28, 37, 54, 0.08)", + "hard-lg": "0 8px 28px rgba(28, 37, 54, 0.10)", + "hard-accent": "0 2px 8px rgba(47, 74, 122, 0.18)", + "accent-soft": "0 1px 2px rgba(47, 74, 122, 0.14)", + frame: "0 2px 8px rgba(28, 37, 54, 0.08)", }, backgroundImage: { - "accent-grad": "linear-gradient(140deg, #ff6b50, #e23e22)", + "accent-grad": "linear-gradient(140deg, #4a6797, #2f4a7a)", }, }, },
{previewContent}
+ {previewContent} )} @@ -276,14 +276,14 @@ function GitPanel() { }; return ( - + {error && ( - + {error} )} {/* Liste des commits */} - + {commits.length === 0 ? ( Aucun commit. L'agent commitera chaque modification de code ici. @@ -310,7 +310,7 @@ function GitPanel() { doRevert(c.hash)} disabled={busy === c.hash} - className="flex-none border-2 border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" + className="flex-none border border-line bg-card px-2 py-1 text-[11px] text-warn disabled:opacity-40" title="Annuler ce commit (revert)" > {busy === c.hash ? "…" : "↶ Annuler"} @@ -357,8 +357,8 @@ function DiffView({ diff }: { diff: string }) { function Empty({ children }: { children: React.ReactNode }) { return ( - AUCUN APERÇU - {children} + AUCUN APERÇU + {children} ); } @@ -375,8 +375,8 @@ function Tab({ return ( {children} diff --git a/frontend/src/panels/SettingsView.tsx b/frontend/src/panels/SettingsView.tsx index 32057af..27af20b 100644 --- a/frontend/src/panels/SettingsView.tsx +++ b/frontend/src/panels/SettingsView.tsx @@ -130,13 +130,13 @@ export function SettingsView() { - + {status?.connected ? "Ollama connecté" : "Ollama déconnecté"} {saved ? "✓ ENREGISTRÉ" : dirty ? "ENREGISTRER" : "À JOUR"} @@ -159,7 +159,7 @@ export function SettingsView() { Actualiser @@ -168,7 +168,7 @@ export function SettingsView() { {models.length === 0 && ( - + Aucun modèle installé. Télécharge-en un ci-dessous. )} @@ -179,7 +179,7 @@ export function SettingsView() { return ( @@ -188,7 +188,7 @@ export function SettingsView() { className="flex min-w-0 flex-1 items-center gap-3 text-left" > @@ -196,11 +196,11 @@ export function SettingsView() { - + {m.name} {m.name === status?.default_model && ( - + DÉFAUT )} @@ -237,7 +237,7 @@ export function SettingsView() { doDeleteModel(m.name)} disabled={deletingModel === m.name} - className="flex-none border-2 border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" + className="flex-none border border-line bg-base px-2 py-1 text-[12px] text-warn disabled:opacity-50" title={`Supprimer ${m.name}`} > {deletingModel === m.name ? "…" : "Supprimer"} @@ -246,18 +246,18 @@ export function SettingsView() { ); })} {deleteError && ( - + {deleteError} )} {warmError && ( - + Préchargement : {warmError} )} - + TÉLÉCHARGER @@ -267,11 +267,11 @@ export function SettingsView() { value={pullName} onChange={(e) => setPullName(e.target.value)} placeholder="gemma2:9b" - className="h-9 flex-1 border-[3px] border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" + className="h-9 flex-1 border border-line bg-card-soft px-3 text-[13px] text-ink outline-none placeholder:text-muted-3" /> Récupérer @@ -279,14 +279,14 @@ export function SettingsView() { {pullStatus && ( - + {pullName} {pullStatus} {pullPct ? `· ${pullPct}%` : ""} - + set("num_batch", Math.round(v))} last /> - + La précision KV (f16/q8_0) est un réglage global du serveur Ollama et nécessite son redémarrage. - + Mode réflexion @@ -405,7 +405,7 @@ export function SettingsView() { 0 ? "border-t-2 border-line-soft" : "" + i > 0 ? "border-t border-line-soft" : "" }`} > + Demander une validation avant chaque commande shell @@ -473,7 +473,7 @@ export function SettingsView() { onClick={() => set(key, !draft[key])} /> ))} - + Mémoire @@ -489,7 +489,7 @@ export function SettingsView() { e.target.value as AgentConfig["memory_mode"] ) } - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Désactivée Sur demande @@ -497,7 +497,7 @@ export function SettingsView() { - + Maintien en VRAM (préchargement) @@ -509,7 +509,7 @@ export function SettingsView() { set("keep_alive", e.target.value)} - className="h-8 border-[3px] border-line bg-card px-2 text-[13px] text-ink" + className="h-8 border border-line bg-card px-2 text-[13px] text-ink" > Décharger aussitôt 5 min @@ -542,7 +542,7 @@ export function SettingsView() { value={draft.system_prompt} onChange={(e) => set("system_prompt", e.target.value)} rows={6} - className="scr w-full resize-y border-[3px] border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" + className="scr w-full resize-y border border-line bg-card-deep p-4 text-[13px] leading-[1.6] text-on-dark outline-none" /> > @@ -595,10 +595,10 @@ function McpCard() { {servers.map((s) => ( - + doTest(s)} disabled={testing === s.id} - className="border-2 border-line bg-card px-2 py-1 text-[11px] text-ink-2" + className="border border-line bg-card px-2 py-1 text-[11px] text-ink-2" > {testing === s.id ? "test…" : "Tester"} @@ -636,7 +636,7 @@ function McpCard() { defaultValue={s.params.command ?? ""} onBlur={(e) => setParam(s, "command", e.target.value)} placeholder="commande stdio (ex. npx -y mon-mcp) ou URL" - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> )} {s.env_params.map((k) => ( @@ -645,7 +645,7 @@ function McpCard() { defaultValue={s.params[k] ?? ""} onBlur={(e) => setParam(s, k, e.target.value)} placeholder={k} - className="border-2 border-line bg-card px-2 py-1 text-[12px] text-ink" + className="border border-line bg-card px-2 py-1 text-[12px] text-ink" /> ))} @@ -685,7 +685,7 @@ function HardwareCard() { MATÉRIEL Rafraîchir @@ -698,7 +698,7 @@ function HardwareCard() { {hw?.loki_gpus.length ? ( hw.loki_gpus.map((g) => ( - + {g.name} @@ -709,7 +709,7 @@ function HardwareCard() { )) ) : hw?.gpu_override ? ( - + {hw.gpu_override.name} ·{" "} {(hw.gpu_override.vram_total_mb / 1024).toFixed(0)} Go{" "} (valeur déclarée) @@ -719,7 +719,7 @@ function HardwareCard() { ) : ( - + Aucun GPU visible depuis le conteneur — normal si Ollama tourne sur une autre machine. Déclare GPU_VRAM_MB pour l'auto-réglage. @@ -729,10 +729,10 @@ function HardwareCard() { Ollama {hw?.ollama_is_local ? "(local)" : "(distant)"} - + @@ -820,7 +820,7 @@ function BenchCard() { {running ? "ÉVALUATION…" : "TESTER CE MODÈLE"} @@ -833,7 +833,7 @@ function BenchCard() { {running && ( - + {progress.map((p) => ( {p.task} @@ -850,13 +850,13 @@ function BenchCard() { )} {error && ( - + Échec du test : {error} )} {!running && current && ( - + Score {children} @@ -911,7 +911,7 @@ function Toggle({ on, onClick }: { on: boolean; onClick: () => void }) { apply(e.target.value)} - className="h-[34px] border-[3px] border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" + className="h-[34px] border border-line bg-card px-2 text-[13px] text-ink disabled:opacity-40" title="Appliquer un preset" > @@ -983,7 +983,7 @@ function PresetBar({ + Preset @@ -1005,7 +1005,7 @@ function Advanced({ label?: string; }) { return ( - + ▸ {label} @@ -1032,7 +1032,7 @@ function ToggleRow({ return ( @@ -1070,13 +1070,13 @@ function Slider({ {label} {fmt(value)} - + encres sur surface claire + "chrome-2": "#e3e6eb", + "chrome-3": "#c3c9d2", + "on-dark": "#1c2536", + "on-dark-2": "#3d4a5e", + "on-dark-3": "#6b7686", }, fontFamily: { - sans: ['"DM Mono"', "ui-monospace", "monospace"], - mono: ['"DM Mono"', "ui-monospace", "monospace"], - pixel: ['"Press Start 2P"', "ui-monospace", "monospace"], + sans: ['"Inter"', "ui-sans-serif", "system-ui", "sans-serif"], + mono: ["ui-monospace", '"SF Mono"', "Menlo", "monospace"], + // Ex-police pixel : devient le « kicker » de la maquette — petites + // capitales très espacées. Les libellés existants suivent sans edit. + pixel: [ + '"Inter"', + { letterSpacing: "0.14em", fontWeight: "500" }, + ], }, borderRadius: { - card: "9px", + card: "10px", // --radius-md }, boxShadow: { - "hard-sm": "3px 3px 0 #18181b", - hard: "4px 4px 0 #18181b", - "hard-lg": "7px 7px 0 #18181b", - "hard-accent": "3px 3px 0 #ff5436", - "accent-soft": "3px 3px 0 rgba(255,84,54,.4)", - frame: "4px 4px 0 #18181b", + // Ombres douces diffuses (--shadow-sm/md/lg) au lieu des ombres dures. + "hard-sm": "0 1px 2px rgba(28, 37, 54, 0.06)", + hard: "0 2px 8px rgba(28, 37, 54, 0.08)", + "hard-lg": "0 8px 28px rgba(28, 37, 54, 0.10)", + "hard-accent": "0 2px 8px rgba(47, 74, 122, 0.18)", + "accent-soft": "0 1px 2px rgba(47, 74, 122, 0.14)", + frame: "0 2px 8px rgba(28, 37, 54, 0.08)", }, backgroundImage: { - "accent-grad": "linear-gradient(140deg, #ff6b50, #e23e22)", + "accent-grad": "linear-gradient(140deg, #4a6797, #2f4a7a)", }, }, },
f16
q8_0
GPU_VRAM_MB