mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-16 19:59:56 +02:00
Thème Nocturne clair (Claude Design) à la place du néo-brutaliste
Reprend les jetons de « Loki App.dc.html » : fond gris froid #f7f8fa, surfaces blanches, accent bleu ardoise #2f4a7a (au lieu de l'orange), filets 1 px #e3e6eb (au lieu des bordures noires 3 px) et ombres douces diffuses (au lieu des ombres dures décalées). - tailwind.config.ts : les NOMS de jetons sont conservés, seules leurs valeurs basculent — toute l'interface suit sans réécrire les composants. Les jetons historiquement sombres (card-deep, on-dark…) deviennent la surface sélectionnée claire et son encre. - Police unique Inter ; l'ex-« font-pixel » devient le kicker de la maquette (petites capitales espacées de 0.14em), donc les libellés existants suivent sans modification. - Conversion mécanique des filets 3 px / 2 px vers 1 px, séparateurs épais affinés, logo et avatar refaits selon la maquette (carré teinté à filet accent), couleurs « papier » de l'aperçu passées en jetons. - Texte blanc corrigé partout où il reposait sur une surface devenue claire ; conservé sur les fonds accent/warn où il reste lisible. Vérifié au rendu : body #f7f8fa, encre #1c2536, surface #ffffff, Inter ; plus aucune trace d'orange, de noir #18181b ni d'ombre dure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SVay7z3y7q2gEe54ByAE6N
This commit is contained in:
16 files changed
+254
-215
No files matched your search
@@ -16,10 +16,10 @@ const items: { id: View; label: string; icon: React.ReactNode }[] = [
|
||||
];
|
||||
|
||||
const btn = (on: boolean) =>
|
||||
`flex h-10 w-10 items-center justify-center border-[3px] ${
|
||||
`flex h-10 w-10 items-center justify-center border ${
|
||||
on
|
||||
? "border-white bg-accent text-white shadow-accent-soft"
|
||||
: "border-chrome-3 text-on-dark-2 hover:text-white"
|
||||
: "border-chrome-3 text-on-dark-2 hover:text-ink"
|
||||
}`;
|
||||
|
||||
/** Barre d'activité verticale (60px) sombre à gauche. */
|
||||
@@ -31,7 +31,7 @@ export function ActivityBar({
|
||||
onChange: (v: View) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex w-[60px] flex-none flex-col items-center gap-2 border-r-[3px] border-line bg-bar py-3">
|
||||
<div className="flex w-[60px] flex-none flex-col items-center gap-2 border-r border-line bg-bar py-3">
|
||||
{items.map((it) => (
|
||||
<button
|
||||
key={it.id}
|
||||
@@ -55,7 +55,7 @@ export function ActivityBar({
|
||||
<SettingsIcon />
|
||||
</button>
|
||||
|
||||
<div className="font-pixel flex h-[34px] w-[34px] items-center justify-center border-[3px] border-white bg-white text-[11px] text-line">
|
||||
<div className="font-pixel flex h-[34px] w-[34px] items-center justify-center border border-line bg-line-soft text-[11px] text-ink-3">
|
||||
M
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -104,20 +104,23 @@ export const CheckIcon = ({ size = 14, className }: Props) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
/** Logo Loki : carré orange à bordure blanche + carré interne (néo-brutaliste). */
|
||||
/** Logo Loki : carré teinté à filet accent + petit carré accent (maquette). */
|
||||
export const LokiMark = ({ size = 30 }: { size?: number }) => (
|
||||
<div
|
||||
className="flex items-center justify-center bg-accent"
|
||||
className="grid place-items-center border border-accent bg-accent-ghost"
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
border: "3px solid #fff",
|
||||
boxShadow: "3px 3px 0 #ff5436",
|
||||
borderRadius: 7,
|
||||
borderRadius: Math.round(size * 0.27),
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ width: size * 0.3, height: size * 0.3, background: "#fff" }}
|
||||
className="bg-accent"
|
||||
style={{
|
||||
width: size * 0.3,
|
||||
height: size * 0.3,
|
||||
borderRadius: 2,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -45,15 +45,15 @@ function CodeBlock({ lang, code }: { lang: string; code: string }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="my-2 overflow-hidden border-[3px] border-line bg-card-deep shadow-hard-sm" style={{ borderRadius: 7 }}>
|
||||
<div className="flex items-center justify-between border-b-2 border-chrome-2 px-3 py-1.5">
|
||||
<div className="my-2 overflow-hidden border border-line bg-card-deep shadow-hard-sm" style={{ borderRadius: 7 }}>
|
||||
<div className="flex items-center justify-between border-b border-chrome-2 px-3 py-1.5">
|
||||
<span className="font-mono text-[10.5px] uppercase tracking-wide text-on-dark-2">
|
||||
{lang || "code"}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={copy}
|
||||
className="flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] text-on-dark-2 transition-colors hover:text-white"
|
||||
className="flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] text-on-dark-2 transition-colors hover:text-ink"
|
||||
>
|
||||
{copied ? <CheckIcon size={13} /> : <CopyIcon size={13} />}
|
||||
{failed ? "Erreur" : copied ? "Copié" : "Copier"}
|
||||
@@ -122,7 +122,7 @@ const components: Components = {
|
||||
),
|
||||
em: ({ children }) => <em className="italic">{children}</em>,
|
||||
blockquote: ({ children }) => (
|
||||
<blockquote className="my-2 border-l-2 border-line-strong pl-3 text-muted">
|
||||
<blockquote className="my-2 border-l border-line-strong pl-3 text-muted">
|
||||
{children}
|
||||
</blockquote>
|
||||
),
|
||||
|
||||
@@ -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 }}
|
||||
>
|
||||
<span
|
||||
className={`h-2.5 w-2.5 border-2 border-line ${
|
||||
className={`h-2.5 w-2.5 border border-line ${
|
||||
warmingModel === selectedModel
|
||||
? "bg-accent animate-pulse"
|
||||
: selectedLoaded
|
||||
@@ -74,7 +74,7 @@ export function ModelSelector({
|
||||
|
||||
{open && (
|
||||
<div
|
||||
className={`absolute z-20 w-64 border-[3px] border-line bg-card p-1 shadow-hard ${
|
||||
className={`absolute z-20 w-64 border border-line bg-card p-1 shadow-hard ${
|
||||
variant === "composer"
|
||||
? "bottom-[calc(100%+6px)] left-0"
|
||||
: "right-0 top-11"
|
||||
@@ -97,7 +97,7 @@ export function ModelSelector({
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`h-2 w-2 border-2 border-line ${
|
||||
className={`h-2 w-2 border border-line ${
|
||||
m.name === selectedModel ? "bg-accent" : "bg-card"
|
||||
}`}
|
||||
/>
|
||||
|
||||
@@ -52,7 +52,7 @@ export function ProjectChip() {
|
||||
<div ref={rootRef} className="relative">
|
||||
<button
|
||||
onClick={() => 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"
|
||||
>
|
||||
📁 <span className="max-w-[140px] truncate">{active ?? "workspace"}</span>
|
||||
@@ -60,7 +60,7 @@ export function ProjectChip() {
|
||||
|
||||
{open && (
|
||||
<div
|
||||
className="absolute bottom-[calc(100%+6px)] left-0 z-30 w-[240px] border-[3px] border-line bg-card shadow-hard"
|
||||
className="absolute bottom-[calc(100%+6px)] left-0 z-30 w-[240px] border border-line bg-card shadow-hard"
|
||||
style={{ borderRadius: 7 }}
|
||||
>
|
||||
<button
|
||||
@@ -75,7 +75,7 @@ export function ProjectChip() {
|
||||
<button
|
||||
key={p.name}
|
||||
onClick={() => 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() {
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
<div className="border-t-2 border-line-soft p-2">
|
||||
<div className="border-t border-line-soft p-2">
|
||||
{creating ? (
|
||||
<input
|
||||
autoFocus
|
||||
@@ -99,7 +99,7 @@ export function ProjectChip() {
|
||||
}
|
||||
}}
|
||||
placeholder="nom-du-projet"
|
||||
className="w-full border-2 border-line bg-base px-2 py-1 text-[12px] text-ink outline-none"
|
||||
className="w-full border border-line bg-base px-2 py-1 text-[12px] text-ink outline-none"
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
|
||||
@@ -55,7 +55,7 @@ export function SessionMenu() {
|
||||
<div ref={rootRef} className="relative">
|
||||
<button
|
||||
onClick={() => 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"
|
||||
>
|
||||
<span className="max-w-[220px] truncate">
|
||||
@@ -66,7 +66,7 @@ export function SessionMenu() {
|
||||
|
||||
{open && (
|
||||
<div
|
||||
className="absolute left-0 top-[calc(100%+9px)] z-30 w-[300px] border-[3px] border-line bg-chrome-2 shadow-hard"
|
||||
className="absolute left-0 top-[calc(100%+9px)] z-30 w-[300px] border border-line bg-chrome-2 shadow-hard"
|
||||
style={{ borderRadius: 7 }}
|
||||
>
|
||||
<button
|
||||
@@ -74,7 +74,7 @@ export function SessionMenu() {
|
||||
setOpen(false);
|
||||
await newSession();
|
||||
}}
|
||||
className="flex w-full cursor-pointer items-center gap-2 border-b-[3px] border-chrome-3 px-3 py-2.5 text-[13px] font-bold text-accent hover:bg-chrome-3"
|
||||
className="flex w-full cursor-pointer items-center gap-2 border-b border-chrome-3 px-3 py-2.5 text-[13px] font-bold text-accent hover:bg-chrome-3"
|
||||
>
|
||||
<PlusIcon />
|
||||
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"
|
||||
/>
|
||||
) : (
|
||||
<span
|
||||
className={`min-w-0 flex-1 truncate text-[13px] ${
|
||||
active ? "text-white" : "text-on-dark"
|
||||
active ? "text-ink" : "text-ink-3"
|
||||
}`}
|
||||
>
|
||||
{s.title}
|
||||
@@ -129,7 +129,7 @@ export function SessionMenu() {
|
||||
)}
|
||||
{working && (
|
||||
<span
|
||||
className="flex-none border-2 border-line bg-accent px-1 py-0.5 text-[9px] leading-none text-white"
|
||||
className="flex-none border border-line bg-accent px-1 py-0.5 text-[9px] leading-none text-white"
|
||||
title="Session en cours de travail"
|
||||
>
|
||||
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"
|
||||
>
|
||||
✎
|
||||
|
||||
@@ -23,11 +23,11 @@ export function ToolCard({ call }: { call: ToolCall }) {
|
||||
const write = call.name === "write_file" || call.name === "edit_file";
|
||||
|
||||
return (
|
||||
<div className="mb-[11px] overflow-hidden border-[3px] border-line bg-card shadow-hard-sm" style={{ borderRadius: 7 }}>
|
||||
<div className="mb-[11px] overflow-hidden border border-line bg-card shadow-hard-sm" style={{ borderRadius: 7 }}>
|
||||
<div className="flex items-center gap-2.5 px-3 py-2.5">
|
||||
<span
|
||||
className={`flex h-[26px] w-[26px] items-center justify-center border-2 border-line ${
|
||||
write ? "bg-accent text-white" : "bg-card-deep text-white"
|
||||
className={`flex h-[26px] w-[26px] items-center justify-center border border-line ${
|
||||
write ? "bg-accent text-white" : "bg-card-deep text-ink"
|
||||
}`}
|
||||
>
|
||||
<ToolGlyph name={call.name} />
|
||||
@@ -37,7 +37,7 @@ export function ToolCard({ call }: { call: ToolCall }) {
|
||||
<div className="flex-1" />
|
||||
{running ? (
|
||||
<span className="flex items-center gap-1.5 text-[13px] text-muted-2">
|
||||
<span className="h-2.5 w-2.5 animate-spin rounded-full border-2 border-muted-3 border-t-accent" />
|
||||
<span className="h-2.5 w-2.5 animate-spin rounded-full border border-muted-3 border-t-accent" />
|
||||
en cours
|
||||
</span>
|
||||
) : pending ? (
|
||||
@@ -53,7 +53,7 @@ export function ToolCard({ call }: { call: ToolCall }) {
|
||||
)}
|
||||
</div>
|
||||
{call.summary && !running && (
|
||||
<div className="border-t-2 border-line-soft px-3 py-2 text-[13px] text-muted-2">
|
||||
<div className="border-t border-line-soft px-3 py-2 text-[13px] text-muted-2">
|
||||
→ {call.summary}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -16,10 +16,10 @@ export function TopBar() {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex h-[54px] flex-none items-center gap-3.5 border-b-[3px] border-line bg-bar px-4">
|
||||
<div className="flex h-[54px] flex-none items-center gap-3.5 border-b border-line bg-bar px-4">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<LokiMark />
|
||||
<div className="font-pixel text-[14px] text-white">LOKI</div>
|
||||
<div className="font-pixel text-[14px] text-ink">LOKI</div>
|
||||
<div
|
||||
className="text-[13px] leading-none text-on-dark-2"
|
||||
title={version ? `build ${version}` : undefined}
|
||||
@@ -39,7 +39,7 @@ export function TopBar() {
|
||||
|
||||
{/* Stats système temps réel : CPU, RAM, GPU/VRAM */}
|
||||
{stats && (
|
||||
<div className="flex h-8 items-center gap-2.5 border-[3px] border-chrome-3 bg-chrome-2 px-[11px] text-[13px] text-on-dark">
|
||||
<div className="flex h-8 items-center gap-2.5 border border-chrome-3 bg-chrome-2 px-[11px] text-[13px] text-on-dark">
|
||||
<span>CPU {stats.cpu_pct.toFixed(0)}%</span>
|
||||
<span className="text-on-dark-3">·</span>
|
||||
<span>RAM {stats.ram_pct.toFixed(0)}%</span>
|
||||
@@ -58,11 +58,11 @@ export function TopBar() {
|
||||
|
||||
{/* Statut Ollama */}
|
||||
<div
|
||||
className="flex h-8 items-center gap-2 border-[3px] border-chrome-3 bg-chrome-2 px-[11px]"
|
||||
className="flex h-8 items-center gap-2 border border-chrome-3 bg-chrome-2 px-[11px]"
|
||||
title={connected ? status?.host : status?.error}
|
||||
>
|
||||
<span
|
||||
className={`h-[11px] w-[11px] border-2 border-line ${
|
||||
className={`h-[11px] w-[11px] border border-line ${
|
||||
connected ? "bg-ok" : "bg-warn"
|
||||
}`}
|
||||
/>
|
||||
|
||||
Reference in new issue
Block a user