Le thème n'est pas une dépendance que vous configurez. C'est un ensemble de
fichiers que la couche possède, bâti sur [shadcn-vue](https://www.shadcn-vue.com)
et Tailwind 4 — et la raison de cette forme décide de ce que coûte une
surcharge.

Changer quelque chose, c'est [Surcharger le thème](/guides/override-the-theme).
Cette page explique pourquoi les coutures sont là où elles sont.

## Les composants sont copiés, pas importés

shadcn-vue n'est pas une bibliothèque de composants que l'on installe. Son CLI
écrit le code source d'un composant dans votre projet, et à partir de là le
fichier est le vôtre. La couche garde ses primitives dans `app/components/ui/`, et
`components.json` pointe le CLI sur cet alias : en ajouter une tient en une seule
commande.

Deux conséquences en découlent, et elles vont en sens inverse :

- **Vous pouvez tout changer, sans fork.** Un composant que vous voulez différent
  est un fichier que vous modifiez — pas d'amont contre lequel lutter, pas d'API
  de thème dans laquelle chercher une faille.
- **Rien ne se met à jour tout seul.** Un correctif amont sur une primitive vous
  parvient quand vous relancez le CLI pour elle, pas quand une dépendance monte de
  version. La couche assume ce coût pour ses propres primitives ; un composant que
  vous surchargez dans votre projet, vous l'assumez.

Ce compromis est toute la raison du troisième niveau du guide de surcharge : le
plus petit changement qui fait le travail est le bon, car un composant que vous
remplacez est un composant que vous maintenez désormais.

::callout{type="info" title="D'où vient la décision"}
Pourquoi shadcn-vue plutôt qu'un thème de documentation tout fait est consigné
dans l'[ADR 0008](/adr/0008-build-the-theme-on-owned-shadcn-vue-components).
::

## Une couche de jetons, deux feuilles de style

La palette est faite de propriétés personnalisées CSS en `oklch`, définies une
fois sur `:root` et redéfinies sur `.dark`. Chaque composant lit un jeton ; aucun
ne détient une couleur. C'est ce qui rend possible une surcharge d'une ligne — vous
redéfinissez `--primary` dans votre propre feuille de style et toutes les surfaces
qui l'utilisent suivent.

Deux fichiers la portent, et ils ne sont pas interchangeables :

| Fichier                       | Contient                                                                                 |
| :---------------------------- | :---------------------------------------------------------------------------------------- |
| `app/assets/css/duxt.css`     | La palette, l'entrée Tailwind, le préréglage de la couche — le fichier que vous lisez     |
| `app/assets/css/typeset.css`  | Le typeset de shadcn, repris tel quel — le fichier que vous **ne** modifiez **pas**       |

Aucune entrée de registre ne se cache derrière `typeset.css` : le CLI ne peut donc
ni le récupérer ni le mettre à jour. Mettre à jour signifie retélécharger le
fichier, et c'est pourquoi les changements locaux ont leur place dans le
préréglage de `duxt.css` — une modification faite dans `typeset.css` est une
modification que la prochaine mise à jour écarte en silence.

## Le mode sombre est une classe, pas une media query

`@custom-variant dark (&:is(.dark *))` — le thème bascule sur une classe `dark`, et
`@nuxtjs/color-mode` pose exactement cette classe parce que la couche le configure
avec `classSuffix: ''`.

C'est le détail sur lequel on trébuche en surchargeant une couleur. Un jeton
défini uniquement sous `@media (prefers-color-scheme: dark)` n'est jamais lu, et un
jeton défini une seule fois sur `:root` sert dans les deux modes — donc il est faux
dans l'un des deux. Redéfinissez dans les deux blocs, ou acceptez qu'un mode garde
la valeur de la couche.

## La palette s'écarte du défaut de shadcn, délibérément

`--muted-foreground` est ici plus sombre que ne le livre le jeu neutre de shadcn.
Ce jeton porte les descriptions de page, le sommaire et le fil d'Ariane, et à la
valeur de shadcn il mesure en dessous du 4,5:1 exigé par WCAG AA sur les surfaces
où il atterrit réellement.

Aucune vérification passant par un navigateur ne l'attrape : un passage
d'accessibilité sur les pages construites n'a pas de couleur calculée à mesurer. La
couche mesure donc les jetons eux-mêmes, dans `tests/contrast.test.ts`, en
appariant chaque couleur de premier plan avec les fonds sur lesquels elle est
vraiment utilisée. Surchargez un jeton de premier plan et vous reprenez cette
garantie — le test lit le fichier de la couche, pas le vôtre.

## Il faut dire à Tailwind où se trouve la couche

`@source '../../../app'` figure en haut de `duxt.css` et n'est pas décoratif.
Tailwind cherche les noms de classe depuis la **racine de compilation**, c'est-à-dire
le dossier du projet consommateur. La couche vit en dehors, dans `node_modules` :
sans cette ligne, chaque utilitaire employé par un composant de la couche
manquerait au CSS généré — un site rendu sans aucun style.

Le chemin est relatif à la feuille de style, il tient donc partout où le paquet est
installé.

## Ce que cela donne

- Une couleur, un rayon, une police : redéfinissez le jeton dans votre feuille de style.
- Une mise en page qui ne convient pas à votre site : occultez le composant par son nom.
- Une primitive que la couche n'apporte pas : ajoutez-la avec le CLI.

Chaque marche vers le bas coûte plus d'entretien que la précédente. Le
[guide de surcharge](/guides/override-the-theme) parcourt les trois, et
[Donner son identité à votre site](/guides/brand-your-site) traite la part qui
relève de l'identité et non du thème — le nom, la marque et les icônes.