From 137213241be63a92676ba2337201334d7d9a47d1 Mon Sep 17 00:00:00 2001 From: Gilles Soulier Date: Sun, 24 May 2026 05:19:33 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20tailwind=20CSS=20+=20design=20system=20?= =?UTF-8?q?Gruvbox=20seventies=20int=C3=A9gr=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajoute postcss.config.js et tailwind.config.ts avec tokens CSS mappés - Copie tokens.css dans frontend/src/design-system/ - Met à jour index.css avec import tokens + directives Tailwind - Adapte ui-kit.jsx en ui-kit.tsx (UMD → ESM, exports nommés) Co-Authored-By: Claude Sonnet 4.6 --- frontend/postcss.config.js | 6 + frontend/src/design-system/tokens.css | 204 ++++++++ frontend/src/design-system/ui-kit.tsx | 669 ++++++++++++++++++++++++++ frontend/src/index.css | 14 +- frontend/tailwind.config.ts | 38 ++ 5 files changed, 930 insertions(+), 1 deletion(-) create mode 100644 frontend/postcss.config.js create mode 100644 frontend/src/design-system/tokens.css create mode 100644 frontend/src/design-system/ui-kit.tsx create mode 100644 frontend/tailwind.config.ts diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/frontend/src/design-system/tokens.css b/frontend/src/design-system/tokens.css new file mode 100644 index 0000000..348bfe2 --- /dev/null +++ b/frontend/src/design-system/tokens.css @@ -0,0 +1,204 @@ +/* ============================================================ + ui-tokens.css + Design tokens Gruvbox Seventies — dark (par défaut) + light. + Sombre délavé (pas noir intense) / gris clair usé (pas blanc pur). + ============================================================ */ + +:root, +[data-theme="dark"] { + /* Couches de fond — sombre délavé, brun-gris chaud */ + --bg-0: #221c17; /* niveau le plus profond (rare) */ + --bg-1: #2a231d; /* fond app */ + --bg-2: #322a23; /* panneaux */ + --bg-3: #3c332a; /* cartes */ + --bg-4: #4a4035; /* hover */ + --bg-5: #5a4f43; /* press / actif */ + + /* Surfaces translucides */ + --surf-glass: rgba(50, 42, 35, 0.72); + --surf-glass-strong: rgba(50, 42, 35, 0.92); + --surf-glass-soft: rgba(50, 42, 35, 0.42); + + /* Bordures */ + --border-1: rgba(168, 153, 132, 0.18); + --border-2: rgba(168, 153, 132, 0.32); + --border-3: rgba(168, 153, 132, 0.55); + + /* Texte */ + --ink-1: #f2e5c7; /* cream principal */ + --ink-2: #d5c4a1; /* secondaire */ + --ink-3: #a89984; /* labels / hints */ + --ink-4: #7c6f64; /* désactivé */ + + /* Accent orange seventies */ + --accent: #fe8019; + --accent-soft: #d65d0e; + --accent-glow: rgba(254, 128, 25, 0.35); + --accent-tint: rgba(254, 128, 25, 0.12); + + /* Statuts */ + --ok: #4dbb26; + --ok-glow: rgba(77, 187, 38, 0.45); + --warn: #fabd2f; + --warn-glow: rgba(250, 189, 47, 0.45); + --err: #fb4934; + --err-glow: rgba(251, 73, 52, 0.4); + --info: #83a598; + --info-glow: rgba(131, 165, 152, 0.4); + + /* Couleurs additionnelles (datavis, badges, catégories) */ + --blue: #3db0d1; + --blue-glow: rgba(61, 176, 209, 0.45); + --purple: #c882c8; + --purple-glow: rgba(200, 130, 200, 0.45); + + /* Ombres */ + --shadow-1: 0 1px 2px rgba(0,0,0,0.4); + --shadow-2: 0 4px 12px rgba(0,0,0,0.45); + --shadow-3: 0 12px 32px rgba(0,0,0,0.55); + --shadow-press: inset 0 2px 4px rgba(0,0,0,0.5); + + /* Relief 3D pour tuiles : highlight haut + ombre bas + ombre portée */ + --tile-3d: + inset 0 1px 0 rgba(255, 230, 180, 0.12), + inset 0 -1px 0 rgba(0, 0, 0, 0.45), + 0 1px 0 rgba(0, 0, 0, 0.35), + 0 2px 4px rgba(0, 0, 0, 0.4), + 0 8px 18px rgba(0, 0, 0, 0.5); + --tile-3d-strong: + inset 0 1px 0 rgba(255, 230, 180, 0.18), + inset 0 -2px 0 rgba(0, 0, 0, 0.55), + 0 1px 0 rgba(0, 0, 0, 0.4), + 0 4px 8px rgba(0, 0, 0, 0.5), + 0 14px 28px rgba(0, 0, 0, 0.55); + + /* Polices */ + --font-ui: 'Inter', system-ui, -apple-system, sans-serif; + --font-mono: 'JetBrains Mono', ui-monospace, monospace; + --font-terminal: 'Share Tech Mono', 'VT323', 'Courier New', monospace; +} + +[data-theme="light"] { + /* Gris clair usé, légèrement chaud (pas blanc pur) */ + --bg-0: #b8b2a3; + --bg-1: #d5d0c5; + --bg-2: #dcd7cc; + --bg-3: #e3ded3; + --bg-4: #ccc6b8; + --bg-5: #bdb6a7; + + --surf-glass: rgba(220, 215, 204, 0.72); + --surf-glass-strong: rgba(220, 215, 204, 0.94); + --surf-glass-soft: rgba(220, 215, 204, 0.42); + + --border-1: rgba(60, 56, 54, 0.15); + --border-2: rgba(60, 56, 54, 0.28); + --border-3: rgba(60, 56, 54, 0.5); + + --ink-1: #28241f; + --ink-2: #3c3836; + --ink-3: #5a544c; + --ink-4: #8a8278; + + --accent: #af3a03; + --accent-soft: #d65d0e; + --accent-glow: rgba(175, 58, 3, 0.28); + --accent-tint: rgba(175, 58, 3, 0.08); + + --ok: #3c911c; + --ok-glow: rgba(60, 145, 28, 0.32); + --warn: #b57614; + --warn-glow: rgba(181, 118, 20, 0.35); + --err: #9d0006; + --err-glow: rgba(157, 0, 6, 0.3); + --info: #427b58; + --info-glow: rgba(66, 123, 88, 0.3); + + /* Couleurs additionnelles (datavis, badges, catégories) */ + --blue: #2d82a3; + --blue-glow: rgba(45, 130, 163, 0.32); + --purple: #8c468c; + --purple-glow: rgba(140, 70, 140, 0.32); + + --shadow-1: 0 1px 2px rgba(40,30,20,0.12); + --shadow-2: 0 4px 12px rgba(40,30,20,0.15); + --shadow-3: 0 12px 32px rgba(40,30,20,0.2); + --shadow-press: inset 0 2px 4px rgba(40,30,20,0.18); + + /* Relief light : highlight haut blanc cassé + ombre marquée */ + --tile-3d: + inset 0 1px 0 rgba(255, 255, 255, 0.55), + inset 0 -1px 0 rgba(60, 50, 40, 0.18), + 0 1px 0 rgba(60, 50, 40, 0.1), + 0 2px 4px rgba(60, 50, 40, 0.12), + 0 8px 18px rgba(60, 50, 40, 0.18); + --tile-3d-strong: + inset 0 1px 0 rgba(255, 255, 255, 0.7), + inset 0 -2px 0 rgba(60, 50, 40, 0.22), + 0 1px 0 rgba(60, 50, 40, 0.15), + 0 4px 8px rgba(60, 50, 40, 0.18), + 0 14px 28px rgba(60, 50, 40, 0.22); +} + +/* ============================================================ + Reset minimal + base typo + ============================================================ */ +* { box-sizing: border-box; } +html, body { margin: 0; padding: 0; } + +body { + font-family: var(--font-ui); + font-size: 14px; + color: var(--ink-1); + background: var(--bg-1); + -webkit-font-smoothing: antialiased; +} + +.mono { font-family: var(--font-mono); } +.terminal { font-family: var(--font-terminal); letter-spacing: 0.02em; } +.label { + font-family: var(--font-mono); + font-size: 11px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--ink-3); +} + +/* ============================================================ + Surfaces — relief 3D marqué, AUCUN effet hover + ============================================================ */ +.glass { + background: var(--surf-glass); + backdrop-filter: blur(12px) saturate(140%); + -webkit-backdrop-filter: blur(12px) saturate(140%); + border: 1px solid var(--border-2); + box-shadow: var(--tile-3d); +} +.glass-strong { + background: var(--surf-glass-strong); + backdrop-filter: blur(16px) saturate(150%); + -webkit-backdrop-filter: blur(16px) saturate(150%); + border: 1px solid var(--border-3); + box-shadow: var(--tile-3d-strong); +} + +/* Élément cliquable : pas de hover, mais réelle pression 3D au clic */ +.interactive { + cursor: pointer; + transition: transform .04s ease-out, box-shadow .04s, background .04s; + transform: translateY(0); +} +.interactive:active { + transform: translateY(1px); + box-shadow: var(--shadow-press) !important; + filter: brightness(0.92); +} + +/* Scrollbar custom */ +*::-webkit-scrollbar { width: 8px; height: 8px; } +*::-webkit-scrollbar-track { background: transparent; } +*::-webkit-scrollbar-thumb { + background: var(--border-2); + border-radius: 4px; +} +*::-webkit-scrollbar-thumb:hover { background: var(--accent-soft); } diff --git a/frontend/src/design-system/ui-kit.tsx b/frontend/src/design-system/ui-kit.tsx new file mode 100644 index 0000000..d8b9747 --- /dev/null +++ b/frontend/src/design-system/ui-kit.tsx @@ -0,0 +1,669 @@ +// @ts-nocheck +/* ============================================================ + ui-kit.tsx + Composants haute-fid Gruvbox Seventies. + Tout est purement décoratif/interactif côté composant. + Effets : transparence (glass), hover glow, click 3D, tooltips. + Adapté de ui-kit.jsx (UMD → ESM TypeScript) + ============================================================ */ + +import { useState, useRef, useEffect } from 'react' + +/* ============================================================ + Icônes — Font Awesome 6 Free. + Mapping nom logique → classe FA. Le CSS de FA est chargé en CDN + dans le . Le composant garde la MÊME API qu'avant (name, + size, style) pour ne rien casser ailleurs. + ============================================================ */ +const ICON_MAP = { + cpu: 'microchip', + memory: 'memory', + disk: 'hard-drive', + network: 'network-wired', + clock: 'clock', + grid: 'table-cells', + list: 'list', + cog: 'gear', + alert: 'triangle-exclamation', + bell: 'bell', + server: 'server', + chart: 'chart-line', + bars: 'chart-simple', + terminal: 'terminal', + refresh: 'arrows-rotate', + play: 'play', + pause: 'pause', + power: 'power-off', + sun: 'sun', + moon: 'moon', + search: 'magnifying-glass', + close: 'xmark', + chevR: 'chevron-right', + chevL: 'chevron-left', + chevD: 'chevron-down', + chevU: 'chevron-up', + plus: 'plus', + filter: 'filter', + download: 'download', + folder: 'folder', + node: 'circle-nodes', + user: 'user', +}; + +const Icon = ({ name, size = 16, style }) => { + const fa = ICON_MAP[name] || 'circle-question'; + return ( +