0b6f3c0808
first
364 lines
15 KiB
Markdown
364 lines
15 KiB
Markdown
# 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|light"]`) |
|
||
| `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
|
||
|
||
1. **Toujours utiliser les variables CSS**, jamais des hex en dur dans le code utilisateur.
|
||
✅ `color: var(--accent)`
|
||
❌ `color: #fe8019`
|
||
|
||
2. **Toujours déclarer `data-theme`** sur un parent (`<html>` ou un wrapper).
|
||
Sans ça, les variables ne sont pas définies et l'UI casse silencieusement.
|
||
|
||
3. **Composants existants** — ne jamais en réinventer. Vérifier d'abord la liste ci-dessous.
|
||
|
||
4. **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.
|
||
|
||
5. **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`.
|
||
|
||
6. **Toujours des tooltips** sur les boutons icônes seuls (`<IconButton>` exige `label`).
|
||
|
||
7. **Pas de bordure arrondie excessive**. Tuiles : `border-radius: 10-12px`. Boutons : `8px`. Pastilles : `999px`.
|
||
|
||
8. **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.
|
||
|
||
9. **Tonalité** : labels en `text-transform: uppercase` + `letter-spacing: 0.08em` (classe `.label` déjà fournie).
|
||
|
||
10. **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|danger|default">` | Action principale, secondaire |
|
||
| 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|err|info|off" pulse>` | LED pulsante pour critique |
|
||
| 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
|
||
```jsx
|
||
<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 Mono` 11-12px
|
||
- Horloge à droite
|
||
|
||
---
|
||
|
||
## 🚫 Anti-patterns à éviter
|
||
|
||
### NE PAS faire :
|
||
|
||
❌ **Mettre des emoji** pour un état :
|
||
```jsx
|
||
<span>✅ Système OK</span> // NON
|
||
<><StatusLed status="ok" /> Système OK</> // OUI
|
||
```
|
||
|
||
❌ **Inventer de nouvelles couleurs hors palette** :
|
||
```jsx
|
||
style={{ color: '#ff00aa' }} // NON — utilise les tokens
|
||
```
|
||
|
||
❌ **Police arbitraire** :
|
||
```jsx
|
||
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** :
|
||
```jsx
|
||
<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-3` ou `.glass`
|
||
- Input fields / containers profonds → `--bg-1` avec inset shadow
|
||
|
||
### Effet glass standard
|
||
```jsx
|
||
className="glass" // backdrop-filter + bg semi-transparent + tile-3d shadow
|
||
```
|
||
ou pour plus marqué :
|
||
```jsx
|
||
className="glass-strong"
|
||
```
|
||
|
||
### Validation visuelle d'un état critique
|
||
```jsx
|
||
<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)
|
||
```jsx
|
||
<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 :
|
||
```jsx
|
||
document.documentElement.dataset.theme = 'light';
|
||
```
|
||
|
||
---
|
||
|
||
## 🪟 Cas particulier : applications GNOME
|
||
|
||
Pour GTK 4 / libadwaita :
|
||
1. Charger `tokens/tokens.gnome.css` via `GtkCssProvider`
|
||
2. Le fichier **override les couleurs sémantiques libadwaita** (`@accent_color`, `@window_bg_color`, etc.) — les widgets standards se ré-habillent automatiquement
|
||
3. Ajouter `add_css_class("tile")` pour le relief 3D, `("mono")` pour monospace, `("terminal")` pour Share Tech Mono
|
||
4. Pour les boutons accent : utiliser la classe libadwaita standard `suggested-action` (déjà restylée)
|
||
5. 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 :
|
||
```jsx
|
||
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
|
||
|
||
1. **Avant de créer un composant, cherche d'abord** dans `ui-kit.jsx`. 90% du temps il existe déjà.
|
||
2. **Avant d'inventer une couleur**, regarde les tokens. Tu as 6 fonds, 4 encres, 4 statuts, 2 datavis = largement assez.
|
||
3. **Si tu hésites sur une taille de police** : labels = 11px mono uppercase, body = 13-14px, kpi = 18-28px mono bold.
|
||
4. **Quand tu ajoutes une tuile**, mets `className="glass"` (ou `glass-strong` pour les modales) — tout le styling est inclus.
|
||
5. **Pour un état critique**, combine plusieurs signaux : couleur + pulse LED + icône + position visuelle. Pas juste une couleur.
|
||
6. **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.
|