# Thèmes, tokens, Tailwind et mode sombre

> Stylez le planificateur avec les tokens --super-scheduler-*, changez l’accent et toutes ses teintes, suivez votre mode sombre et configurez Tailwind v3 ou v4.

Source: https://superscheduler.org/fr/docs/theming/
Reviewed: 2026-10-07

Importez la feuille de style une seule fois : elle vit dans @layer super-scheduler avec des sélecteurs de spécificité nulle, donc votre CSS hors couche l’emporte sans !important. Changez l’habillage avec les tokens --super-scheduler-* ; les tokens de composant fonctionnent partout, mais la famille d’accent doit être définie sur :root et .dark (pour tout le site, avec la valeur par défaut colorScheme 'inherit') ou sur la racine du contrôle avec un colorScheme explicite. Le mode sombre suit par défaut une classe .dark ou un attribut data-theme sur un ancêtre, et ne suit le système d’exploitation qu’avec colorScheme: 'auto'.

SuperScheduler est entièrement stylé au moyen de propriétés CSS personnalisées, de classes et d’attributs data. Vous pouvez l’accorder à votre produit sans forker la feuille de style et sans `!important`. Ce guide décrit le contrat, les recettes qui atteignent de façon fiable chaque couleur, le mode sombre, les classes par slot, la densité, le mode sans style et Tailwind. L’essentiel s’applique à Pro ; la [dernière section](#lite) traite de Lite.

## Le contrat CSS
Importez la feuille de style une seule fois, à côté du CSS de votre application :

```css
@import 'super-scheduler/styles.css';
```

(Avec un bundler, vous pouvez aussi écrire `import 'super-scheduler/styles.css'` dans un module.) Le fichier est un unique bloc `@layer super-scheduler` de sélecteurs `:where()` de spécificité nulle. Toute règle hors couche de votre part l’emporte, quelle que soit sa spécificité.

| Surface | Sélecteur ou préfixe |
|---|---|
| Racine | `.super-scheduler`, avec `data-color-scheme`, `data-density`, `data-lod` et `data-unstyled` |
| Parties | Classes `.super-scheduler__*` (`__event`, `__event-inner`, `__event-bar`, `__cell`, `__row-header-cell`, `__link`, ...) |
| Marqueurs de parties | `[data-super-scheduler-part="event"]`, `"cell"`, `"event-meta"`, `"now-line"`, `"minimap"`, `"pane"`, ... |
| État | `data-selected`, `data-hovered`, `data-dragging`, `data-conflict`, `data-today`, `data-weekend`, `data-disabled`, `data-expanded`, ... |
| Contenu React | `data-super-scheduler-slot`, `data-super-scheduler-slot-ready`, `data-super-scheduler-fallback` |
| Tokens | `--super-scheduler-*` |

Ne dépendez pas des noms de fichiers des chunks ni des identifiants générés. Les tokens de géométrie comme `--super-scheduler-cell-width`, `-row-height` et `-row-header-width` sont écrits par le moteur : modifiez les tailles par les options (`cellWidth`, `eventHeight`, `rowHeaderWidth`), pas par le CSS.

## Tokens
Il existe trois sortes de tokens, et l’endroit où ils sont déclarés détermine où vous pouvez les surcharger.

- **Les primitives**, déclarées sur `:root` : `--super-scheduler-white`, `neutral-50` à `neutral-950`, `accent-50` à `accent-950`, `danger-400/600`, `warning-400/600`, `success-400/600`, `duration`, `ease`, `ease-spring`.
- **Les tokens sémantiques**, déclarés pour chaque schéma de couleurs (valeurs claires sur `:root` et dans les portées claires, valeurs sombres sur `.dark`, `[data-theme="dark"]` et `[data-color-scheme="dark"]`) :

| Groupe | Tokens (tous préfixés par `--super-scheduler-`) |
|---|---|
| Surfaces et texte | `surface`, `surface-raised`, `text`, `text-muted`, `on-accent` |
| Lignes | `border`, `border-strong`, `grid-line`, `grid-break`, `row-line` |
| Accent | `accent-rgb`, `accent`, `accent-emphasis`, `accent-soft`, `accent-text`, `accent-border` |
| Statut | `danger`, `danger-soft`, `warning`, `warning-soft`, `success` |
| Grisés du calendrier | `today-bg`, `weekend-bg`, `non-business-bg`, `group`, `group-row`, `hatch` |
| Interaction | `hover-row`, `hover-cell`, `selection`, `selection-border`, `focus-ring`, `micro-bar`, `duration-bar` |
| Superpositions et chargement | `overlay`, `overlay-text`, `overlay-muted`, `overlay-subtle`, `overlay-border`, `skeleton-base`, `skeleton-highlight`, `shadow-1` à `shadow-3` |

- **Les tokens de composant**, jamais déclarés : ils sont lus avec une valeur de repli là où ils sont utilisés, si bien que vous pouvez les définir sur n’importe quel ancêtre. Exemples : `--super-scheduler-radius`, `-event-radius`, `-event-padding`, `-event-bg`, `-event-text`, `-event-border`, `-event-bar`, `-link`, `-link-hover`, `-now-line`, `-handle-target`, `-hover-*`, `-minimap-*`, `-pane-splitter`, `-zoom-hud-bg`.

## Recettes d’habillage qui fonctionnent
Comme les tokens sémantiques sont déclarés par schéma de couleurs, et que quelques-uns sont redéclarés sur la racine du contrôle, toutes les surcharges n’atteignent pas toutes les teintes. Ces quatre recettes ont été vérifiées dans le navigateur avec la feuille de style 0.1.0.

### Les tokens de composant, partout
Les tokens de composant fonctionnent sur n’importe quel ancêtre, quel que soit le mode de schéma de couleurs :

```css
.planning {
  --super-scheduler-radius: 8px;
  --super-scheduler-event-radius: 6px;
  --super-scheduler-event-padding: 2px 6px;
  --super-scheduler-link: #8b5cf6;
  --super-scheduler-now-line: #e11d48;
}
```

### Couleurs neutres sur un élément enveloppe
Avec la valeur par défaut `colorScheme: 'inherit'`, la plupart des tokens sémantiques peuvent être surchargés sur un élément enveloppe : surfaces, texte, lignes, grisés et teintes de sélection.

```css
.planning {
  --super-scheduler-surface: #fbfaf7;
  --super-scheduler-border: #e6e1d6;
  --super-scheduler-weekend-bg: rgb(120 100 60 / 0.05);
}
.dark .planning {
  --super-scheduler-surface: #16140f;
  --super-scheduler-border: rgb(255 255 255 / 0.08);
}
```

Deux limites : avec un `colorScheme` explicite (`'light'`, `'dark'` ou `'auto'`), la racine du contrôle déclare elle-même les tokens sémantiques et un élément enveloppe ne les atteint plus (utilisez la dernière recette). Par ailleurs, `accent`, `duration-bar`, `grid-break`, `hatch`, `overlay-text`, `overlay-muted`, `overlay-subtle` et la couleur de la barre de défilement sont toujours déclarés sur la racine.

### Un accent de marque pour tout le site
La famille d’accent est calculée à partir d’un token de canaux, `--super-scheduler-accent-rgb` (trois nombres séparés par des espaces), plus quelques primitives pour les fonds doux et le texte. Déclarez-les hors couche sur `:root` et dans la portée sombre qu’utilise votre site :

```css
:root {
  --super-scheduler-accent-rgb: 10 140 80;
  --super-scheduler-accent-100: #e0f2e9; /* accent-soft: event fills */
  --super-scheduler-accent-200: #c9e6d6; /* border in light mode */
  --super-scheduler-accent-800: #04361f; /* accent-text, accent-emphasis */
}
:root.dark {
  --super-scheduler-accent-rgb: 80 200 140;
  --super-scheduler-accent-950: #0c2a1b; /* accent-soft in dark mode */
  --super-scheduler-accent-100: #d8f5e6; /* accent-text in dark mode */
}
```

La sélection, le jour courant, l’anneau de focus, les teintes de survol et les micro-barres suivent tous, dans les deux schémas. Cette recette nécessite la valeur par défaut `colorScheme: 'inherit'`.

### Un accent de marque pour un seul planificateur
Pour appliquer votre marque à un seul planificateur, ou pour utiliser un `colorScheme` explicite, placez une classe sur la racine du contrôle avec `cssClass` et ciblez-la en même temps que l’attribut de schéma :

```css
.brand[data-color-scheme='light'] {
  --super-scheduler-accent-rgb: 10 140 80;
  --super-scheduler-accent-100: #e0f2e9;
  --super-scheduler-accent-200: #c9e6d6;
  --super-scheduler-accent-800: #04361f;
}
.brand[data-color-scheme='dark'] {
  --super-scheduler-accent-rgb: 80 200 140;
  --super-scheduler-accent-950: #0c2a1b;
  --super-scheduler-accent-100: #d8f5e6;
}
.job--late {
  --super-scheduler-event-bg: var(--super-scheduler-danger-soft);
  --super-scheduler-event-border: var(--super-scheduler-danger);
  --super-scheduler-event-text: var(--super-scheduler-danger);
}
```

```tsx
// src/BrandedPlanner.tsx
import { useMemo } from 'react'
import { SuperSchedulerComponent } from 'super-scheduler'
import type { SchedulerProps, SuperScheduler } from 'super-scheduler'
import 'super-scheduler/styles.css'

type Job = { status: 'planned' | 'late' | 'done' }

// Stable objects: a new classNames or styles object is applied again on every render.
const CLASS_NAMES: SuperScheduler.SchedulerClassNames = {
  event: 'planning-event',
  rowHeaderCell: 'planning-row-header',
}
const STYLES: SuperScheduler.SchedulerStyles = {
  timeHeaderCell: { fontVariantNumeric: 'tabular-nums' },
}

// A class per state; the colors live in CSS, so they follow light and dark mode.
const statusClass: NonNullable<SchedulerProps['onBeforeEventRender']> = (args) => {
  const job = args.data as SuperScheduler.EventRenderData<Job>
  args.data.cssClass = `job job--${job.status}`
}

export function BrandedPlanner(props: {
  theme: 'light' | 'dark'
  resources: SuperScheduler.ResourceData[]
  jobs: SuperScheduler.EventData<Job>[]
}) {
  const events = useMemo(() => props.jobs.slice(), [props.jobs])
  return (
    <SuperSchedulerComponent
      // Extra class on the control root: the brand CSS targets `.brand[data-color-scheme=...]`.
      cssClass="brand"
      // Follows the application's own theme switch.
      colorScheme={props.theme}
      density="compact"
      classNames={CLASS_NAMES}
      styles={STYLES}
      onBeforeEventRender={statusClass}
      startDate="2026-10-01"
      days={31}
      scale="Day"
      resources={props.resources}
      events={events}
    />
  )
}
```
Vous devriez voir une sélection et des fonds d’événements verts en mode clair, leurs équivalents sombres quand `theme` vaut `'dark'`, et les interventions en retard dans les couleurs d’alerte de chaque schéma. Avec `colorScheme: 'auto'`, écrivez les mêmes règles sur `.brand` et sur `.brand` à l’intérieur de `@media (prefers-color-scheme: dark)`.

> **Behavior:**
> Trois surcharges semblent correctes mais ne fonctionnent pas. Définir `--super-scheduler-accent` sur un ancêtre est masqué par la déclaration propre à la racine. Définir `--super-scheduler-accent-rgb` sur un élément enveloppe change l’accent lui-même, mais aucune des teintes qui en sont calculées. Définir des primitives comme `--super-scheduler-accent-100` sur un élément enveloppe ne change rien, car les tokens sémantiques les ont déjà résolues sur `:root`.

## Schéma de couleurs et mode sombre
`colorScheme` est écrit sur la racine sous forme de `data-color-scheme` :

| Valeur | Suit |
|---|---|
| `'inherit'` (par défaut) | L’ancêtre le plus proche portant la classe `dark` ou un attribut `data-theme="dark"` / `data-theme="light"` |
| `'light'`, `'dark'` | Imposé ; l’emporte sur tout ancêtre |
| `'auto'` | Le `prefers-color-scheme` du système d’exploitation |

Seul `'auto'` lit le système d’exploitation. Un site clair sur un système sombre reste clair avec le mode par défaut, ce que veut généralement un produit doté de son propre sélecteur de thème. Le mode sombre de Tailwind basé sur une classe (`<html class="dark">`) fonctionne tel quel avec `'inherit'`.

Les menus, bulles et cartes de survol sont montés dans `document.body`, en dehors du planificateur. Ils portent le schéma et les tokens du planificateur, et lui sont donc assortis.

## Couleurs et états par événement
Les couleurs simples ne demandent aucun CSS : `backColor`, `fontColor`, `borderColor`, `barColor` et `barBackColor` dans les données de l’événement, ou définis dans `onBeforeEventRender`. `SuperScheduler.ColorUtil.contrasting(color)` choisit une couleur de texte lisible.

Pour des couleurs qui doivent suivre le mode sombre, préférez une classe par état et les tokens de composant, comme dans la recette ci-dessus : `cssClass` sur l’événement, puis `--super-scheduler-event-bg`, `-event-text`, `-event-border` et `-event-bar` dans le CSS. Les événements exposent aussi leur état d’interaction sous forme d’attributs : `data-hovered`, `data-dragging` et `data-resizing` sur l’événement en cours de modification, et `data-conflict` avec `conflictHighlight`. Dans la version 0.1.0, les événements sélectionnés nécessitent une classe à vous (voir [sélection d’événements](https://superscheduler.org/fr/docs/trees-columns-selection/#event-selection)). La fine barre de durée utilise `--super-scheduler-duration-bar` globalement ou `--super-scheduler-event-bar` par événement ; `durationBarVisible: false` la supprime.

## classNames et styles
`classNames` et `styles` ajoutent des classes ou des styles en ligne à des parties nommées. Les slots sont `root`, `scroll`, `corner`, `timeHeader`, `timeHeaderCell`, `rowHeader`, `rowHeaderCell`, `treeToggle`, `grid`, `row`, `cell`, `event`, `eventInner`, `eventBar`, `area`, `separator`, `link`, `selection`, `shadow`, `rectangle`, `crosshair`, `dragCard`, `tooltip`, `skeleton`, `empty`, `error` et `message`.

Ils acceptent les utilitaires Tailwind comme vos propres noms de classes. Définissez les deux objets au niveau du module ou mémoïsez-les, et laissez au moteur la position, la taille, le débordement et le z-index : les modifier casse la détection des cibles du pointeur, les en-têtes collants et la virtualisation. `cssClass` est un raccourci pour ajouter une classe à la racine.

## Densité
`density` modifie les tailles par défaut sans toucher à vos options :

| Préréglage | Hauteur d’événement | Hauteur d’en-tête | Également |
|---|---|---|---|
| `'comfortable'` | 35 px | 30 px | Apparence par défaut |
| `'compact'` | 28 px | 26 px | Marge intérieure d’événement `2px 4px`, texte d’événement en 11 px |
| `'dense'` | 20 px | 22 px | Marge intérieure `0 4px`, texte en 10 px, masque `[data-super-scheduler-part="event-meta"]` |

Les tailles du préréglage ne s’appliquent que tant que `eventHeight` et `headerHeight` gardent leurs valeurs par défaut ; des valeurs explicites l’emportent. `control.update({ density: 'dense' })` recalcule la mise en page sans remonter le composant. Les lignes denses sont des cibles difficiles sur écran tactile : sur téléphone, proposez-les comme option plutôt que par défaut.

## Mode sans style
Pour une apparence entièrement personnalisée, activez `unstyled` et n’importez pas la feuille de style. La racine reçoit `data-unstyled`, le moteur continue d’écrire uniquement les styles en ligne structurels (positions, tailles, empilement, en-têtes collants), et la région live des annonces reste visuellement masquée. Tout le reste vous revient, y compris les indicateurs de focus, la sélection, le survol et la prise en charge des couleurs forcées.

## Tailwind
Les tokens sont le contrat ; Tailwind est une façon parmi d’autres de les consommer.

### Tailwind v3
`super-scheduler/tailwind` est un preset v3. Il ajoute des couleurs (`bg-super-scheduler-surface`, `text-super-scheduler-text-muted`, `bg-super-scheduler-accent/20`, `text-super-scheduler-ink/60`, ...), des rayons (`rounded-super-scheduler`, `rounded-super-scheduler-event`), des ombres (`shadow-super-scheduler-1` à `-3`), ainsi que `duration-super-scheduler` / `ease-super-scheduler`.

```ts
// tailwind.config.ts
import superSchedulerPreset from 'super-scheduler/tailwind'

// Tailwind v3. The preset adds colors, radii, shadows and easing utilities that read the
// --super-scheduler-* tokens (bg-super-scheduler-surface, rounded-super-scheduler-event...),
// so they follow the scheduler's light and dark values.
// In a CommonJS config: presets: [require('super-scheduler/tailwind')].
export default {
  content: ['./index.html', './src/**/*.{ts,tsx}'],
  darkMode: 'class',
  presets: [superSchedulerPreset],
}
```
Le preflight de Tailwind v3 est hors couche : il l’emporterait donc sur les bordures de la bibliothèque, qui sont dans une couche. Placez le preflight dans une couche inférieure à celle de la bibliothèque :

```css
@layer tw-base, super-scheduler;

@import 'super-scheduler/styles.css';

@layer tw-base {
  @tailwind base;
}
@tailwind components;
@tailwind utilities;
```

### Tailwind v4
Tailwind v4 n’a pas de presets : associez les tokens dans `@theme inline`, après avoir déclaré l’ordre des couches. Les associations inline lisent la valeur du token la plus proche : les thèmes sombres imbriqués fonctionnent donc, de même que les modificateurs d’opacité comme `bg-super-scheduler-accent/20`.

```css
@layer theme, base, super-scheduler, components, utilities;

@import 'tailwindcss';
@import 'super-scheduler/styles.css';

@custom-variant dark (&:where(.dark, .dark *));

@theme inline {
  --color-super-scheduler-surface: var(--super-scheduler-surface);
  --color-super-scheduler-surface-raised: var(--super-scheduler-surface-raised);
  --color-super-scheduler-text: var(--super-scheduler-text);
  --color-super-scheduler-text-muted: var(--super-scheduler-text-muted);
  --color-super-scheduler-border: var(--super-scheduler-border);
  --color-super-scheduler-border-strong: var(--super-scheduler-border-strong);
  --color-super-scheduler-grid-line: var(--super-scheduler-grid-line);
  --color-super-scheduler-grid-break: var(--super-scheduler-grid-break);
  --color-super-scheduler-row-line: var(--super-scheduler-row-line);
  --color-super-scheduler-accent: var(--super-scheduler-accent);
  --color-super-scheduler-accent-emphasis: var(--super-scheduler-accent-emphasis);
  --color-super-scheduler-accent-soft: var(--super-scheduler-accent-soft);
  --color-super-scheduler-accent-text: var(--super-scheduler-accent-text);
  --color-super-scheduler-accent-border: var(--super-scheduler-accent-border);
  --color-super-scheduler-on-accent: var(--super-scheduler-on-accent);
  --color-super-scheduler-ink: rgb(var(--super-scheduler-ink-rgb));
  --color-super-scheduler-danger: var(--super-scheduler-danger);
  --color-super-scheduler-danger-soft: var(--super-scheduler-danger-soft);
  --color-super-scheduler-warning: var(--super-scheduler-warning);
  --color-super-scheduler-warning-soft: var(--super-scheduler-warning-soft);
  --color-super-scheduler-success: var(--super-scheduler-success);
  --color-super-scheduler-today-bg: var(--super-scheduler-today-bg);
  --color-super-scheduler-weekend-bg: var(--super-scheduler-weekend-bg);
  --color-super-scheduler-non-business-bg: var(--super-scheduler-non-business-bg);
  --color-super-scheduler-group: var(--super-scheduler-group);
  --color-super-scheduler-group-row: var(--super-scheduler-group-row);
  --color-super-scheduler-hover-row: var(--super-scheduler-hover-row);
  --color-super-scheduler-hover-cell: var(--super-scheduler-hover-cell);
  --color-super-scheduler-selection: var(--super-scheduler-selection);
  --color-super-scheduler-selection-border: var(--super-scheduler-selection-border);
  --color-super-scheduler-focus-ring: var(--super-scheduler-focus-ring);
  --color-super-scheduler-micro-bar: var(--super-scheduler-micro-bar);
  --color-super-scheduler-duration-bar: var(--super-scheduler-duration-bar);
  --color-super-scheduler-hatch: var(--super-scheduler-hatch);
  --color-super-scheduler-overlay: var(--super-scheduler-overlay);
  --color-super-scheduler-overlay-text: var(--super-scheduler-overlay-text);
  --color-super-scheduler-overlay-muted: var(--super-scheduler-overlay-muted);
  --color-super-scheduler-overlay-subtle: var(--super-scheduler-overlay-subtle);
  --color-super-scheduler-overlay-border: var(--super-scheduler-overlay-border);
  --color-super-scheduler-skeleton-base: var(--super-scheduler-skeleton-base);
  --color-super-scheduler-skeleton-highlight: var(--super-scheduler-skeleton-highlight);
  --radius-super-scheduler: var(--super-scheduler-radius, 12px);
  --radius-super-scheduler-event: var(--super-scheduler-event-radius, 8px);
  --shadow-super-scheduler-1: var(--super-scheduler-shadow-1);
  --shadow-super-scheduler-2: var(--super-scheduler-shadow-2);
  --shadow-super-scheduler-3: var(--super-scheduler-shadow-3);
  --ease-super-scheduler: var(--super-scheduler-ease);
  --ease-super-scheduler-spring: var(--super-scheduler-ease-spring);
}
```

## Thèmes dans Lite
Lite (`super-scheduler-lite/styles.css`) dispose de six tokens : `--super-scheduler-background`, `-text`, `-border`, `-header`, `-event` et `-focus`. Ils sont déclarés sur l’élément `.super-scheduler-lite` lui-même : définissez-les donc sur cet élément, et non sur un ancêtre :

```css
.bookings .super-scheduler-lite {
  --super-scheduler-event: #dcfce7;
  --super-scheduler-focus: #15803d;
}
.dark .bookings .super-scheduler-lite {
  --super-scheduler-background: #111827;
  --super-scheduler-text: #f3f4f6;
  --super-scheduler-border: #374151;
  --super-scheduler-header: #1f2937;
  --super-scheduler-event: #14532d;
}
```

Lite n’a pas de schéma sombre intégré : c’est à vous de déclarer les valeurs sombres. Sa feuille de style est elle aussi dans une couche, et elle adapte bordures et focus aux couleurs forcées. Par événement, Lite accepte `backColor`, `fontColor` et `cssClass`.

## Ce que possède votre application
- Le contraste de chaque couleur que vous introduisez, en mode clair, en mode sombre et en contraste élevé.
- Le sélecteur de thème lui-même : où placer la classe `dark` ou `data-theme`, ou quel `colorScheme` passer.
- Les styles du contenu personnalisé (HTML des hooks, slots React, cartes de survol) : utilisez les tokens pour qu’il suive le schéma de couleurs.
- La vérification de vos surcharges après chaque mise à jour. Les tokens et les sélecteurs de parties constituent le contrat stable ; l’ordre interne des classes et le balisage entre les parties, non.

## Voir aussi
→ https://superscheduler.org/fr/examples/sports-club-courts/
→ https://superscheduler.org/fr/examples/festival-stages/
→ https://superscheduler.org/fr/examples/hotel-rooms/
- [Clavier, accessibilité et tactile](https://superscheduler.org/fr/docs/keyboard-accessibility-touch/#motion-contrast) pour les animations réduites, le contraste élevé et les couleurs forcées.
- [Slots de rendu React et cartes de survol](https://superscheduler.org/fr/docs/react-render-slots/) pour les tokens des cartes de survol.
