Theming
Wie das Theme gebaut ist — eigene Komponenten, eine Token-Ebene und ein Dark Mode, der über eine Klasse schaltet.
Das Theme ist keine Abhängigkeit, die du konfigurierst. Es ist ein Satz Dateien, die die Ebene besitzt, gebaut auf shadcn-vue und Tailwind 4 — und der Grund für diese Form entscheidet, was dich das Überschreiben kostet.
Etwas ändern ist Das Theme überschreiben. Diese Seite erklärt, warum die Nähte dort sitzen, wo sie sitzen.
Komponenten werden kopiert, nicht importiert
shadcn-vue ist keine Komponentenbibliothek, die du installierst. Ihr CLI schreibt
den Quelltext einer Komponente in dein Projekt, und von da an gehört die Datei
dir. Die Ebene hält ihre Primitive in app/components/ui/, und components.json
zeigt das CLI auf diesen Alias — eine hinzuzufügen ist ein einziger Befehl.
Zwei Folgen ergeben sich, und sie laufen in entgegengesetzte Richtungen:
- Du kannst alles ändern, ohne Fork. Eine Komponente, die anders aussehen soll, ist eine Datei, die du bearbeitest — es gibt kein Upstream, gegen das du ankämpfst, und keine Theme-API, in der du eine Lücke suchst.
- Nichts aktualisiert sich von selbst. Eine Korrektur an einem Primitiv erreicht dich, wenn du das CLI erneut dafür aufrufst, nicht wenn eine Abhängigkeit springt. Die Ebene trägt diese Kosten für ihre eigenen Primitive; eine Komponente, die du in deinem Projekt überschreibst, trägst du.
Dieser Tausch ist der ganze Grund für die dritte Stufe im Überschreib-Leitfaden: die kleinste Änderung, die die Aufgabe erledigt, ist die richtige — denn eine Komponente, die du ersetzt, ist eine Komponente, die du ab jetzt pflegst.
Warum shadcn-vue statt eines fertigen Dokumentations-Themes, steht in ADR 0008.
Eine Token-Ebene, zwei Stylesheets
Die Palette besteht aus CSS-Custom-Properties in oklch, einmal auf :root
definiert und auf .dark neu definiert. Jede Komponente liest ein Token; keine
hält eine Farbe. Genau das macht eine einzeilige Überschreibung möglich — du
definierst --primary in deinem eigenen Stylesheet neu, und jede Fläche, die es
nutzt, zieht mit.
Zwei Dateien tragen das, und sie sind nicht austauschbar:
| Datei | Enthält |
|---|---|
app/assets/css/duxt.css | Palette, Tailwind-Einstieg, das Preset der Ebene — die Datei, die du liest |
app/assets/css/typeset.css | shadcns Typeset, wortgleich übernommen — die Datei, die du nicht bearbeitest |
Hinter typeset.css steht kein Registry-Eintrag, das CLI kann sie also weder
holen noch aktualisieren. Ein Upgrade heißt: Datei erneut herunterladen. Deshalb
gehören lokale Änderungen ins Preset von duxt.css — eine Änderung in
typeset.css ist eine, die das nächste Upgrade stillschweigend verwirft.
Dark Mode ist eine Klasse, keine Media Query
@custom-variant dark (&:is(.dark *)) — das Theme schaltet über eine
dark-Klasse, und @nuxtjs/color-mode setzt genau diese Klasse, weil die Ebene
es mit classSuffix: '' konfiguriert.
Das ist das Detail, über das man beim Überschreiben einer Farbe stolpert. Ein
Token, das nur unter @media (prefers-color-scheme: dark) definiert ist, wird nie
gelesen; ein Token, das einmal auf :root steht, gilt in beiden Modi — und ist
damit in einem von beiden falsch. Definiere in beiden Blöcken neu, oder nimm in
Kauf, dass ein Modus den Wert der Ebene behält.
Die Palette weicht bewusst von shadcns Standard ab
--muted-foreground ist hier dunkler, als der neutrale shadcn-Satz ihn ausliefert.
Dieses Token trägt die Seitenbeschreibungen, das Inhaltsverzeichnis und den
Brotkrumenpfad, und bei shadcns Wert misst es auf den Flächen, auf denen es
tatsächlich landet, unter den 4,5:1, die WCAG AA verlangt.
Keine browserbasierte Prüfung fängt das: ein Accessibility-Lauf über die gebauten
Seiten hat keine berechnete Farbe zu messen. Die Ebene misst deshalb die Tokens
selbst, in tests/contrast.test.ts, und paart jede Vordergrundfarbe mit den
Hintergründen, auf denen sie wirklich verwendet wird. Überschreibst du ein
Vordergrund-Token, übernimmst du diese Zusicherung — der Test liest die Datei der
Ebene, nicht deine.
Tailwind muss erfahren, wo die Ebene liegt
@source '../../../app' steht weit oben in duxt.css und ist keine Zierde.
Tailwind sucht Klassennamen ab der Build-Wurzel, und das ist das Verzeichnis
des konsumierenden Projekts. Die Ebene liegt außerhalb davon, in node_modules —
ohne diese Zeile fehlte also jede von einer Ebenen-Komponente genutzte Utility im
erzeugten CSS: eine Website, die vollkommen ungestylt rendert.
Der Pfad ist relativ zum Stylesheet und gilt daher überall, wo das Paket installiert ist.
Was das für dich heißt
- Eine Farbe, ein Radius, eine Schrift: Token im eigenen Stylesheet neu definieren.
- Ein Layout, das für deine Website falsch ist: Komponente per Namen überschatten.
- Ein Primitiv, das die Ebene nicht mitbringt: mit dem CLI hinzufügen.
Jede Stufe abwärts kostet mehr Pflege als die darüber. Der Überschreib-Leitfaden geht alle drei durch, und Deiner Website eine Marke geben behandelt den Teil, der Identität statt Theme ist — Name, Marke und Icons.