Un socle, six voix

« Moderne » est le thème de base. Cinq thèmes prêts à l'emploi — Solaire, Luxe, Créatif, Puissant, Forêt — l'écrasent proprement via data-theme-style,
en clair comme en sombre, sans jamais toucher aux composants. Trois garde-fous vérifient que ça reste vrai : la charte des tokens, la sémantique HTML et le contraste WCAG des 348 paires de couleurs que produisent les thèmes.

🏗️ Architecture en 2 couches

Quatre feuilles pour le socle, puis les thèmes voulus — dans cet ordre précis. Chaque fichier a une seule nature, donc une seule raison de changer (voir ARCHITECTURE-CSS.md) :

<link rel="stylesheet" href="styles/primitives.css">            <!-- valeurs brutes, jamais themées -->
<link rel="stylesheet" href="styles/defaults.css">              <!-- les 6 familles par défaut, ce qu'un thème surcharge -->
<link rel="stylesheet" href="styles/components.css">            <!-- éléments HTML, ne lit QUE des tokens sémantiques -->
<link rel="stylesheet" href="styles/layout.css">                <!-- classes de disposition mécaniques, non themées -->
<link rel="stylesheet" href="styles/themes/theme-solaire.css">  <!-- thèmes prêts à l'emploi, chacun -->
<link rel="stylesheet" href="styles/themes/theme-luxe.css">     <!-- optionnel : ne chargez que ceux -->
<link rel="stylesheet" href="styles/themes/theme-creatif.css">  <!-- dont vous avez réellement besoin -->
<link rel="stylesheet" href="styles/themes/theme-puissant.css"> <!-- en production -->
<link rel="stylesheet" href="styles/themes/theme-foret.css">    <!-- (créé avec le créateur de thème) -->

Le thème actif s'active avec deux attributs indépendants sur <html>. Sans data-theme, le mode suit la préférence système — pour les six thèmes, sans JavaScript : chaque token qui dépend du mode est écrit une seule fois en light-dark(clair, sombre), et data-theme ne fait que figer le color-scheme.

<html>                                               <!-- Moderne · auto : suit la préférence système -->
<html data-theme="light">                            <!-- Moderne · clair -->
<html data-theme="dark">                             <!-- Moderne · sombre -->
<html data-theme-style="solaire">                    <!-- Solaire · auto -->
<html data-theme="light" data-theme-style="solaire"> <!-- Solaire · clair -->
<html data-theme="dark"  data-theme-style="luxe">    <!-- Luxe · sombre -->
<html data-theme="dark"  data-theme-style="creatif"> <!-- Créatif · sombre -->
<html data-theme="light" data-theme-style="puissant"> <!-- Puissant · clair -->
components.css ne contient aucune couleur, aucun espacement, aucune ombre, aucune police en dur — seulement des var(--token-sémantique). Un plugin stylelint vérifie cette règle automatiquement (voir npm run lint:css), pas seulement dans la documentation.

Les 6 familles, séparées et surchargeables indépendamment

Chaque famille peut être surchargée seule — un thème n'est pas obligé de toutes les redéfinir.

FamilleRôleExemples de tokens
Couleurs Surfaces, texte, bordures, actions, statuts --surface-base --action-primary --brand-gradient
Espaces Rythme, paddings de composants --space-card-padding --space-section-gap
Layout principal Largeurs de conteneur, silhouette (rayons) --layout-content-width --layout-radius-card
Ombres Élévation, halos lumineux --shadow-elev-mid --shadow-glow-accent
Animations Vitesse, ressort, amplitude --motion-normal --motion-float-distance
Typographie Police, graisse, interlignage, interlettrage --font-heading --weight-display --leading-body

Les 6 thèmes

ThèmeCouleursFormesOmbresVitesseTitres
ModerneIndigo / SlateCoins modérésSubtilesRapideNeo-Grotesque
SolaireCorail / ArgileTrès arrondiChaudes, marquéesLent, rebondGeometric Humanist
LuxeOr / EncreCoins netsDiscrètesTrès lentDidone
CréatifFuchsia / RaisinPilule partoutColorées, vivesRapide, rebondRounded Sans
PuissantNoir / CramoisiAngles droitsDures, décaléesImmédiateIndustrial
ForêtVert profond / SarcelleCoins modérésTeintées vertPoséeNeo-Grotesque

🎨 Tokens actifs

Ces échantillons lisent les tokens sémantiques — ils changent avec le sélecteur de thème en haut de page.

Couleurs de marque (thémées)

--action-primary --brand-gradient --surface-raised --action-secondary

Statuts — universels, ne changent jamais de thème

✓ Succès ⚠ Alerte ✕ Danger ℹ Info

Typographie — voix du thème actif

--font-headingTitre du thème

--font-bodyCorps de texte du thème actif, pour juger sa lisibilité.

--font-uiLibellé d'interface

--font-codeconst voix = "thème";

Espaces — échelle sémantique

inline-gap

stack-gap

group-gap

card-padding

section-gap

Layout principal — rayons

bouton input carte modale badge

Ombres — élévation sémantique

interactive elevated dialog glow accent

🧱 Composants

Le même HTML, sans aucune modification, sous les six thèmes.

Boutons — <button>



Badges — .badge

Neutral Primary ✓ Success ⚠ Warning ✕ Danger ℹ Info

Formulaires

Champs de formulaire de démonstration

Checkbox, Radio & Switch

Cases à cocher, boutons radio et interrupteur

Range & Color

Curseur et sélecteur de couleur

Progress & Meter

Barres de progression et jauge

Alertes — .alert

ℹ Information par défaut.
✓ Opération réussie.
⚠ Action irréversible.
✕ Erreur critique.

Cartes — .card

MR

Carte Interactive
Survolez-moi !

Glassmorphism

Backdrop-filter blur.

✨ Bordure gradient

Contour animé au survol.

Avatars

S MD LG

Groupe : AB CD EF GH

Skeleton — aria-busy="true"

 

Pagination


La page courante porte aria-current="page" : l'information est dans le HTML, le CSS ne fait que la montrer.

Infobulle & activité


L'infobulle est un complément : une information indispensable doit vivre dans le flux, pas dans un pseudo-élément.

Notifications — .toast

Brouillon enregistré.
✓ Thème exporté.
Échec de l'envoi — réessayez.

En place réelle, dans un .toast-region avec role="status" : l'ajout est annoncé sans voler le focus.

État vide

Aucun article

Vos publications apparaîtront ici dès que vous en aurez écrit une.

Composer un site

Panneau latéral — <dialog data-variant="drawer">

Un <dialog> ouvert par showModal() : le navigateur fournit déjà le piège de focus, la fermeture par Échap et le voile. Seule la géométrie change.

Navigation

Accordéon — <details> / <summary>

Comment fonctionne la surcharge de thème ?

Chaque thème ajoute data-theme-style="nom" sur <html>. Ses sélecteurs ciblent cet attribut avec une spécificité égale ou supérieure à ceux de tokens.css et sont chargés après : ils gagnent la cascade sans !important.

Puis-je ne surcharger que les couleurs ?

Oui. Chacune des 6 familles est indépendante : gardez uniquement la section « Couleurs » d'un fichier de thème et seules les couleurs changeront, le reste (espaces, layout, ombres, animations, typographie) retombera sur « Moderne ».

Comment le garde-fou stylelint m'empêche-t-il de casser ça ?

Le plugin tooling/stylelint-plugin-design-tokens.js interdit d'écrire var(--base-primary-500) ou var(--base-font-didone) (une primitive) directement dans components.css : il faut passer par un token sémantique comme --action-primary ou --font-heading. Il interdit aussi toute couleur littérale (#hex, rgb()…) hors des primitives, et tout sélecteur [data-theme] dans components.css. Lancez npm run lint:css pour le vérifier.

Et si mon thème a besoin de nouvelles couleurs de marque ?

Ajoutez-les en section 0 de votre fichier de thème (ex. --base-solaire-coral-500), comme le fait « Solaire ». Les composants ne les verront jamais directement : ils ne lisent que --action-primary, --brand-gradient, etc.

Citations — <blockquote>

Un design system n'est pas une palette figée, c'est une indirection bien placée.

Architecture des tokens

Cinq thèmes actifs, zéro ligne de components.css modifiée.

Séparateurs — <hr>




Tables — <table>

AttributRôle
data-themeMode clair (light) ou sombre (dark)
data-theme-styleAbsent = « Moderne » · solaire/luxe/creatif/puissant = thème actif

Code

Inline : --action-primary change avec la marque active. Raccourcis : + K

Modale — <dialog>

Confirmer l'action

Le rayon, l'ombre, le rythme et la police de cette modale suivent le thème actif.

Navigation — <nav>

Horizontale :
Breadcrumb :

✨ Animations — data-animate

Les mêmes attributs, mais chaque thème a sa propre vitesse et son propre ressort — de l'immédiat (Puissant) au très lent (Luxe).

float pulse-glow gradient scale-in

📋 Créer son propre thème

<!-- 1. Copiez un thème proche de ce que vous voulez -->
<!-- 2. Remplacez data-theme-style="solaire" par votre nom -->
[data-theme-style="mon-theme"] {
  /* Un seul bloc : light-dark() porte les deux modes. */
  --action-primary: light-dark(var(--ma-marque-600), var(--ma-marque-400));
  /* … uniquement les familles que vous voulez changer … */
}

<!-- 3. Chargez-le après components.css -->
<link rel="stylesheet" href="styles/themes/theme-mon-theme.css">

<!-- 4. Activez-le (sans data-theme : suit la préférence système) -->
<html data-theme-style="mon-theme">

# 5. Vérifiez la charte, les contrastes et le reste
npm test