62317f2ad7
Mise en place du Design System ManageMate Group v0.2 — refonte du
système de tokens (préfixe --mmg-color-*), 9 presets accent
user-themable validés WCAG AA, overlays Radix UI + Floating UI,
Storybook 8 + Vitest + axe-core en CI, doc Astro Starlight,
DESIGN.md (format google-labs-code) et exports tokens DTCG/CSS/
TS/Figma/Tailwind v3 et v4.
- 4 packages monorepo pnpm : @managemate/{tokens,css,react,icons}
- 62 composants React headless-first (Sheet, HoverCard, ContextMenu,
Slider, ToggleGroup, AvatarGroup, UserCard, ProfileHeader,
MetricCard, PricingCard, FeatureCard, Text/Display/Eyebrow/Lead…)
- Lint contraste WCAG : 37/37 paires AA, branché CI
- Toast pile Sonner-style avec ResizeObserver
- Theming user (9 presets) sans casser sémantique fixe
- Identité Synapse (rose #D12B6A) préservée
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
469 lines
18 KiB
Markdown
469 lines
18 KiB
Markdown
---
|
||
version: "0.2"
|
||
name: DSMMG
|
||
description: >
|
||
Design System ManageMate Group — référence pour Synapse, HRTime, Forge,
|
||
Orbit, MSLM, Espace-Client et sites publics. Headless-first sur Radix UI,
|
||
RGAA 4.1 / WCAG 2.2 AA, theming utilisateur via 9 presets accent.
|
||
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
# COULEURS — primitives → semantic → accent (user-themable)
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
colors:
|
||
# — Neutrals (warm-cool mix : frais en light, neutre en dark) ——————
|
||
neutral-0: "#FFFFFF"
|
||
neutral-50: "#F7F6FB"
|
||
neutral-100: "#F0EFF9"
|
||
neutral-150: "#EDEDFA"
|
||
neutral-200: "#E4E3F4"
|
||
neutral-300: "#C9C7E0"
|
||
neutral-400: "#AAA8C9"
|
||
neutral-500: "#7875A1"
|
||
neutral-600: "#56557A"
|
||
neutral-700: "#3B3A56"
|
||
neutral-800: "#1F1E32"
|
||
neutral-900: "#111120"
|
||
|
||
# — Synapse (rose corporate ManageMate, défaut accent) ——————
|
||
synapse-50: "#FEF0F4"
|
||
synapse-100: "#FCE0EA"
|
||
synapse-200: "#FAD0DF"
|
||
synapse-300: "#F4A0BD"
|
||
synapse-400: "#ED608E"
|
||
synapse-500: "#D12B6A" # ★ marque ManageMate
|
||
synapse-600: "#BA245F"
|
||
synapse-700: "#A82257"
|
||
synapse-800: "#831B45"
|
||
synapse-900: "#5A132F"
|
||
|
||
# — Presets accent user (8 alternatives au synapse) ——————
|
||
rose-500: "#E11D48"
|
||
blue-500: "#2563EB"
|
||
violet-500: "#7C3AED"
|
||
green-500: "#0E9F6E"
|
||
amber-500: "#D97706"
|
||
red-500: "#DC2626"
|
||
cyan-500: "#0891B2"
|
||
slate-500: "#475569"
|
||
|
||
# — Sémantique fixe (NE CHANGE JAMAIS avec l'accent user) ——————
|
||
success: "#059669"
|
||
warning: "#D97706"
|
||
danger: "#DC2626"
|
||
info: "#2563EB"
|
||
|
||
# — Active accent (alias dynamique, par défaut synapse) ——————
|
||
primary: "{colors.synapse-500}"
|
||
secondary: "{colors.neutral-600}"
|
||
tertiary: "{colors.neutral-300}"
|
||
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
# TYPOGRAPHIE — Figtree partout, 3 échelles selon contexte
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
typography:
|
||
# — Display (landings produits — HRTime, Synapse, Forge, Orbit) ——
|
||
display-2xl:
|
||
fontFamily: Figtree
|
||
fontSize: 72px
|
||
fontWeight: 800
|
||
letterSpacing: "-0.035em"
|
||
lineHeight: 1.0
|
||
display-xl:
|
||
fontFamily: Figtree
|
||
fontSize: 60px
|
||
fontWeight: 800
|
||
letterSpacing: "-0.03em"
|
||
lineHeight: 1.05
|
||
display-lg:
|
||
fontFamily: Figtree
|
||
fontSize: 48px
|
||
fontWeight: 700
|
||
letterSpacing: "-0.025em"
|
||
lineHeight: 1.1
|
||
display-md:
|
||
fontFamily: Figtree
|
||
fontSize: 36px
|
||
fontWeight: 700
|
||
letterSpacing: "-0.02em"
|
||
lineHeight: 1.15
|
||
|
||
# — Headlines (apps métier — h1 → h6 sémantiques) ————————
|
||
h1:
|
||
fontFamily: Figtree
|
||
fontSize: 36px
|
||
fontWeight: 700
|
||
letterSpacing: "-0.02em"
|
||
lineHeight: 1.2
|
||
h2:
|
||
fontFamily: Figtree
|
||
fontSize: 30px
|
||
fontWeight: 700
|
||
letterSpacing: "-0.015em"
|
||
lineHeight: 1.25
|
||
h3:
|
||
fontFamily: Figtree
|
||
fontSize: 24px
|
||
fontWeight: 700
|
||
letterSpacing: "-0.01em"
|
||
lineHeight: 1.3
|
||
h4:
|
||
fontFamily: Figtree
|
||
fontSize: 20px
|
||
fontWeight: 600
|
||
letterSpacing: "-0.005em"
|
||
lineHeight: 1.35
|
||
h5:
|
||
fontFamily: Figtree
|
||
fontSize: 17px
|
||
fontWeight: 600
|
||
lineHeight: 1.4
|
||
h6:
|
||
fontFamily: Figtree
|
||
fontSize: 15px
|
||
fontWeight: 600
|
||
lineHeight: 1.45
|
||
|
||
# — Body ————————————————————————————————————————
|
||
body-lg:
|
||
fontFamily: Figtree
|
||
fontSize: 17px
|
||
lineHeight: 1.6
|
||
body:
|
||
fontFamily: Figtree
|
||
fontSize: 15px
|
||
lineHeight: 1.55
|
||
body-sm:
|
||
fontFamily: Figtree
|
||
fontSize: 13px
|
||
lineHeight: 1.5
|
||
body-xs:
|
||
fontFamily: Figtree
|
||
fontSize: 11px
|
||
lineHeight: 1.45
|
||
|
||
# — Auxiliaires ————————————————————————————————
|
||
eyebrow:
|
||
fontFamily: Figtree
|
||
fontSize: 13px
|
||
fontWeight: 600
|
||
letterSpacing: "0.06em"
|
||
textTransform: uppercase
|
||
lead:
|
||
fontFamily: Figtree
|
||
fontSize: 20px
|
||
fontWeight: 400
|
||
letterSpacing: "-0.005em"
|
||
lineHeight: 1.5
|
||
overline:
|
||
fontFamily: Figtree
|
||
fontSize: 11px
|
||
fontWeight: 600
|
||
letterSpacing: "0.08em"
|
||
textTransform: uppercase
|
||
caption:
|
||
fontFamily: Figtree
|
||
fontSize: 11px
|
||
lineHeight: 1.4
|
||
code:
|
||
fontFamily: "JetBrains Mono"
|
||
fontSize: 13px
|
||
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
# RAYONS — pill par défaut sur interactifs et conteneurs
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
rounded:
|
||
none: 0
|
||
sm: 8px
|
||
md: 12px
|
||
card: 20px
|
||
panel: 24px
|
||
icon: 12px
|
||
pill: 9999px
|
||
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
# ESPACEMENT — grille 4pt (multiples de 4 ou 8 exclusivement)
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
spacing:
|
||
"0": 0
|
||
"1": 4px
|
||
"2": 8px
|
||
"3": 12px
|
||
"4": 16px
|
||
"5": 20px
|
||
"6": 24px
|
||
"7": 32px
|
||
"8": 40px
|
||
"9": 48px
|
||
"10": 64px
|
||
"11": 80px
|
||
"12": 120px
|
||
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
# MOTION — animation = feedback fonctionnel, jamais décoratif
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
motion:
|
||
duration:
|
||
fast: 120ms # micro-interactions (hover, focus)
|
||
base: 200ms # transitions UI standard
|
||
slow: 320ms # navigation (modals, drawers)
|
||
easing:
|
||
default: "cubic-bezier(0.4, 0, 0.2, 1)" # matériel, doux
|
||
emphasis: "cubic-bezier(0.2, 0.8, 0.2, 1)" # rebond léger
|
||
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
# DENSITÉ — 3 modes adaptables par préférence user
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
density:
|
||
comfortable:
|
||
rowHeight: 44px
|
||
inputHeight: 40px
|
||
paddingX: 16px
|
||
paddingY: 12px
|
||
cozy:
|
||
rowHeight: 36px
|
||
inputHeight: 36px
|
||
paddingX: 12px
|
||
paddingY: 8px
|
||
compact:
|
||
rowHeight: 28px
|
||
inputHeight: 30px
|
||
paddingX: 8px
|
||
paddingY: 4px
|
||
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
# COMPOSANTS — extraits clé. Liste exhaustive : @managemate/react
|
||
# ═══════════════════════════════════════════════════════════════════
|
||
components:
|
||
button-primary:
|
||
backgroundColor: "{colors.primary}"
|
||
textColor: "{colors.neutral-0}"
|
||
typography: "{typography.body-sm}"
|
||
fontWeight: 600
|
||
rounded: "{rounded.pill}"
|
||
padding: "10px 22px"
|
||
minHeight: 40px
|
||
|
||
button-tonal:
|
||
backgroundColor: "{colors.synapse-50}"
|
||
textColor: "{colors.synapse-800}"
|
||
typography: "{typography.body-sm}"
|
||
fontWeight: 600
|
||
rounded: "{rounded.pill}"
|
||
padding: "10px 22px"
|
||
|
||
button-ghost:
|
||
backgroundColor: transparent
|
||
textColor: "{colors.neutral-700}"
|
||
typography: "{typography.body-sm}"
|
||
fontWeight: 600
|
||
|
||
card:
|
||
backgroundColor: "{colors.neutral-0}"
|
||
rounded: "{rounded.card}"
|
||
padding: "{spacing.6}"
|
||
borderColor: "{colors.neutral-200}"
|
||
|
||
input:
|
||
backgroundColor: "{colors.neutral-0}"
|
||
textColor: "{colors.neutral-900}"
|
||
borderColor: "{colors.neutral-200}"
|
||
rounded: "{rounded.md}"
|
||
padding: "10px 14px"
|
||
minHeight: 40px
|
||
|
||
badge:
|
||
backgroundColor: "{colors.neutral-150}"
|
||
textColor: "{colors.neutral-700}"
|
||
typography: "{typography.body-xs}"
|
||
fontWeight: 600
|
||
rounded: 6px
|
||
padding: "2px 8px"
|
||
|
||
toast:
|
||
backgroundColor: "{colors.neutral-0}"
|
||
borderColor: "{colors.neutral-200}"
|
||
rounded: 14px
|
||
padding: "14px 14px 14px 16px"
|
||
|
||
tile:
|
||
backgroundColor: "{colors.neutral-0}"
|
||
borderColor: "{colors.neutral-200}"
|
||
rounded: "{rounded.card}"
|
||
padding: "{spacing.6}"
|
||
---
|
||
|
||
# DSMMG — Design System ManageMate Group
|
||
|
||
> **Version 0.2** · La source de vérité visuelle, comportementale et accessible pour les produits ManageMate (Synapse, HRTime, Forge, Orbit, MSLM, Espace-Client, sites publics).
|
||
|
||
## Overview
|
||
|
||
Le DSMMG est un design system **headless-first** construit sur Radix UI. Trois mots :
|
||
|
||
- **Cohérence** — un bouton dans n'importe quel produit ManageMate a la même structure et la même couleur de base. La différenciation se fait par contenu, pas par couleur.
|
||
- **Accessibilité** — RGAA 4.1 / WCAG 2.2 AA non-négociable. Validé `axe-core` en CI. Plusieurs clients (collectivités, opérateurs publics) sont soumis au RGAA par la loi.
|
||
- **Theming utilisateur** — 9 presets accent (rose Synapse par défaut), chaque utilisateur choisit dans ses préférences. La sémantique (success/danger/warning/info) reste fixe.
|
||
|
||
## Colors
|
||
|
||
Trois couches verticales :
|
||
|
||
```
|
||
primitives → semantic → accent (user-themable)
|
||
```
|
||
|
||
1. **Primitives** — rampes brutes (`neutral-0..900`, `synapse-50..900`, et 8 presets). Ne JAMAIS référencer directement dans les composants.
|
||
2. **Sémantiques** — `bg-page`, `text-primary`, `border`, `success/warning/danger/info`. **Stables, ne changent pas avec l'accent user.**
|
||
3. **Accent** — `--mmg-color-accent-*`. Posé par `[data-mmg-accent="<preset>"]` sur `<html>`. SEUL token couleur user-themable.
|
||
|
||
### Presets accent disponibles
|
||
|
||
`synapse` (défaut), `rose`, `blue`, `violet`, `green`, `amber`, `red`, `cyan`, `slate`.
|
||
|
||
Chaque preset a sa version dark adaptée (saturation -2pts, luminosité +3pts) pour confort visuel.
|
||
|
||
### Règle absolue
|
||
|
||
- ❌ **Aucun hex en dur dans les composants.**
|
||
- ❌ **Jamais de `--mmg-color-synapse-*` direct** dans un composant — toujours via `--mmg-color-accent-*`.
|
||
|
||
## Typography
|
||
|
||
**Figtree** partout (Google Fonts, sans-serif géométrique). 3 échelles selon contexte :
|
||
|
||
| Famille | Cas d'usage | Tailles |
|
||
|---|---|---|
|
||
| **Display** | Hero des landings produits (HRTime, Synapse…) | 36px → 72px |
|
||
| **Headlines** | Apps métier (h1-h6 sémantiques) | 15px → 36px |
|
||
| **Body** | Texte courant et UI | 11px → 17px |
|
||
| **Auxiliaires** | eyebrow, lead, overline, caption | 11px → 20px |
|
||
|
||
**Modificateurs** : `mono`, `tabular`, `balance` (titres), `pretty` (body), `italic`, `emphasis` (italique + accent), `highlight`, `underline`, `strike`, `gradient`, `rainbow`.
|
||
|
||
> **Choisir le tag (`as`) selon la SÉMANTIQUE, pas selon la taille.** Un titre de page reste `<h1>` même si visuellement il s'affiche en `display-xl`.
|
||
|
||
## Layout & Spacing
|
||
|
||
Grille **4 points** stricte. Multiples de 4 ou 8 uniquement. Aucune valeur intermédiaire (10, 14, 22) qui casse l'alignement vertical.
|
||
|
||
12 niveaux : `0` (0) → `12` (120px).
|
||
|
||
**Densité** adaptable par utilisateur via `[data-mmg-density="comfortable|cozy|compact"]`. Touch target minimum **44×44** quel que soit le mode (WCAG SC 2.5.5).
|
||
|
||
## Elevation & Depth
|
||
|
||
Light mode :
|
||
- `shadow-1` — 0 1px 4px ink + 1px ring
|
||
- `shadow-2` — 0 4px 16px ink + 1px ring
|
||
- `shadow-3` — 0 12px 32px ink (modals, dropdowns)
|
||
- `shadow-elevated` — neutre, pour boutons elevated
|
||
|
||
Dark mode :
|
||
- Ombres = noir + halo blanc subtil 4-6 % (jamais "noir s'évapore")
|
||
- backdrop-filter blur 12-14px sur overlays/popovers/toasts pour effet verre dépoli
|
||
|
||
Ombres teintées accent via `color-mix(in srgb, var(--mmg-color-accent) X%, transparent)` — s'adaptent automatiquement au preset user.
|
||
|
||
## Shapes
|
||
|
||
Pill par défaut sur **interactifs** (buttons, inputs, badges-pills) et **conteneurs principaux** (Tile, Card, Hero).
|
||
|
||
| Token | Valeur | Usage |
|
||
|---|---|---|
|
||
| `rounded-sm` | 8px | inputs, badges-discrets |
|
||
| `rounded-md` | 12px | cards compact, popover, menu |
|
||
| `rounded-card` | 20px | cards principales, tiles |
|
||
| `rounded-panel` | 24px | modals, sheets |
|
||
| `rounded-pill` | 9999px | boutons, badges-pills |
|
||
|
||
## Motion
|
||
|
||
Animation = **feedback fonctionnel**, jamais décoratif. Trois durées :
|
||
|
||
- 120ms — micro-interactions (hover, focus, ripple)
|
||
- 200ms — transitions UI standard
|
||
- 320ms — navigation (modals, drawers, sheets)
|
||
|
||
`prefers-reduced-motion: reduce` désactive tout (durée 0.001ms). WCAG SC 2.3.3 AAA.
|
||
|
||
## Components
|
||
|
||
Catalogue complet (~62 composants) dans `@managemate/react`. Les principaux :
|
||
|
||
**Forms** : Button, Input, Textarea, Select, Combobox, Checkbox, Radio, Switch, Slider, ToggleGroup, FileUpload.
|
||
|
||
**Layout** : Container, Section, Stack, Inline, Card, Tile, Hero.
|
||
|
||
**Feedback** : Alert, Notice, Banner, Badge (avec dot indicator + pulse), Spinner, Skeleton, Toast (pile Sonner-style empilable).
|
||
|
||
**Overlays** : Tooltip, Popover, Menu, Dialog, ConfirmDialog, Sheet (4 sides × 5 sizes), Drawer, HoverCard, ContextMenu — **tous Radix-backed**.
|
||
|
||
**Navigation** : Header (mega-menu DSFR-style), Footer, Breadcrumb, Tabs, Pagination, AppShell, Sidebar, Topbar, SkipLink.
|
||
|
||
**Profile & Cards** : Avatar (status indicator + auto-color), AvatarGroup, UserCard, ProfileHeader (cover + débord), MetricCard (KPI avec trend), PricingCard, FeatureCard, Stat.
|
||
|
||
**Article** : ArticlePage, ArticleHeader, ArticleAside, ArticleFooter, ArticleCallout, ArticleTOC.
|
||
|
||
**Theming** : ThemePicker (radiogroup avec navigation flèches/Home/End).
|
||
|
||
## Do's and Don'ts
|
||
|
||
### ✅ Do
|
||
|
||
- Utiliser les **tokens sémantiques** (`--mmg-color-text-primary`, `--mmg-color-bg-surface`).
|
||
- Choisir le tag HTML selon **la sémantique**, pas selon la taille visuelle.
|
||
- Tester en clavier : Tab, Shift+Tab, Esc, flèches, Enter, Espace.
|
||
- Tester en zoom 200 % et reflow 320px.
|
||
- Tester avec `prefers-reduced-motion: reduce` activé.
|
||
- Préférer les composants Radix-backed (Tooltip, Menu, Dialog…) aux implémentations custom.
|
||
- Documenter le composant dans Storybook + MDX avant de le livrer.
|
||
|
||
### ❌ Don't
|
||
|
||
- **Aucun hex en dur** dans les composants.
|
||
- **Aucune référence directe** à `--mmg-color-synapse-*` — toujours via `--mmg-color-accent-*`.
|
||
- **Pas de couleur seule** porteuse d'info (RGAA 9). Toujours redonder avec icône, texte ou pattern.
|
||
- **Pas de placeholder** en remplacement de label (RGAA 11.1).
|
||
- **Pas de focus invisible** ni `outline: none` sans alternative.
|
||
- **Pas de `<div onClick>`** au lieu de `<button>`.
|
||
- **Pas d'animation** sans `prefers-reduced-motion`.
|
||
- **Pas de composant** sans navigation clavier complète.
|
||
- **Pas de composant** sans test axe-core.
|
||
- **Pas de fichier** monolithique > 300 lignes mélangeant N composants.
|
||
|
||
## Accessibilité (engagement)
|
||
|
||
- **RGAA 4.1 / WCAG 2.2 AA ≥ 95 %**, validé `axe-core` en CI.
|
||
- **Sanctions légales** : jusqu'à 50 000 € par service en ligne non conforme (loi 2005-102 + décret 2019-768).
|
||
- **Couverture handicaps** : visuels (cécité, malvoyance, daltonisme 8 % des hommes), auditifs, moteurs (paralysie, tremblements, bras cassé), cognitifs (dyslexie, TDAH, autisme, fatigue, langue non maternelle), temporaires/situationnels (soleil, mauvaise connexion, vieux device).
|
||
|
||
### Tests automatisés
|
||
|
||
- `axe-core` 4.10 (vitest-axe) — chaque composant interactif.
|
||
- Couverture : `wcag2a + wcag2aa + wcag21a + wcag21aa + best-practice`.
|
||
- Threshold CI : 60 % ligne / branche / function / statement (à monter à 80 % v0.3).
|
||
|
||
### Tests manuels recommandés
|
||
|
||
- NVDA (Windows), VoiceOver (macOS/iOS).
|
||
- Clavier 100 % (souris débranchée).
|
||
- Zoom 200 % + reflow 320px.
|
||
- `prefers-reduced-motion`, `prefers-contrast: more`, `forced-colors: active`.
|
||
|
||
## Distribution
|
||
|
||
Monorepo pnpm avec 4 packages :
|
||
|
||
| Package | Rôle |
|
||
|---|---|
|
||
| `@managemate/tokens` | Source DTCG W3C des tokens. Génère CSS, JS/TS, Figma, Tailwind v3, Tailwind v4. |
|
||
| `@managemate/css` | CSS vanilla — tokens, base, composants, utilitaires `@layer`. |
|
||
| `@managemate/icons` | 96 icônes (line + fill) Remix Icon, subset par icône possible. |
|
||
| `@managemate/react` | Composants React typés, headless-first sur Radix UI, tree-shakable (`sideEffects: false`). |
|
||
|
||
Versioning : SemVer strict. Packages **fixed** (même version) pour éviter les incompatibilités cross-package. Changesets sur `main` → release auto.
|
||
|
||
---
|
||
|
||
> Ce fichier est lisible par des agents IA via le format [google-labs-code/design.md](https://github.com/google-labs-code/design.md). Front matter YAML = tokens normatifs, corps Markdown = contexte d'application.
|