first
15 KiB
Consignes — mon design system (Gruvbox seventies)
Tu es un agent IA chargé de produire ou modifier du code utilisant ce design system. Lis ce fichier en entier avant d'écrire la moindre ligne. Suis les règles à la lettre.
🎯 Identité du système
- Nom : mon design system — Gruvbox seventies
- Vibe : rétro-industriel, console de monitoring, SCADA, terminal années 70
- Palette : orange brûlé Gruvbox + fond brun délavé (pas noir intense) ou gris clair usé (pas blanc pur)
- Cas d'usage cibles : tableaux de bord, monitoring, IoT, domotique, ops, scanners réseau
- Public : utilisateurs techniques (admin sys, devs, makers) — densité d'info élevée acceptée
📁 Fichiers à connaître
| Fichier | Contient |
|---|---|
tokens/tokens.css |
Variables CSS web (`:root[data-theme="dark |
tokens/tokens.gnome.css |
Tokens GTK 4 / libadwaita (@define-color) |
tokens/tokens.json |
Tokens en JSON pour outils externes |
components/ui-kit.jsx |
14 composants React (Button, Icon, Popup…) |
examples/exemple-minimal.html |
Démo de référence |
⚠️ Règles absolues — ne JAMAIS enfreindre
-
Toujours utiliser les variables CSS, jamais des hex en dur dans le code utilisateur. ✅
color: var(--accent)❌color: #fe8019 -
Toujours déclarer
data-themesur un parent (<html>ou un wrapper). Sans ça, les variables ne sont pas définies et l'UI casse silencieusement. -
Composants existants — ne jamais en réinventer. Vérifier d'abord la liste ci-dessous.
-
Icônes — utiliser le composant
<Icon name="…">avec les noms mappés. JAMAIS d'emoji, JAMAIS de SVG inline custom pour un cas où une icône Font Awesome existe. -
Pas d'effet hover sur les boutons / tuiles / composants généraux (sauf jauges et tuiles Heimdall qui en ont un). Seulement pression 3D au clic via
.interactive. -
Toujours des tooltips sur les boutons icônes seuls (
<IconButton>exigelabel). -
Pas de bordure arrondie excessive. Tuiles :
border-radius: 10-12px. Boutons :8px. Pastilles :999px. -
Polices — respecter strictement les 3 familles :
- Inter → UI (titres, corps, boutons, labels d'interface généraux)
- JetBrains Mono → données numériques, valeurs, code, IDs, IPs
- Share Tech Mono → logs, terminal embarqué, ambiance rétro Toute autre police = bug.
-
Tonalité : labels en
text-transform: uppercase+letter-spacing: 0.08em(classe.labeldéjà fournie). -
Densité : pas de padding inutile. Ce DS est dense par nature. Tuiles : padding 14-18px. Boutons : 6-10px vertical.
🎨 Tokens disponibles
Couleurs (toutes définies en dark ET light)
Fonds (du plus profond au plus haut)
--bg-0 très rare, niveau le plus bas
--bg-1 fond application principal
--bg-2 panneaux (sidebar, headerbar)
--bg-3 cartes, tuiles ← LE PLUS UTILISÉ
--bg-4 hover, état actif
--bg-5 press, sélection forte
Texte (du plus contrasté au moins)
--ink-1 texte principal
--ink-2 texte secondaire
--ink-3 labels, hints
--ink-4 désactivé
Accent
--accent couleur primaire (orange Gruvbox seventies)
--accent-soft variante foncée (bordures, hover)
--accent-glow halo (rgba)
--accent-tint teinte transparente (fonds discrets)
Statuts
--ok #4dbb26 (vert flashy)
--warn #fabd2f (jaune)
--err #fb4934 (rouge)
--info #83a598 (vert-bleu pastel)
Datavis additionnel
--blue #3db0d1
--purple #c882c8
Bordures
--border-1, --border-2, --border-3 du plus subtil au plus marqué
Ombres / relief
--shadow-1, -2, -3 élévations standards
--shadow-press état pressé (inset)
--tile-3d relief 3D marqué pour cartes ← À utiliser sur les tuiles importantes
Polices
--font-ui 'Inter', system-ui, sans-serif
--font-mono 'JetBrains Mono', monospace
--font-terminal 'Share Tech Mono', monospace
🧩 Composants — quand utiliser quoi
| Besoin | Composant | Exemple |
|---|---|---|
| Bouton texte avec ou sans icône | `<Button variant="primary | ghost |
| Bouton icône seul | <IconButton icon="…" label="…"> |
Toolbars, headers (le label devient tooltip) |
| On/off | <Toggle on={…} onChange={…} label icon> |
Activer/désactiver une option |
| État système | `<StatusLed status="ok | warn |
| Jauge ronde standard | <RadialGauge value={…} label size> |
KPI compact, cockpit |
| Jauge ronde héro | <BigRadialGauge value={…} label> |
Métrique principale unique |
| Jauge barre standard | <BatteryGauge value label> |
Stack vertical de ressources |
| Jauge barre inline | <BatteryGauge compact value label icon> |
Listes denses, label + barre + valeur sur 1 ligne |
| Modale | <Popup open onClose title footer> |
Confirmation, config détaillée |
| Tree dépliable | <TreeNav groups activeId onSelect> |
Sidebar hiérarchique (clusters/nodes) |
| Mini graphe | <Sparkline points color> |
Dans une tuile KPI |
| Graphe ligne | <LineChart series labels h> |
Évolution temporelle multi-séries |
| Tooltip | <Tooltip label side><…/></Tooltip> |
Toute icône isolée |
| Icône | <Icon name="…" size> |
JAMAIS d'emoji, JAMAIS de SVG custom |
Icônes disponibles (noms logiques → Font Awesome)
cpu, memory, disk, network, clock, grid, list, cog, alert, bell, server, chart, bars, terminal, refresh, play, pause, power, sun, moon, search, close, chevR, chevL, chevD, chevU, plus, filter, download, folder, node, user.
Pour un nouveau besoin → utiliser une icône Font Awesome (préfixe fa-solid fa-…) en ajoutant l'alias dans ICON_MAP au sein de ui-kit.jsx.
🏗️ Patterns d'agencement standards
Layout dashboard 3 colonnes
┌─ Header (tabs workspace + search + actions + statut connexion) ─┐
├──────┬────────────────────────────────┬──────────────────────────┤
│ Tree │ Center cockpit (KPIs + jauges) │ Logs/Terminal repliable │
│ nav │ │ │
├──────┴────────────────────────────────┴──────────────────────────┤
│ Status bar (mode · workspace · stats · horloge) │
└──────────────────────────────────────────────────────────────────┘
Tuile KPI standard
<div className="glass" style={{ padding: 12, borderRadius: 10, ...}}>
<Icon name="cpu" /> <span className="label">CPU</span>
<span className="mono">{value}<span className="label">%</span></span>
<Sparkline points={trend} color="var(--accent)" />
</div>
Status bar inférieure
- Première cellule = mode courant en fond accent (style tmux)
- Cellules séparées par
border-right: 1px solid var(--border-1) - Police
Share Tech Mono11-12px - Horloge à droite
🚫 Anti-patterns à éviter
NE PAS faire :
❌ Mettre des emoji pour un état :
<span>✅ Système OK</span> // NON
<><StatusLed status="ok" /> Système OK</> // OUI
❌ Inventer de nouvelles couleurs hors palette :
style={{ color: '#ff00aa' }} // NON — utilise les tokens
❌ Police arbitraire :
fontFamily: 'Roboto' // NON
fontFamily: 'var(--font-ui)' // OUI
❌ Bordures arrondies à 24px+ sur des cartes (vibe trop SaaS pastel).
❌ Tooltip absent sur une icône isolée :
<button><Icon name="cog" /></button> // NON
<IconButton icon="cog" label="Configurer" onClick={fn} /> // OUI
❌ window.alert / confirm — toujours utiliser <Popup>.
❌ Texte secondaire en --ink-1 — choisir la bonne couche d'encre selon la hiérarchie.
❌ Sur-utiliser le glow / shadow — réservé aux accents importants.
❌ Mélanger les casses de label — labels = uppercase mono, titres = sentence case.
✅ Patterns recommandés
Hiérarchie de fond
- App / page →
--bg-1 - Sidebar / headerbar →
--bg-2 - Tuiles / cartes principales →
--bg-3ou.glass - Input fields / containers profonds →
--bg-1avec inset shadow
Effet glass standard
className="glass" // backdrop-filter + bg semi-transparent + tile-3d shadow
ou pour plus marqué :
className="glass-strong"
Validation visuelle d'un état critique
<StatusLed status="err" pulse /> // pastille pulsante
<Button variant="danger" icon="power">…</Button>
// + bordure rouge sur le conteneur :
style={{ border: '1px solid var(--err)', boxShadow: 'inset 0 1px 0 rgba(251,73,52,0.2), 0 0 18px rgba(251,73,52,0.15)' }}
Sticky footer d'actions (form)
<div className="glass-strong" style={{
padding: '12px 20px',
display: 'flex', gap: 12, alignItems: 'center',
borderTop: '1px solid var(--border-2)',
}}>
<StatusLed status={dirty ? 'warn' : 'ok'} pulse={dirty} />
<span className="terminal">{dirty ? 'modifications non sauvegardées' : 'à jour'}</span>
<span style={{ flex: 1 }}></span>
<Button variant="ghost">Annuler</Button>
<Button variant="primary" icon="download">Enregistrer</Button>
</div>
🌗 Gestion des deux thèmes
Règle d'or : tout ce qui s'affiche doit être lisible et cohérent dans les deux thèmes.
Avant de livrer un écran, mentalement (ou réellement) bascule data-theme et vérifie :
- Les couleurs personnalisées (en dur) cassent forcément → utilise les tokens
- Les opacités blanches (
rgba(255,255,255,…)) en dark passent mal en light → préfère les variables--border-* - Les ombres très profondes en dark sont invisibles en light → utilise
--shadow-*qui s'adapte
Pour basculer dynamiquement :
document.documentElement.dataset.theme = 'light';
🪟 Cas particulier : applications GNOME
Pour GTK 4 / libadwaita :
- Charger
tokens/tokens.gnome.cssviaGtkCssProvider - Le fichier override les couleurs sémantiques libadwaita (
@accent_color,@window_bg_color, etc.) — les widgets standards se ré-habillent automatiquement - Ajouter
add_css_class("tile")pour le relief 3D,("mono")pour monospace,("terminal")pour Share Tech Mono - Pour les boutons accent : utiliser la classe libadwaita standard
suggested-action(déjà restylée) - Pour danger : classe
destructive-action
Polices : penser à installer ou bundler Inter / JetBrains Mono / Share Tech Mono dans le .flatpak / .deb (sinon GTK fallback sur Cantarell / DejaVu).
🎯 Quand l'utilisateur demande quelque chose…
"Ajoute un bouton de déconnexion"
→ <IconButton icon="power" label="Se déconnecter" danger /> ou
<Button variant="danger" icon="power">Déconnexion</Button>
"Affiche le statut du serveur"
→ Combinaison <StatusLed status="ok|warn|err" pulse /> + label texte. Le pulse uniquement si c'est critique/nouveau.
"Mets une jauge CPU"
→ <BatteryGauge compact value={cpu} label="cpu" icon="cpu" warnAt={70} errAt={85} /> (inline)
ou <RadialGauge value={cpu} label="CPU" /> (visuel)
"Crée une modale de confirmation"
→ <Popup> avec footer={<><Button variant="ghost">Annuler</Button><Button variant="primary">Confirmer</Button></>}
"Liste hiérarchique des serveurs"
→ <TreeNav> avec groups: [{ id, icon: 'server', label, count, open, children: [{ id, label, status, meta }] }]
"Affiche les logs"
→ Conteneur avec font-family: var(--font-terminal) + lignes colorées par niveau (ERROR → var(--err), WARN → var(--warn), INFO → var(--ink-2)).
"Ajoute une option dark/light dans les réglages"
→ <RadioGroup options={[{value:'dark', icon:'moon'}, {value:'light', icon:'sun'}, {value:'auto', icon:'clock'}]}> + effet de bord :
React.useEffect(() => { document.documentElement.dataset.theme = theme; }, [theme]);
📐 Tailles standards à respecter
| Élément | Taille / Padding |
|---|---|
| Boutons sm | h: 28px · pad: 5px 10px · font: 12px |
| Boutons md | h: 34px · pad: 7px 14px · font: 13px |
| Boutons lg | h: 40px · pad: 10px 18px · font: 14px |
| IconButton | 34px (default) · 26px (compact) |
| Inputs | pad: 9px 12px · font: 13px |
| Toggle | 42 × 22px |
| StatusLed | 8-14px diamètre |
| Header app | 48-56px hauteur |
| Sidebar | 200-260px largeur |
| Volet logs | 320-360px largeur |
| Status bar | 24-28px hauteur |
| Radius tuile | 10-12px |
| Radius button | 8px |
| Espacement | 8 / 12 / 14 / 18 / 24px (rythme bas) |
💡 Trucs pour ne pas se tromper
- Avant de créer un composant, cherche d'abord dans
ui-kit.jsx. 90% du temps il existe déjà. - Avant d'inventer une couleur, regarde les tokens. Tu as 6 fonds, 4 encres, 4 statuts, 2 datavis = largement assez.
- Si tu hésites sur une taille de police : labels = 11px mono uppercase, body = 13-14px, kpi = 18-28px mono bold.
- Quand tu ajoutes une tuile, mets
className="glass"(ouglass-strongpour les modales) — tout le styling est inclus. - Pour un état critique, combine plusieurs signaux : couleur + pulse LED + icône + position visuelle. Pas juste une couleur.
- Quand l'utilisateur demande "un peu d'effet" : pas de hover (sauf jauges), oui à la pression 3D, oui aux animations d'entrée 200-400ms
cubic-bezier(.3,.7,.3,1.2).
🔚 En cas de doute
- Pas sûr d'une couleur ? → tokens
- Pas sûr d'un composant ? →
ui-kit.jsx - Pas sûr d'un layout ? →
examples/exemple-minimal.html - Pas sûr d'une convention ? → ce fichier
Toujours préférer la cohérence avec l'existant à l'innovation. Quand tu doutes, demande-moi plutôt que de deviner.