Fondations

Mode sombre

الوضع الداكن

Le mode sombre n'est pas une feuille de style séparée : c'est le même composant, alimenté par des jetons qui changent de valeur selon l'attribut data-theme. Aucun composant DSM n'écrit de variante dark:.

Comment ça marche

Un attribut data-theme sur <html>, posé avant la première peinture pour éviter tout flash.

  1. 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. 2. À l'exécution

    ThemeProvider synchronise React avec cet attribut et écoute les changements de préférence système.

  3. 3. Dans l'UI

    ThemeToggle expose un menu clair / sombre / système, propulsé par le hook useTheme.

src/app/layout.tsx
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

Dossier validéRéf. 2026-004821

Acte de naissance

Votre demande a été traitée. Le document est prêt au téléchargement.

Conservez votre référence

Elle vous sera demandée pour toute réclamation.

Sombre

Dossier validéRéf. 2026-004821

Acte de naissance

Votre demande a été traitée. Le document est prêt au téléchargement.

Conservez votre référence

Elle vous sera demandée pour toute réclamation.

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.

JetonClairSombre
--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:

{/* À éviter */}
<div className="bg-white text-black dark:bg-neutral-900 dark:text-white" />

{/* À faire */}
<div className="bg-surface text-ink" />