Fondations
Mode sombre
الوضع الداكن
Comment ça marche
Un attribut data-theme sur <html>, posé avant la première peinture pour éviter tout flash.
1. Avant peinture
themeInitScript lit la préférence stockée (ou le système) et pose data-theme sur <html> via un <Script strategy="beforeInteractive">.
2. À l'exécution
ThemeProvider synchronise React avec cet attribut et écoute les changements de préférence système.
3. Dans l'UI
ThemeToggle expose un menu clair / sombre / système, propulsé par le hook useTheme.
import Script from "next/script";
import { ThemeProvider, themeInitScript } from "@/dsm/components/theme";
<html lang="fr" suppressHydrationWarning>
<head>
<Script id="dsm-theme-init" strategy="beforeInteractive">{themeInitScript}</Script>
</head>
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>import { ThemeToggle, useTheme } from "@/dsm/components/theme";
// Menu clair / sombre / système, prêt à l'emploi
<ThemeToggle />
// Ou piloter soi-même
const { theme, resolved, setTheme } = useTheme();Le même bloc, deux thèmes
Card, Badge, Alert et Button rendus sans aucune modification de code, dans un conteneur data-theme="light" puis data-theme="dark".
Clair
Acte de naissance
Votre demande a été traitée. Le document est prêt au téléchargement.
Conservez votre référence
Sombre
Acte de naissance
Votre demande a été traitée. Le document est prêt au téléchargement.
Conservez votre référence
Remappage des jetons
Chaque variable change de valeur sous [data-theme="dark"] ; les utilitaires Tailwind (bg-canvas, text-ink…) restent identiques dans le code des composants.
| Jeton | Clair | Sombre |
|---|---|---|
| --dsm-canvas | #FAF7F1 | #121110 |
| --dsm-surface | #FFFFFF | #1A1917 |
| --dsm-surface-inverse | #1C1A17 | #F3EEE6 |
| --dsm-ink | #1C1A17 | #F3EEE6 |
| --dsm-ink-inverse | #FAF7F1 | #1C1A17 |
| --dsm-vert | #0B6B3F | #3FA870 |
| --dsm-rouge | #B5202C | #E4606A |
| --dsm-bleu | #2B3FA8 | #8C9BF2 |
| --dsm-safran | #C4720A | #E9A23B |
| --dsm-primary-fg | #FFFFFF | #0D0C0B |
primary-fg : le cas du texte sur bouton principal
Sur bg-primary, le texte doit rester lisible dans les deux thèmes — sa couleur ne peut donc pas être fixe.
primary-fg vaut blanc en clair et une encre proche du noir en sombre : le vert du bouton s'éclaircit en mode sombre pour rester accessible, et le texte bascule pour préserver le contraste.
Les surfaces inverses basculent aussi
surface-inverse et ink-inverse sont pensées pour rester contrastées face au thème courant : elles s'inversent donc à leur tour en mode sombre.
Bandeau inverse — thème clair
surface-inverse = encre foncée, ink-inverse = toile claire.
Bandeau inverse — thème sombre
Les deux jetons s'échangent : le bandeau reste le contraire du fond ambiant.
La règle : jamais de dark:
Ne jamais écrire de variante dark:
dark: duplique la décision de couleur et finit par diverger. Utilisez toujours l'alias sémantique : il porte déjà les deux valeurs.{/* À éviter */}
<div className="bg-white text-black dark:bg-neutral-900 dark:text-white" />
{/* À faire */}
<div className="bg-surface text-ink" />