feat(web): couche de tokens de design centralisée (surfaces, statuts, terminal)
Some checks failed
CI / Build & test (Node 24) (push) Has been cancelled
CI / Pack & boot smoke (Node 22) (push) Has been cancelled
CI / No em/en dashes (push) Has been cancelled
CI / Build & test (Node 22) (push) Has been cancelled

Introduit une couche sémantique dans style.css (@theme) : surfaces (surface-0..3), bordures, texte (fg/muted/subtle) et accent, aliasant la palette Tailwind (rendu identique, vérifié dans le CSS produit). Ajoute les métriques du chrome IDE (--ide-*) pour la refonte à venir.

Centralise deux sources uniques : lib/terminal-theme.ts (thème + police xterm) et lib/status-tokens.ts (tons de statut, dédupliqués entre BaseBadge et SessionStateBadge). Définit le thème Monaco « arboretum-dark ». Remplace les #09090b épars des composants par bg-surface-0 (ne restent que index.html et les renderers exigeant un hex concret).
This commit is contained in:
2026-07-17 16:50:58 +02:00
parent 65ef616867
commit 9a496abd00
12 changed files with 129 additions and 57 deletions

View File

@@ -1,9 +1,41 @@
@import 'tailwindcss';
/* Tokens additifs (la palette zinc/emerald/amber/sky/red reste celle de Tailwind). */
/* Tokens de design centralisés.
Couche SÉMANTIQUE aliasant la palette Tailwind (zinc/emerald/amber/sky/red) : rendu
identique aujourd'hui, mais un point d'entrée unique pour la refonte IDE et un futur
thème clair (il suffirait de redéfinir ces variables sous [data-theme=light]). */
@theme {
--shadow-card: 0 1px 2px 0 rgb(0 0 0 / 0.4);
--shadow-pop: 0 12px 32px -12px rgb(0 0 0 / 0.7);
/* Surfaces : du fond le plus profond de l'app aux surfaces survolées. */
--color-surface-0: var(--color-zinc-950); /* fond application (ex-#09090b) */
--color-surface-1: var(--color-zinc-900); /* cartes, panneaux */
--color-surface-2: var(--color-zinc-800); /* boutons, chips */
--color-surface-3: var(--color-zinc-700); /* survol des surfaces */
/* Bordures. */
--color-border: var(--color-zinc-800);
--color-border-strong: var(--color-zinc-700);
/* Texte. */
--color-fg: var(--color-zinc-200);
--color-fg-muted: var(--color-zinc-400);
--color-fg-subtle: var(--color-zinc-500);
/* Accent (interactions, focus). */
--color-accent: var(--color-emerald-600);
--color-accent-hover: var(--color-emerald-500);
}
/* Métriques du chrome IDE (barres, onglets, lignes). Consommées via des valeurs
arbitraires Tailwind, ex. h-[var(--ide-tab-h)]. */
:root {
--ide-activitybar-w: 3rem;
--ide-titlebar-h: 2.25rem;
--ide-tab-h: 2.25rem;
--ide-statusbar-h: 1.5rem;
--ide-row-h: 1.75rem;
}
html,
@@ -13,13 +45,13 @@ body,
}
body {
background-color: var(--color-zinc-950);
color: var(--color-zinc-200);
background-color: var(--color-surface-0);
color: var(--color-fg);
-webkit-font-smoothing: antialiased;
}
@layer base {
/* Tailwind v4 ne met plus cursor:pointer sur les boutons on le rétablit
/* Tailwind v4 ne met plus cursor:pointer sur les boutons : on le rétablit
(sauf désactivés, qui gardent le curseur par défaut / not-allowed). */
button:not(:disabled),
[role='button']:not([aria-disabled='true']) {
@@ -30,22 +62,22 @@ body {
@layer components {
/* Champs : rayon unifié + anneau de focus visible (absent auparavant). */
.input {
@apply w-full rounded-lg border border-zinc-700 bg-zinc-950 px-2.5 py-1.5 text-sm text-zinc-100 outline-none transition-colors placeholder:text-zinc-600 focus-visible:border-zinc-500 focus-visible:ring-2 focus-visible:ring-emerald-500/40;
@apply w-full rounded-lg border border-border-strong bg-surface-0 px-2.5 py-1.5 text-sm text-zinc-100 outline-none transition-colors placeholder:text-zinc-600 focus-visible:border-zinc-500 focus-visible:ring-2 focus-visible:ring-accent-hover/40;
}
/* Boutons : socle CSS pour les usages hors composant (ex. RouterLink class="btn").
Le composant BaseButton réplique ces variantes et ajoute tailles / loading / focus. */
.btn {
@apply inline-flex items-center justify-center gap-1.5 rounded-lg border border-zinc-700 bg-zinc-800 px-3 py-1.5 text-sm font-medium text-zinc-200 transition-colors hover:bg-zinc-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/70 focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:cursor-not-allowed disabled:opacity-50;
@apply inline-flex items-center justify-center gap-1.5 rounded-lg border border-border-strong bg-surface-2 px-3 py-1.5 text-sm font-medium text-fg transition-colors hover:bg-surface-3 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-hover/70 focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:cursor-not-allowed disabled:opacity-50;
}
.btn-primary {
@apply inline-flex items-center justify-center gap-1.5 rounded-lg bg-emerald-600 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-emerald-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/70 focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:cursor-not-allowed disabled:opacity-50;
@apply inline-flex items-center justify-center gap-1.5 rounded-lg bg-accent px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-accent-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-hover/70 focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:cursor-not-allowed disabled:opacity-50;
}
.btn-danger {
@apply inline-flex items-center justify-center gap-1.5 rounded-lg border border-red-900 bg-red-950 px-3 py-1.5 text-sm font-medium text-red-300 transition-colors hover:bg-red-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500/70 focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:cursor-not-allowed disabled:opacity-50;
@apply inline-flex items-center justify-center gap-1.5 rounded-lg border border-red-900 bg-red-950 px-3 py-1.5 text-sm font-medium text-red-300 transition-colors hover:bg-red-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500/70 focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:cursor-not-allowed disabled:opacity-50;
}
.btn-ghost {
@apply inline-flex items-center justify-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-300 transition-colors hover:bg-zinc-800/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/70 focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:cursor-not-allowed disabled:opacity-50;
@apply inline-flex items-center justify-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-300 transition-colors hover:bg-surface-2/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-hover/70 focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:cursor-not-allowed disabled:opacity-50;
}
.badge {
@@ -54,9 +86,9 @@ body {
/* Cartes : factorise le motif répété dans les listes/sections/formulaires. */
.card {
@apply rounded-xl border border-zinc-800 bg-zinc-900/50 p-3;
@apply rounded-xl border border-border bg-surface-1/50 p-3;
}
.card-inset {
@apply rounded-lg border border-zinc-800 bg-zinc-950/40 p-2;
@apply rounded-lg border border-border bg-surface-0/40 p-2;
}
}