chore: initial DSMMG v0.2 — refonte architecturale complète
Release / Release / open changeset PR (push) Has been cancelled
CI / Build, typecheck, test, a11y (push) Has been cancelled

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>
This commit is contained in:
Dinawo
2026-05-04 22:07:57 +02:00
parent 5e019857fc
commit 62317f2ad7
172 changed files with 31397 additions and 1 deletions
+72
View File
@@ -0,0 +1,72 @@
import { defineConfig } from "astro/config";
import starlight from "@astrojs/starlight";
export default defineConfig({
site: "https://design.managemate.fr",
integrations: [
starlight({
title: "DSMMG",
description: "Design System ManageMate Group — référence pour designers et développeurs",
defaultLocale: "fr",
locales: { fr: { label: "Français", lang: "fr" } },
logo: { src: "./src/assets/logo.svg", replacesTitle: false },
social: {
github: "https://github.com/managemate/dsmmg",
},
customCss: ["./src/styles/custom.css", "@managemate/css", "@managemate/icons"],
sidebar: [
{
label: "Démarrer",
items: [
{ label: "Introduction", slug: "intro" },
{ label: "Installation", slug: "intro/installation" },
{ label: "Migration v0.1 → v0.2", slug: "intro/migration" },
],
},
{
label: "Fondations",
items: [
{ label: "Tokens", slug: "fondations/tokens" },
{ label: "Couleurs", slug: "fondations/colors" },
{ label: "Typographie", slug: "fondations/typography" },
{ label: "Espacement", slug: "fondations/spacing" },
{ label: "Motion", slug: "fondations/motion" },
{ label: "Densité", slug: "fondations/density" },
],
},
{
label: "Theming utilisateur",
items: [
{ label: "Architecture accent", slug: "theming/architecture" },
{ label: "Presets", slug: "theming/presets" },
{ label: "Mode sombre", slug: "theming/dark-mode" },
],
},
{
label: "Accessibilité",
items: [
{ label: "Engagement RGAA", slug: "a11y/engagement" },
{ label: "Tests automatisés", slug: "a11y/tests" },
{ label: "Patterns clavier", slug: "a11y/keyboard" },
],
},
{
label: "Composants",
autogenerate: { directory: "components" },
},
{
label: "Patterns",
autogenerate: { directory: "patterns" },
},
{
label: "Contribution",
items: [
{ label: "Comment contribuer", slug: "contrib/how" },
{ label: "RFC process", slug: "contrib/rfc" },
{ label: "Versioning", slug: "contrib/versioning" },
],
},
],
}),
],
});
+19
View File
@@ -0,0 +1,19 @@
{
"name": "docs",
"private": true,
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "astro dev --port 4321",
"start": "astro dev --port 4321",
"build": "astro build",
"preview": "astro preview"
},
"dependencies": {
"@astrojs/starlight": "^0.30.0",
"@managemate/css": "workspace:*",
"@managemate/icons": "workspace:*",
"astro": "^5.0.0",
"sharp": "^0.33.0"
}
}
+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="32" height="32" aria-hidden="true">
<rect width="64" height="64" rx="14" fill="#D12B6A"/>
<path d="M14 46V18h6.4l8.8 13.5L38.1 18h6.3v28h-6.3V28.6l-7.6 11.6h-1.7l-7.5-11.5V46H14z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 272 B

+38
View File
@@ -0,0 +1,38 @@
---
title: Engagement RGAA
description: Accessibilité = priorité non-négociable du DSMMG.
---
## Pourquoi
- **12M de Français** en situation de handicap (visuel, auditif, moteur, cognitif).
- Plusieurs clients ManageMate sont des **collectivités, opérateurs publics ou entreprises >250M€ CA****soumis au RGAA par la loi**.
- Sanctions jusqu'à **50 000 €** par service en ligne non conforme (LOI n° 2005-102 + décret 2019-768 + ordonnance 2018-1102).
- Argument commercial fort sur les **appels d'offres publics**.
## Niveau cible
**RGAA 4.1 — équivalent WCAG 2.1 AA — couverture ≥ 95 %**, validé automatiquement en CI via `axe-core`.
## Couverture par composant
| Composant | axe-core | clavier | lecteur d'écran | Forced colors |
|---|---|---|---|---|
| Button | ✓ | ✓ Tab/Enter/Space | ✓ role + label | ✓ |
| Input/Field | ✓ | ✓ | ✓ label, erreurs aria-describedby | ✓ |
| Combobox | ✓ | ✓ flèches/Home/End/Enter/Esc | ✓ activedescendant | ✓ |
| Tooltip (Radix) | ✓ | ✓ Esc | ✓ role=tooltip | ✓ |
| Dialog (Radix) | ✓ | ✓ focus trap, Esc, restitution | ✓ aria-labelledby/describedby | ✓ |
| Menu (Radix) | ✓ | ✓ flèches/type-ahead/Esc | ✓ menuitem | ✓ |
| ThemePicker | ✓ | ✓ flèches/Home/End | ✓ radiogroup + radios labellés | ✓ |
## Refus absolus
- ❌ Couleur seule porteuse d'information
- ❌ Placeholder en remplacement de label (RGAA 11.1)
- ❌ Focus invisible ou supprimé sans alternative
-`<div onClick>` au lieu de `<button>`
- ❌ Animation sans `prefers-reduced-motion`
- ❌ Contraste en-dessous de AA "pour le style"
- ❌ Composant sans test axe-core
- ❌ Composant sans navigation clavier complète
+39
View File
@@ -0,0 +1,39 @@
---
title: Patterns clavier
description: Conventions clavier appliquées dans tous les composants DSMMG.
---
## Patterns standard
| Composant | Touches |
|---|---|
| Button | `Enter` / `Space` |
| Tab dans formulaire | `Tab` / `Shift+Tab` |
| Modal / Dialog | `Esc` ferme, focus trap, restitution focus |
| Tooltip | `Esc` ferme, focus trigger affiche |
| Menu | `↓ ↑` navigue, `Enter` sélectionne, `type-ahead`, `Esc` ferme |
| Combobox | `↓ ↑` navigue suggestions, `Home/End`, `Enter` sélectionne, `Esc` ferme |
| Tabs | `← →` navigue (manual activation), `Enter` active |
| ThemePicker (radiogroup) | `← → ↑ ↓ Home End` navigue + sélectionne |
| Accordion | `Enter` / `Space` toggle |
## Raccourcis globaux
Le système de raccourcis (`ShortcutProvider`) propose :
- `Cmd/Ctrl + K` : ouvre `CommandMenu` (palette d'actions)
- `?` : affiche la `ShortcutCheatsheet` contextuelle
- Séquences (vim-style) supportées : `g i` = go to inbox, `g s` = go to settings
```tsx
import { useShortcut } from "@managemate/react";
useShortcut(
{ keys: "n", description: "Nouveau ticket", scope: "synapse" },
() => createTicket(),
);
```
## Skip link
`<SkipLink />` à poser comme premier enfant de `<body>`. Sauts visuels Tab visibles. Cible : `<main id="main">` par défaut.
+54
View File
@@ -0,0 +1,54 @@
---
title: Tests automatisés
description: Comment l'accessibilité est validée en CI.
---
## Stack
- **Vitest** (runner)
- **@testing-library/react** (rendu + interactions)
- **@testing-library/user-event** (simulation clavier réaliste)
- **vitest-axe** (axe-core 4.10 en assertions)
- **jsdom** (environnement DOM)
## Exemple de test
```tsx
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { axe } from "vitest-axe";
import { Button } from "./Button";
it("est focusable au clavier", async () => {
const user = userEvent.setup();
render(<Button>OK</Button>);
await user.tab();
expect(screen.getByRole("button")).toHaveFocus();
});
it("aucune violation axe-core", async () => {
const { container } = render(<Button>OK</Button>);
expect(await axe(container)).toHaveNoViolations();
});
```
## Politique CI
- Le job `test` du workflow CI échoue si :
- une violation axe est détectée dans un test ;
- un test clavier échoue ;
- la couverture descend sous 60 % (threshold).
## Storybook a11y
Le panneau **Accessibility** (addon-a11y) s'affiche pour chaque story. Configuré pour `wcag2a + wcag2aa + wcag21a + wcag21aa + best-practice`.
## Tests manuels conseillés
axe-core couvre ~40 % des règles WCAG. Compléter par :
- **NVDA** (Windows) ou **VoiceOver** (macOS)
- **Navigation 100 % clavier** (souris débranchée)
- **Zoom 200 %** + reflow 320px de large
- **`prefers-reduced-motion`** activé
- **Forced colors / High Contrast Mode** (Windows)
@@ -0,0 +1,71 @@
---
title: Button
description: Bouton DSMMG — variants Material 3 / Fluent, pill par défaut, tous états couverts.
---
## Anatomie
```
┌────────────────────────────────┐
│ [icon] Label [trailing icon]│
└────────────────────────────────┘
```
## Variants
| Variant | Quand l'utiliser |
|---|---|
| `primary` | Action principale d'une page/section. Un seul par bloc. |
| `tonal` | Action importante mais pas la principale. |
| `secondary` | Action neutre, outline accent. |
| `tertiary` | Action discrète mais visible. |
| `ghost` | Action très discrète, dans un toolbar. |
| `elevated` | Quand le bouton flotte sur un fond chargé (image). |
| `danger` | Suppression, action destructive. |
| `success` | Validation positive (rare, généralement preferring primary). |
## Sizes
`xs` (28px), `sm` (34px), `md` (40px, défaut), `lg` (48px), `xl` (56px).
`md` et plus respectent la cible tactile WCAG 2.5.5 (≥ 44×44 effective). Pour `xs`/`sm` en `icon-only`, une zone tactile invisible 44×44 est ajoutée via `::after`.
## API
```tsx
import { Button } from "@managemate/react";
<Button
variant="primary"
size="md"
icon="arrow-right-line"
iconPosition="right"
loading={false}
disabled={false}
block={false}
onClick={() => {}}
>
Continuer
</Button>
```
## Do / Don't
**Do**
- Un seul `primary` par section logique.
- Verbes d'action concrets : "Sauvegarder", "Continuer", "Supprimer".
- `aria-label` sur les `icon-only`.
**Don't**
- Pas de "Cliquez ici" / "Soumettre" / "OK" génériques.
- Ne pas désactiver un bouton sans aria-explication ; préférer le rendre actif et afficher l'erreur après.
- Ne pas remplacer un `<a>` (navigation) par un `<button>`. Sémantique avant tout.
## A11y
- `<button type="button">` natif. Sémantique correcte garantie.
- `disabled` empêche `pointer-events` et le focus.
- `loading` affiche un spinner et bloque les clicks ; pas d'`aria-busy` requis (le state est dans la classe).
- Ratio de contraste : tous les variants respectent AA contre `--mmg-color-bg-surface` et `--mmg-color-bg-page`.
+21
View File
@@ -0,0 +1,21 @@
---
title: Composants
description: Catalogue des composants DSMMG.
---
Les composants sont documentés en détail dans **Storybook** (live, props auto-générées). Cette section donne les guidelines (anatomie, do/don't, a11y).
→ [Storybook](https://design.managemate.fr/storybook)
## Catégories
| Catégorie | Composants |
|---|---|
| **Forms** | Button, Input, Textarea, Select, Combobox, Checkbox, Radio, Switch, Field, FileUpload, SearchBar |
| **Layout** | Container, Section, Stack, Inline, Card, Tile, Hero |
| **Feedback** | Alert, Notice, Banner, Badge, Spinner, Skeleton, Toast |
| **Overlays** | Tooltip, Popover, Menu, Dialog, ConfirmDialog, Drawer |
| **Navigation** | Header, Footer, Breadcrumb, Tabs, Pagination, AppShell, Sidebar, Topbar |
| **Data display** | DataTable, Stat, Avatar, Tag, Progress, EmptyState |
| **Article** | ArticlePage, ArticleHeader, ArticleAside, ArticleFooter, ArticleCallout, ArticleTOC |
| **Theming** | ThemePicker |
+47
View File
@@ -0,0 +1,47 @@
---
title: Comment contribuer
description: Workflow de contribution au DSMMG.
---
## Setup local
```sh
git clone <repo>
cd managemate-ds
pnpm install
pnpm build # build tous les packages dans le bon ordre
pnpm storybook # lance Storybook localement
pnpm --filter @managemate/react test:watch
```
## Workflow de PR
1. Branch depuis `main` : `feat/...`, `fix/...`, `chore/...`.
2. Modifier le code.
3. **Ajouter un changeset** : `pnpm changeset` (sélectionner les packages impactés et le bump).
4. Tests + Storybook updates obligatoires.
5. Push, ouvrir la PR.
6. CI doit passer (lint + types + tests + axe + size-limit + Storybook build).
7. 1 review minimum (CODEOWNERS).
## Conventions
- **Commits** : conventional commits (`feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`).
- **Branches** : `<type>/<short-description>`.
- **Code** : Prettier + ESLint via la config workspace (à venir).
## Ajouter un nouveau composant
1. Créer `packages/react/src/<Component>.tsx` (un fichier, exports nommés).
2. Si CSS dédié : ajouter `packages/css/src/components/<comp>.css` + l'importer dans `index.css` avec `layer(components)`.
3. Story Storybook : `storybook/stories/<Component>.stories.tsx` avec au minimum default + variants + states.
4. Tests : `packages/react/src/<Component>.test.tsx` (axe + clavier + interactions).
5. Doc MDX : `docs/src/content/docs/components/<component>.md` (anatomie, props, do/don't, a11y).
6. Export dans `packages/react/src/index.tsx`.
7. Changeset minor.
> **Un composant non documenté n'est pas livré.**
## RFC pour les changements majeurs
Voir [RFC process](/contrib/rfc/).
+50
View File
@@ -0,0 +1,50 @@
---
title: RFC process
description: Quand et comment proposer une RFC.
---
Une **RFC (Request for Comments)** est requise pour :
- Nouveau composant non-trivial (DataTable, Calendar…)
- Breaking change sur l'API publique d'un composant existant
- Refonte d'un token ou d'un groupe de tokens
- Nouvelle dépendance externe (ex: ajouter Floating UI)
- Changement architectural (build, tree-shaking, distribution)
## Format
PR sur `docs/src/content/docs/rfcs/000X-<titre>.md` avec :
```md
---
title: RFC 0001 — Nom de la RFC
status: draft | accepted | rejected | superseded
author: <handle>
date: YYYY-MM-DD
---
## Contexte
Pourquoi cette RFC ? Quel problème ?
## Proposition
La solution. Code, schémas, exemples.
## Alternatives
Ce qu'on a écarté et pourquoi.
## Coût migration
Codemod possible ? Effort consommateur ?
## Risques
A11y, perf, DX, lock-in.
## Décision
À remplir après discussion.
```
## Cycle
1. Auteur ouvre la PR `docs(rfc): 000X — title`.
2. Au moins **2 reviewers** (un design, un code).
3. Discussion ouverte ≥ 7 jours.
4. Décision : `accepted` → implémentation dans une PR séparée. `rejected` → on garde la RFC en archive.
@@ -0,0 +1,44 @@
---
title: Versioning
description: SemVer strict, packages liés, deprecation policy.
---
## SemVer strict
- **major** : breaking change sur l'API publique
- rename/suppression d'export
- signature de prop modifiée
- rename de token CSS
- changement structurel du DOM rendu (peut casser des sélecteurs CSS consommateurs)
- **minor** : addition non-breaking
- nouveau composant
- nouvelle prop optionnelle
- nouveau token
- nouvelle variante
- **patch** : bugfix, doc, perf interne sans surface publique
## Fixed packages
`@managemate/css`, `@managemate/react`, `@managemate/icons`, `@managemate/tokens` sont **fixed** (même version), pour éviter les incompatibilités de tokens entre CSS et React.
## Deprecation policy
1. Ajouter `@deprecated` JSDoc sur l'API à supprimer + indiquer le remplacement.
2. Émettre un warning console en dev (`process.env.NODE_ENV !== "production"`).
3. **Au minimum un cycle minor** entre deprecation et suppression.
4. Suppression dans un major, listée explicitement dans le CHANGELOG.
## Codemods
Tout breaking change qui peut être migré automatiquement **doit** fournir un codemod.
Voir `scripts/migrate-tokens.mjs` comme référence.
## Workflow Changesets
```sh
pnpm changeset # ajouter un changeset
pnpm version-packages # consume les changesets, bump versions
pnpm release # build + publish
```
CI gère ça via GitHub Actions sur `main` (voir `.github/workflows/release.yml`).
@@ -0,0 +1,39 @@
---
title: Couleurs
description: Palette neutre + presets accent + sémantique.
---
import { Aside } from "@astrojs/starlight/components";
<Aside type="caution">
Pour la **palette interactive** avec swatches en live, voir <a href="https://design.managemate.fr/storybook/?path=/docs/tokens-colors--docs">Storybook → Tokens → Colors</a>.
</Aside>
## 3 catégories
1. **Neutres** — bg, text, border. Stables.
2. **Sémantiques** — success/warning/danger/info. **Stables, pas affectées par l'accent user.**
3. **Accent** — user-themable, 9 presets.
## Contrastes garantis
| Combinaison | Ratio | Niveau |
|---|---|---|
| `text-primary` sur `bg-page` | ≥ 12:1 | AAA |
| `text-secondary` sur `bg-page` | ≥ 7:1 | AAA |
| `text-tertiary` sur `bg-page` | ≥ 4.5:1 | AA |
| `text-quaternary` sur `bg-page` | ≥ 4:1 | (limite, pour placeholder uniquement) |
| `accent-on` sur `accent` | ≥ 4.5:1 | AA — sur tous les presets |
| `accent` sur `bg-page` | ≥ 3:1 | AA non-texte |
## Daltonisme
8 % des hommes (1/12) ont un trouble de la perception des couleurs. Aucune information ne doit reposer **uniquement** sur la couleur :
- Status badges → icône + texte ("Résolu" + check, pas juste un point vert).
- Sparkline / graphique → patterns + labels.
- Validation form → message + bordure rouge + icône `alert`.
## OKLCH
Les ramps sont conçues en OKLCH (perception uniforme). Rendu en hex pour compat IE/Safari < 15.4. Migration `oklch()` envisagée quand support ≥ 95 %.
@@ -0,0 +1,30 @@
---
title: Densité
description: 3 modes adaptables par préférence utilisateur.
---
## Modes
| Mode | Scale | Row height | Padding | Pour qui |
|---|---|---|---|---|
| `comfortable` (défaut) | 1.0 | 44 | x:16, y:12 | Espace-Client, sites publics, mobile |
| `cozy` | 0.85 | 36 | x:12, y:8 | Apps métier (Synapse, HRTime, Forge…) |
| `compact` | 0.72 | 28 | x:8, y:4 | Power users, 6h+/jour, dashboards denses |
## Application
Sur un sous-arbre (généralement `<body>` ou un container) :
```html
<body data-mmg-density="cozy">
```
Les composants qui consomment `--mmg-density-*` héritent automatiquement.
## Persistance
Recommandation : exposer un toggle dans les préférences user, persister en localStorage + DB user, appliquer en SSR pour éviter le flash.
## Touch target minimum
Quel que soit le mode, la **cible tactile reste ≥ 44×44** (WCAG SC 2.5.5). En `compact`, la cible visible peut être plus petite mais une zone tactile invisible la complète (cf. `Button.tsx` icon-only).
@@ -0,0 +1,24 @@
---
title: Motion
description: Animation = feedback fonctionnel, jamais décoratif.
---
## Tokens
| Token | Valeur | Usage |
|---|---|---|
| `--mmg-duration-fast` | 120ms | micro-interactions (hover, focus, ripple) |
| `--mmg-duration-base` | 200ms | transitions UI (panels, popovers) |
| `--mmg-duration-slow` | 320ms | navigation (modals, drawers) |
| `--mmg-ease-default` | cubic-bezier(0.4, 0, 0.2, 1) | matériel, doux |
| `--mmg-ease-emphasis` | cubic-bezier(0.2, 0.8, 0.2, 1) | rebond / overshoot léger |
## Règles
- **Animation = feedback** — toujours expliquer ce qui se passe (apparition, disparition, état).
- **Jamais décorative** — pas de "pour faire joli".
- **Entry: ease-out**, **Exit: ease-in**, **Continuous: ease-in-out**.
## prefers-reduced-motion
Toutes les animations sont désactivées (durée 0.001ms) sous `@media (prefers-reduced-motion: reduce)` (WCAG SC 2.3.3 AAA + bonne pratique AA). Cf. utilisateurs sensibles vestibulaire, migraine, attention.
@@ -0,0 +1,44 @@
---
title: Espacement
description: Grille 4pt — multiples de 4 ou 8 exclusivement.
---
## Tokens
| Token | px |
|---|---|
| `--mmg-space-0` | 0 |
| `--mmg-space-1` | 4 |
| `--mmg-space-2` | 8 |
| `--mmg-space-3` | 12 |
| `--mmg-space-4` | 16 |
| `--mmg-space-5` | 20 |
| `--mmg-space-6` | 24 |
| `--mmg-space-7` | 32 |
| `--mmg-space-8` | 40 |
| `--mmg-space-9` | 48 |
| `--mmg-space-10` | 64 |
| `--mmg-space-11` | 80 |
| `--mmg-space-12` | 120 |
## Règles
- **Toujours utiliser un token.** Aucun `padding: 17px` en dur.
- **Multiples de 4 ou 8** uniquement. Évite les valeurs intermédiaires (10, 14, 22) qui cassent l'alignement vertical.
- **Densité adaptable** : `--mmg-density-padding-{x,y}` change avec `[data-mmg-density]`. Préférer ces tokens aux `--mmg-space-*` directs dans les composants soumis à la densité.
## Utilitaires
```html
<div class="mmg-u-stack mmg-u-stack-4">
<!-- gap: 16px -->
</div>
```
| Class | Effect |
|---|---|
| `mmg-u-gap-{1..6}` | gap: var(--mmg-space-N) |
| `mmg-u-stack-{1..6}` | flex column + gap |
| `mmg-u-mt-{1..6}` | margin-top |
| `mmg-u-mb-{1..6}` | margin-bottom |
| `mmg-u-p-{0,2,3,4,6}` | padding |
@@ -0,0 +1,55 @@
---
title: Tokens
description: Architecture des tokens DSMMG.
---
Les tokens sont organisés en **3 couches**, du bas vers le haut :
```
primitives → semantic → accent (presets user)
```
## 1. Primitives
Rampes de couleur brutes (`--mmg-color-{neutral,synapse,blue,…}-{50..900}`), non utilisées directement par les composants.
## 2. Semantic
Tokens de rôle qui mappent les primitives. **Les composants consomment ceci.**
- `--mmg-color-bg-{page,surface,raised,muted,subtle,overlay}` — surfaces
- `--mmg-color-text-{primary,secondary,tertiary,quaternary,inverse}` — texte
- `--mmg-color-border{,-soft,-strong}` — bordures
- `--mmg-color-{success,warning,danger,info}{,-soft,-border,-strong,-on}` — sémantique fixe
## 3. Accent (user-themable)
`--mmg-color-accent{,-hover,-active,-soft,-border,-strong,-on}` — la SEULE couleur user-themable. Posée par `[data-mmg-accent="<preset>"]` sur `<html>`.
## Non-color
| Catégorie | Préfixe | Exemple |
|---|---|---|
| Espacement | `--mmg-space-{0..12}` | `var(--mmg-space-4)` = 16px |
| Rayons | `--mmg-radius-{sm,md,card,panel,icon,pill}` | |
| Font size | `--mmg-font-size-{xs,sm,base,lg,xl,2xl..5xl}` | |
| Font weight | `--mmg-font-weight-{regular,medium,semi,bold,extra}` | |
| Line height | `--mmg-line-height-{tight,snug,normal}` | |
| Motion | `--mmg-duration-{fast,base,slow}`, `--mmg-ease-{default,emphasis}` | |
| Z-index | `--mmg-z-{dropdown,sticky,modal,toast,tooltip}` | |
| Density | `--mmg-density-{scale,row-height,input-height,padding-x,padding-y}` | |
## Source unique : DTCG
`packages/tokens/src/tokens.json` au format **W3C Design Tokens Community Group**. Style Dictionary génère :
- `dist/tokens.css` — les CSS custom properties
- `dist/tokens.{js,cjs,d.ts}` — un objet JS/TS auto-completé pour le code
- `dist/figma-tokens.json` — pour le plugin Figma Tokens Studio
## Règles
- **Aucun hex en dur** dans les composants. Toujours via tokens.
- **Aucun `--mmg-color-synapse-*` direct** : utiliser `--mmg-color-accent-*`.
- **Pas de nouveau token sans changeset** : les tokens sont une API publique.
- **Renommage** = breaking change → bump major + codemod fourni.
@@ -0,0 +1,53 @@
---
title: Typographie
description: Figtree + échelle modulaire + line-heights.
---
## Famille
`Figtree` (Google Fonts) — sans-serif géométrique moderne. Fallback : `system-ui, -apple-system, "Segoe UI", Roboto, sans-serif`.
```css
font-family: var(--mmg-font-sans);
```
Mono : `ui-monospace, "JetBrains Mono", "SF Mono", Menlo, monospace`.
## Échelle
| Token | px | Usage |
|---|---|---|
| `--mmg-font-size-xs` | 11 | annotations, métadonnées |
| `--mmg-font-size-sm` | 13 | UI dense (inputs, boutons sm), hint |
| `--mmg-font-size-base` | 15 | corps de texte |
| `--mmg-font-size-lg` | 17 | corps de texte plus aéré |
| `--mmg-font-size-xl` | 20 | h4 / sous-titres |
| `--mmg-font-size-2xl` | 24 | h3 |
| `--mmg-font-size-3xl` | 30 | h2 |
| `--mmg-font-size-4xl` | 36 | h1 |
| `--mmg-font-size-5xl` | 48 | hero / display |
## Weights
| Token | Valeur |
|---|---|
| `regular` | 400 |
| `medium` | 500 |
| `semi` | 600 |
| `bold` | 700 |
| `extra` | 800 |
## Line heights
- `tight` (1.2) — titres, boutons
- `snug` (1.4) — UI dense
- `normal` (1.6) — corps de texte
## B1 du CECRL — pour les sites publics
Espace-Client et sites publics doivent viser le **niveau B1 du CECRL** :
- Phrases courtes (< 25 mots).
- Vocabulaire courant.
- Pas de jargon ni d'acronymes non explicités.
- Voix active.
+45
View File
@@ -0,0 +1,45 @@
---
title: DSMMG — Design System ManageMate Group
description: Référence design + code pour les produits ManageMate. RGAA 4.1, headless-first, tokens W3C DTCG.
template: splash
hero:
tagline: La source de vérité visuelle, comportementale et accessible pour Synapse, HRTime, Forge, Orbit, MSLM et l'Espace-Client.
actions:
- text: Démarrer
link: /intro/
icon: right-arrow
variant: primary
- text: Storybook
link: https://design.managemate.fr/storybook
icon: external
variant: minimal
---
import { Card, CardGrid, LinkCard } from "@astrojs/starlight/components";
## Pourquoi un DS ?
Un design system n'est pas un dossier de composants. C'est **la garantie** que toute UI sortie sous la marque ManageMate :
- respecte le **RGAA 4.1** (= WCAG 2.2 AA) — non-négociable, validé en CI ;
- est **cohérente cross-produit** — un bouton dans Synapse, HRTime, Forge ou Orbit a la même forme, le même contraste, le même comportement clavier ;
- est **theming user-aware** — chaque utilisateur peut choisir son accent parmi 9 presets validés.
## Couverture
<CardGrid>
<Card title="62 composants" icon="puzzle">React headless-first, sur primitives Radix UI + Floating UI.</Card>
<Card title="9 presets accent" icon="seti:image">Synapse (défaut), rose, blue, violet, green, amber, red, cyan, slate.</Card>
<Card title="3 densités" icon="setting">Comfortable / cozy / compact, adaptables par préférence user.</Card>
<Card title="2 thèmes" icon="moon">Light + dark, sémantique cohérente, accent qui pop sans noyer le contenu.</Card>
</CardGrid>
## Standards
| Niveau | Inspirations |
|---|---|
| Architecture & a11y | shadcn/ui, Radix UI, Ariakit, React Aria |
| Patterns SaaS dense | Linear, Notion, Vercel, Atlassian DS |
| Apps enterprise | IBM Carbon, Atlassian |
| Méthodologie a11y | DSFR, DSFR.gouv.fr |
| Mobile / mobile patterns | Apple HIG, Material Design 3 |
+29
View File
@@ -0,0 +1,29 @@
---
title: Introduction
description: Bienvenue dans le DSMMG.
---
Le **DSMMG** (Design System ManageMate Group) est la source de vérité unique pour toutes les interfaces des produits ManageMate.
## Architecture des packages
| Package | Rôle |
|---|---|
| `@managemate/tokens` | Source DTCG des tokens primitifs. Génère CSS, JS/TS, Figma. |
| `@managemate/css` | CSS vanilla — tokens, base reset, 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, tree-shakable. |
## Principes
1. **Accessibilité = première classe.** RGAA 4.1, validé axe-core en CI. Refus de toute solution qui exclut une catégorie d'utilisateurs.
2. **Headless-first.** Les comportements (focus management, ARIA, keyboard nav) viennent de Radix UI. Le style vient des tokens DSMMG. Séparation stricte.
3. **Tokens partout.** Aucun hex en dur dans un composant. Couleur d'accent toujours via `--mmg-color-accent`, jamais `--mmg-color-synapse` direct.
4. **Tree-shakable.** Un fichier par composant. `sideEffects: false`. L'import d'un Button n'embarque pas le DataTable.
5. **Theming user-aware.** L'utilisateur choisit son accent. La sémantique (success/danger…) reste fixe.
6. **Pro-friendly.** Densité adaptable, raccourcis clavier first-class, bulk actions, optimistic UI, vues sauvegardées.
## Démarrer
→ [Installation](/intro/installation/)
→ [Migration v0.1 → v0.2](/intro/migration/)
@@ -0,0 +1,83 @@
---
title: Installation
description: Comment installer le DSMMG dans un projet ManageMate.
---
## Pré-requis
- Node ≥ 20
- pnpm ≥ 9 (ou npm/yarn équivalents)
- React ≥ 18
## Install
```sh
pnpm add @managemate/css @managemate/icons @managemate/react
```
## Setup minimal
### 1. Importer les CSS
```tsx
// app/main.tsx — ou _app.tsx en Next
import "@managemate/css";
import "@managemate/icons";
```
L'ordre n'a pas d'importance grâce à la cascade `@layer reset, tokens, base, components, utilities`.
### 2. (Optionnel) Mettre un thème initial
```tsx
import { applyTheme, applyAccent } from "@managemate/react";
// Dès le mount du root, idéalement avant React render
applyTheme("system"); // ou "light" / "dark"
applyAccent("synapse"); // ou un autre preset
```
Mieux : appliquer en SSR via un script inline pour éviter le flash :
```html
<script>
(function () {
try {
var t = localStorage.getItem("mmg-theme");
var a = localStorage.getItem("mmg-accent");
if (t && t !== "system") document.documentElement.setAttribute("data-mmg-theme", t);
if (a && a !== "synapse") document.documentElement.setAttribute("data-mmg-accent", a);
} catch (e) {}
})();
</script>
```
### 3. Wrapper Provider à la racine
```tsx
import { TooltipProvider, ToastProvider } from "@managemate/react";
<TooltipProvider>
<ToastProvider>
<App />
</ToastProvider>
</TooltipProvider>
```
### 4. Premier composant
```tsx
import { Button } from "@managemate/react";
<Button variant="primary" icon="arrow-right-line" iconPosition="right">
Continuer
</Button>
```
## Tree-shaking
Tous les exports sont nommés et `sideEffects: false`. L'import suivant ne tire que `Button` + `Icon` + `cx` :
```tsx
import { Button } from "@managemate/react";
```
+60
View File
@@ -0,0 +1,60 @@
---
title: Migration v0.1 → v0.2
description: Guide de migration vers la nouvelle architecture DSMMG.
---
La v0.2 est une **refonte architecturale** avec breaking changes. Elle prépare le DS à un usage réel cross-produit avec theming utilisateur, tree-shaking strict, primitives Radix.
## Codemod automatique
Un codemod est fourni pour renommer la majorité des tokens dans ton codebase consommateur :
```sh
node scripts/migrate-tokens.mjs
```
Il modifie en place les `.css` et `.tsx` selon une table de mapping idempotente.
## Token renames (mapping principal)
| Avant | Après |
|---|---|
| `--mmg-bg-page/surface/raised/muted/subtle/overlay` | `--mmg-color-bg-*` |
| `--mmg-text-1/2/3/4` | `--mmg-color-text-{primary,secondary,tertiary,quaternary}` |
| `--mmg-text-inverse` | `--mmg-color-text-inverse` |
| `--mmg-text-{xs..5xl}` | `--mmg-font-size-*` |
| `--mmg-leading-*` | `--mmg-line-height-*` |
| `--mmg-weight-*` | `--mmg-font-weight-*` |
| `--mmg-border/border-soft/border-strong` | `--mmg-color-border*` |
| `--mmg-brand-*` | `--mmg-color-accent-*` |
| `--mmg-success/warning/danger/info-*` | `--mmg-color-success/warning/danger/info-*` |
| `--mmg-shadow-brand-*` | `--mmg-shadow-accent-*` |
| `--mmg-art-*` | `--mmg-color-art-*` |
| `--mmg-state-*` | `--mmg-color-state-*` |
## API React — changements
### `Tooltip`, `Popover`, `Menu`, `Dialog`, `Combobox`
Réécrits sur **Radix UI + Floating UI**. L'API publique est globalement préservée mais :
- `Menu` : la prop `items[i].onClick` devient `onSelect` (cohérent avec Radix). Les flèches, type-ahead et focus management sont gérés natif.
- `Tooltip` : exige `<TooltipProvider>` à la racine. Les délais sont partagés entre tooltips voisins.
- `Combobox` : nouvelle prop `emptyMessage`, navigation `Home`/`End`, `aria-activedescendant`.
### Suppression du switch produit
`[data-mmg-product]` est retiré au profit de `[data-mmg-accent]`. Chaque utilisateur choisit son accent (par défaut Synapse). Voir [Architecture accent](/theming/architecture/).
### Composants splittés
`Advanced.tsx`, `Chrome.tsx`, `Article.tsx` ont été éclatés en un fichier par composant. Imports inchangés via le barrel.
## Nouveautés
- 9 presets accent + ramps -50/-900 + `-on` validé AA
- Composant `<ThemePicker />` + hooks `useAccent`, `useTheme`
- Cascade `@layer reset, tokens, base, components, utilities`
- Utilitaires CSS `mmg-u-*` (stack, flex, grid, text, bg, padding, margin)
- Build packages — distribution via `dist/` (ESM + CJS + types)
- Storybook + tests Vitest + axe-core en CI
+18
View File
@@ -0,0 +1,18 @@
---
title: Patterns
description: Patterns d'interaction et de composition récurrents dans les apps ManageMate.
---
## Power user patterns
- **Densité adaptable** — 3 modes (comfortable / cozy / compact).
- **Raccourcis clavier first-class** — registry centralisé, cmd+K, séquences vim-style.
- **Bulk actions** — toolbar contextuelle sticky sur sélection.
- **Vues sauvegardées** — filtres + colonnes + tri + group sous un nom partageable.
- **Optimistic UI** — actions appliquées instantanément, réconciliation serveur.
- **Inline editing** — clic = édition, Enter valide, Esc annule.
- **Recherche fuzzy partout** — typos tolérées, highlight des matches.
- **Drag and drop avec alternative clavier** — toujours.
- **Empty states contextuels** — pas de "no data" générique.
Détails et exemples → en cours, à compléter.
@@ -0,0 +1,102 @@
---
title: Architecture du theming user
description: Comment l'accent personnalisable est structuré dans le DSMMG.
---
## Le problème
Plusieurs apps ManageMate (Synapse, HRTime, Forge, Orbit, MSLM) doivent permettre à chaque utilisateur de **choisir sa couleur d'accent**, tout en garantissant :
- **WCAG AA** sur tous les fonds (light, dark, raised).
- **Consistance cross-produit** : le bouton primary fait la même *forme*, juste une autre teinte.
- **Pas de flash** au chargement (FOUC).
- **Sémantique préservée** : un Alert danger reste rouge même si l'accent est rouge.
## La solution
Indirection systématique :
```
[data-mmg-accent="<preset>"] ─┐
├─→ --mmg-color-accent (et dérivés) ─→ Composants
[data-mmg-theme="dark"] ─┘
```
### 1. Les composants consomment `--mmg-color-accent-*`
```css
.mmg-btn--primary {
background: var(--mmg-color-accent);
color: var(--mmg-color-accent-on);
box-shadow: var(--mmg-shadow-accent);
}
```
**Jamais** :
```css
.mmg-btn--primary {
background: var(--mmg-color-synapse-500); /* ❌ casse le theming user */
}
```
### 2. Les presets posent les valeurs
`packages/css/src/tokens/accent.css` définit pour chaque preset :
```css
[data-mmg-accent="blue"] {
--mmg-color-accent: var(--mmg-color-blue-500);
--mmg-color-accent-hover: var(--mmg-color-blue-600);
--mmg-color-accent-active: var(--mmg-color-blue-700);
--mmg-color-accent-soft: var(--mmg-color-blue-50);
--mmg-color-accent-border: var(--mmg-color-blue-200);
--mmg-color-accent-strong: var(--mmg-color-blue-800);
--mmg-color-accent-on: var(--mmg-color-neutral-0);
}
```
### 3. Le hook `useAccent` synchronise localStorage et `<html>`
```tsx
import { useAccent } from "@managemate/react";
const { accent, setAccent, reset } = useAccent();
```
Ou impératif :
```ts
import { applyAccent } from "@managemate/react";
applyAccent("blue", true); // persist=true par défaut
```
### 4. Pour éviter le flash en SSR
Inclure ce script dans le `<head>` :
```html
<script>
(function () {
try {
var v = localStorage.getItem("mmg-accent");
if (v && v !== "synapse") document.documentElement.setAttribute("data-mmg-accent", v);
} catch (e) {}
})();
</script>
```
## Sémantique vs accent
> **L'accent est un accent, pas une dominante.** La sémantique prime sur la personnalisation.
| Token | Affecté par l'accent ? |
|---|---|
| `--mmg-color-accent-*` | ✅ Oui — c'est son rôle |
| `--mmg-color-success-*` | ❌ Non — toujours vert |
| `--mmg-color-danger-*` | ❌ Non — toujours rouge |
| `--mmg-color-warning-*` | ❌ Non — toujours ambre |
| `--mmg-color-info-*` | ❌ Non — toujours bleu |
| `--mmg-color-bg-*`, `--mmg-color-text-*` | ❌ Non — neutres |
Cas particulier : l'utilisateur peut choisir un accent **rouge**. Il sera distinguable de `danger` car les deux ont des soft/border/strong propres.
@@ -0,0 +1,39 @@
---
title: Mode sombre
description: Activation et personnalisation du dark mode.
---
## Toggle simple
```tsx
import { useTheme } from "@managemate/react";
const { theme, setTheme, toggle } = useTheme();
// theme === "light" | "dark" | "system"
```
## Tokens dark mode
Toutes les surfaces, textes, bordures et états ont leur version dark définie dans `tokens/semantic.css`. Les ombres deviennent **noires + halo blanc subtil** plutôt que noires pures (qui s'évaporent).
```css
[data-mmg-theme="dark"] {
--mmg-color-bg-page: #0B0D14;
--mmg-color-bg-surface: #14171F;
/* ... */
--mmg-shadow-1: 0 1px 3px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.04);
}
```
## Auto-system
Sans `[data-mmg-theme]`, le DS suit `prefers-color-scheme: dark`.
## Forced colors / High Contrast Mode (Windows)
`@media (forced-colors: active)` bascule sur les system colors :
- `Highlight` pour les états sélectionnés
- `Canvas`/`CanvasText` pour les surfaces
Les composants overlays (Tooltip, Dialog, Menu) ont une bordure `1px solid CanvasText` en HCM pour rester lisibles.
+36
View File
@@ -0,0 +1,36 @@
---
title: Presets accent
description: Les 9 couleurs d'accent disponibles dans le DSMMG.
---
| Preset | Hex (light) | Usage suggéré |
|---|---|---|
| `synapse` (défaut) | `#D12B6A` | ManageMate corporate, défaut partout |
| `rose` | `#E11D48` | Variante rose plus vif |
| `blue` | `#2563EB` | Apps banking / fintech / lourd-data |
| `violet` | `#7C3AED` | Forge, créatif, AI |
| `green` | `#0E9F6E` | HRTime, environnemental |
| `amber` | `#D97706` | Orbit, attention positive |
| `red` | `#DC2626` | Sites événementiels — ne pas confondre avec sémantique danger |
| `cyan` | `#0891B2` | SIRH analytics, dashboards |
| `slate` | `#475569` | Neutre haut contraste, brutalist |
## Tests de contraste — chaque preset
Chaque preset est validé contre 6 règles avant inclusion :
1. **Accent vs fond light** ≥ 4.5:1 (texte) ou 3:1 (composant non-texte).
2. **Accent vs fond dark** ≥ 4.5:1 / 3:1 (avec la version dark-tuned).
3. **`-on` vs `accent`** ≥ 4.5:1 (texte sur le bouton).
4. Focus ring distinguable sur tous les fonds (light, dark, raised).
5. Tous les états (hover/active/disabled) restent distinguables.
6. Pas de confusion avec les couleurs sémantiques (`accent === red``danger`).
## Dark mode — adaptation
En `[data-mmg-theme="dark"]`, l'accent est **éclairci et désaturé** pour confort visuel.
Référence : Linear, Stripe, Apple HIG. L'œil supporte mal les couleurs vives sur fond sombre.
Exemple Synapse :
- Light : `#D12B6A` (HSL 335 65% 50%)
- Dark : `#E83A7E` (HSL 335 78% 57%) — plus clair, légèrement plus saturé
+8
View File
@@ -0,0 +1,8 @@
/* Customisation Starlight pour matcher le DSMMG */
:root {
--sl-color-accent: var(--mmg-color-accent);
--sl-color-accent-low: var(--mmg-color-accent-soft);
--sl-color-accent-high: var(--mmg-color-accent-strong);
--sl-font: var(--mmg-font-sans);
--sl-font-mono: var(--mmg-font-mono);
}