ThemeForge: Ein einfach zu installierendes CSS-Theme-System – von einem KI-Agenten in nur einem Schritt eingerichtet.
- Kategorie
- KI & lokale LLMs
- Veröffentlicht
- 5 Oktober 2026
- Aktualisiert
- 6 Oktober 2026
- Von
- Jacob Lloyd — mit KI-Unterstützung geschrieben, im Nachhinein
- Lesezeit
- 31 Min. Lesezeit
Kurz gesagt: ThemeForge ist ein kostenloses Paket aus CSS-Dateien sowie einem kleinen Skript. Es ermöglicht es jeder Web-Anwendung, einen Themenauswähler zu nutzen – außerdem stehen zehn Farbthemen sowie eine Vielzahl von vorgefertigten Elementen wie Buttons, Feldern, Karten und Dialogen zur Verfügung. Das Paket wurde so konzipiert, dass ein KI-Programmieragent es mit nur einer einzigen Zeile Code in eine Anwendung einfügen kann. Der Agent befolgt dabei die Anweisungen in einer kurzen Datei im Repository – dadurch erhält die Anwendung einen funktionierenden Themenauswähler, ein standardkonformes Design sowie alle notwendigen Design-Elemente zum Weiterentwickeln.
Die meisten Webanwendungen enden damit, dass drei verschiedene Themes an drei unterschiedlichen Stellen definiert werden: ein :root-Block im Haupt-CSS, ein zweiter Block unter @media (prefers-color-scheme: dark) sowie ein dritter Block, den ein Entwickler irgendwo hinzugefügt hat, damit der Theme-Picker funktioniert. Das Ergebnis ist jedes Mal dasselbe: Ein Steuerelement sieht auf der Startseite anders aus als in den Einstellungen – und im Issue-Tracker taucht dann die Frage auf, warum das dunkle Theme den Footer blau färbt. Ich habe ThemeForge entwickelt, um genau solche Probleme zu verhindern. Es besteht aus einem einzigen Ordner, ui-theme/, der die Laufzeitumgebung, eine Basis-Schicht, die Komponentenklassen, die Design-Tokens aller zehn Themes, einen Theme-Picker sowie optionale Adapter für Tailwind und Quasar enthält – außerdem eine kurze Datei AGENTS.md für KI-Programmieragenten. Man legt diesen Ordner einfach in die Anwendung ab, fügt vier Zeilen zum Seitenkopf hinzu – schon hat man einen funktionierenden Theme-Picker sowie ein System-folgendes Standard-Theme. Der Agent, der die Installation vornimmt, erledigt alles mit einem einzigen Befehl; der Rest dieses Artikels richtet sich an alle, die tiefer in die Funktionsweise einsteigen möchten.
Dieser Artikel dient als Übersicht: Was befindet sich eigentlich im Ordner? Welche zehn Themes gibt es und wofür sind sie gedacht? Wie sieht es mit dem Kontrast aus? Außerdem werden die Design-Tokens sowie Komponentenklassen als Nachschlagewerk bereitgestellt. Der zweite Teil dient bewusst als schnell lesbare Referenz – alle Tokens, alle Komponenten sowie alle öffentlichen Methoden sind dort aufgeführt, sodass ein KI-Agent (oder Sie selbst in Zukunft) sie wortgetreu übernehmen kann.
Kurz gesagt:
- Herunterladen: github.com/LaserLloyd/ThemeForge – MIT-Lizenz, kostenlos; im Download-Bereich unten gibt es auch ein ZIP-Archiv mit dem Quellcode.
- Was ist das? Ein einziger Ordner,
ui-theme/, den man in jede Webanwendung einbinden kann. Er stellt zehn Farbthemes, einen Theme-Picker, rund 250 Design-Tokens, eine Basis-Schicht für Elemente, Standards für Texte sowie eine vollständige Sammlung von Komponentenklassen bereit – darunter Buttons, Eingabefelder, Schalter, Karten, Dialoge, Toasts und Tabellen. Alles basiert auf reinem CSS sowie einem kleinen Skript. Es gibt keinen Build-Schritt, kein Node.js, keine weiteren Abhängigkeiten. - Einzeilige Installation (aus dem README übernommen):
python3 -c "import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())" - Reihenfolge im Seitenkopf (wichtig!): Zuerst
ui-theme.jseinbinden (klassisch, blockierend – niemalsdeferodermodule), danachui-theme-base.cssundui-components.css; anschließend das eigene CSS der Anwendung sowie zuletztui-theme.css, damit die Theme-Tokens Vorrang haben. - Theme-Picker: Es genügt ein einziges Element:
<select class="ui-select" data-ui-theme-picker aria-label="Theme"></select>. Dieser füllt sich selbstständig und bleibt zwischen Tabs synchronisiert. - Die zehn Themes: Sechs Kern-Themes (Purple, Midnight Gold, Glacier, Forest, Paper, Daylight) sowie vier optionale Varianten (Electric Yellow, LaserLloyd, LaserLloyd Light, Night Red). Alle Themes bestehen die Kontrastprüfung ohne Fehler.
- Kontrast: Haupttext hat ein Verhältnis von 7:1, sekundärer Text 6:1; alle Textebenen auf allen Oberflächen mindestens 4,5:1. Kanten von Steuerelementen sowie Ein-/Aus-Zustände erreichen 3:1 – erkennbar an Form und Füllung, nicht nur an Farbe.
- Für KI-Agenten konzipiert: AGENTS.md enthält die Installationsanweisungen in Form von Text – ein beliebiger Agent kann sie nutzen, um den Theme-Picker in einem Schritt zu aktivieren. Die CI des Repos (GitHub Actions, drei Jobs) prüft das Projekt: Ein Klon, eine Kontrastprüfung,
node --checkfür alle JS-Dateien sowie ein Testlauf des Runtimes mit headless Chrome.
Wo man es bekommt
Es gibt ein einziges Repository unter MIT-Lizenz: github.com/LaserLloyd/ThemeForge. Die Installationsanleitung findet sich in AGENTS.md, das Ergebnis der Kontrastprüfung in contrast report. Möchten Sie lieber ein ZIP-Archiv? Im Download-Bereich am Ende dieser Seite finden Sie den kompletten Quellcode; außerdem ist er auch auf der Downloads-Seite verfügbar. Falls kein Python installiert ist, nennt das README auch die Varianten git clone –depth 1, npx degit sowie eine jsDelivr-<script>-URL, die auf @v1.0.0 verweist – nützlich für Prototypen.
Was am Ende dabei herauskommt
Der Nutzer kann sein bevorzugtes Theme problemlos auswählen: Es gibt einen Header mit einem Theme-Picker, der alle verfügbaren Themes kennt; ein dunkles und ein helles Standard-Theme, die sich automatisch an die Systemeinstellungen anpassen. Im Quellcode der Anwendung genügt eine einzige CSS-Zeile: background: var(–surface-2) statt #1d1d39. Wählt man ein Theme aus und lädt die Seite neu, gibt es keinen Flackern – das Runtimeskript läuft synchron im <head>, liest die eigenen data-*-Einstellungen aus dem Tag und setzt das Theme noch vor dem ersten Zeichnen. Öffnet man den Theme-Picker in zwei Tabs und ändert das Theme in einem, passt sich der andere automatisch an (dank eines storage-Event-Listeners). Wählt man beim Drucken ein dunkles oder OLED-Theme aus, schaltet die Laufzeitumgebung vorübergehend auf das helle Pendant um – oder versteckt je nach Einstellung in data-print-theme die Navigation, sodass das gedruckte Blatt gut lesbar ist; bei einem hellen Theme bleibt alles wie gewohnt.
ui-app, ui-card, ui-btn, ui-switch sowie den --surface-* / --text-* / --accent-Tokens. Der Theme-Picker besteht aus einem einzigen <select data-ui-theme-picker> – die Laufzeitumgebung füllt ihn automatisch und sorgt für Synchronisation.Die obige Abbildung stellt die interne Demo dar – kein Screenshot von einer separaten Datei. Das vollständige Exemplar mit allen Komponenten in jedem Theme findet sich im Repository unter specimen/index.html (aufrufbar via python3 -m http.server und anschließend /specimen/).
Wie alles zusammenhängt
Die Laufzeitumgebung besteht aus einem kleinen Skript, ui-theme.js (ca. 23 KB, 575 Zeilen), das nacheinander drei Aufgaben erledigt. Zuerst liest es die eigenen data-*-Attribute aus dem <script>-Tag, in dem es enthalten ist – so bleiben die Einstellungen mit der Datei verbunden. Anschließend prüft es localStorage sowie die Systemeinstellung „helles/dunkles Theme“ und schreibt das gewählte Theme in <html data-palette> sowie den aktuellen Modus in <html data-theme> (z. B. amoled, dark oder light) – und zwar noch vor dem ersten Zeichnen. Danach durchsucht es das Dokument nach Elementen vom Typ <select data-ui-theme-picker>, füllt diese mit der Liste der verfügbaren Themes auf (und reagiert auch auf später von Frameworks erzeugte Instanzen). Schließlich stellt es window.UITheme bereit; sobald ui-components.js geladen ist, auch window.UIComponents. Zudem registriert es einen storage-Event-Listener, sodass beide Tabs synchron bleiben. Das CSS ist übersichtlich strukturiert: ui-theme-base.css legt die Standards für Texte, Links, Fokusringe, Scrollbalken sowie reduzierte Bewegung fest; ui-components.css definiert Buttons, Eingabefelder, Schalter, Karten, Dialoge, Toasts und Tabellen. Die einzige Datei, die sich zwischen den Themes ändert, ist ui-theme.css: Darin werden alle Tokens – Farben, Typografie, Abstände, Rundungen, Schatten, Animationen – für alle zehn Themes unter einem [data-palette=”…”]-Selektor definiert. Für das „Purple“-Theme genügt :root, also die Abwesenheit von data-palette. Das Runtimeskript wählt das Theme aus; das CSS stellt es dann grafisch dar.
Die Übernahme des System-Designs ist es, was viele überrascht: data-default=”auto” liest bei jedem Seitenaufruf prefers-color-scheme aus; die Laufzeit kombiniert dies mit der vom Nutzer gespeicherten Auswahl (oder mit data-default-dark bzw. data-default-light) zur Theme-Auswahl. Ändert man das System-Design und aktualisiert die Seite, passt sich diese an. Wählt man ein Theme explizit aus dem Auswahlfeld, bleibt dieses so lange aktiv, bis der Nutzer es löscht (oder UITheme.reset() aufruft). Zudem bindet die Laufzeit ein storage-Event ein, sodass zwei geöffnete Tabs derselben App ohne Serverkontakt synchron bleiben.
Installation
Die Datei AGENTS.md im Repository enthält die ausführliche Anleitung; die Kurzversion besteht aus einer einzigen Befehlszeile sowie vier Head-Tags. Vom Wurzelverzeichnis der App aus:
python3 -c "import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())"
Damit wird der Installer heruntergeladen, welcher die neueste Version holt, jede Datei mit der SHA-256-Liste in files.json vergleicht und den Ordner anlegt. Unter Windows nutzt man python bzw. py statt python3; die Zeile funktioniert in PowerShell, cmd und Bash gleichermaßen. Die vier Zeilen im <head> jedes Dokuments:
<script src="/static/ui-theme/ui-theme.js"
data-themes="purple,midnight-gold,glacier,forest,paper,daylight"
data-default="auto" data-default-dark="midnight-gold" data-default-light="daylight"
data-storage-key="myapp.theme"></script>
<link rel="stylesheet" href="/static/ui-theme/ui-theme-base.css">
<link rel="stylesheet" href="/static/ui-theme/ui-components.css">
<!-- Ihre Stylesheets -->
<link rel="stylesheet" href="/static/ui-theme/ui-theme.css">
Drei Regeln, jede aus gutem Grund. Das Skript ui-theme.js ist klassisch und blockierend – niemals type=”module”, defer oder async –, weil es seine Einstellungen aus dem eigenen Tag liest (document.currentScript, was für Modulskripte null ist) und das Theme vor dem ersten Rendern festlegt. Die Basis- sowie Komponenten-CSS-Dateien laden vor der App-CSS, sodass die eigenen Regeln der App bei gleicher Spezifität Vorrang haben. ui-theme.css lädt zuletzt, wodurch alte App-Variablen kein Theme-Token überschreiben können. Der Auswahlfeld-Code besteht aus einer einzigen Zeile: <select class=”ui-select” data-ui-theme-picker aria-label=”Theme”></select>. Aus Skript heraus: UITheme.set(‘glacier’), UITheme.current(), UITheme.onChange(fn). Insgesamt dauert die Installation laut Einleitung von AGENTS.md etwa fünf Minuten.
Der Agent, der dies in einem Schritt auf einer echten App umsetzte, sah so aus: Der Mensch bat einen KI-Programmieragenten, der App ein Dunkelmodus sowie ein Theme-Auswahlfeld zu verpassen. Der Agent las AGENTS.md, führte die eine Zeile in static/ui-theme/ aus, kopierte die vier Head-Tags in die Basisvorlage, ersetzte zwei Farbangaben durch var(–surface-2) bzw. var(–text-secondary) und platzierte das Auswahlfeld im Header. Sechs Diff-Zeilen in der App – keine neuen Abhängigkeiten. Der Kontrast-Check deckt alle Kombinationen ab, die die Komponenten nutzen; die Laufzeit folgt dem System-Design automatisch. Ein zukünftiger Commit, der eine Farbe hartkodiert, ist das einzige, was der Lint-Prüfer zu finden hätte.
Die Themes
Die ersten sechs sind die Standardauswahl, die jede App anbietet; die vier optionalen Themes erscheinen nur, wenn eine App sie aufführt. Jedes Theme besteht einen Kontrast-Check (docs/contrast-report.md): Haupttext hat ein Verhältnis von 7:1, sekundärer Text 6:1 auf allen Oberflächen; alle weiteren Textebenen mindestens 4,5:1. Kanten sowie Ein-/Aus-Zustände erreichen 3:1; in jedem Theme erkennt man sie auch über Form statt Farbe. Die vollständige Liste:
| Theme | Gruppe | Grundfarbe | Beschreibung |
|---|---|---|---|
| Purple | Standard | dunkel | Violetter Akzent und sanftes Lavendel auf dunklem Indigo; das Basis-Theme: seine Werte sind die :root-Standards. |
| Midnight Gold | Standard | OLED | Warmes Gold auf reinem Schwarz – ideal für OLED-Bildschirme. |
| Glacier | Standard | OLED | Eisfarbenes Blau und ein Signature-Farbton auf Schwarz; dazu ein tiefes Türkis als Akzent. |
| Forest | Standard | OLED | Helles Smaragdgrün sowie braune Nuancen auf Schwarz. |
| Paper | Standard | hell | Warmes Pergament mit braunem Text, einer Serifenschrift für Prosa und einem roten Akzent. |
| Daylight | Standard | hell | Sauberes Weiß mit blauem Akzent. |
| Electric Yellow | Optional | dunkel | Säuregelb auf grauem Grund; mit engen Rundungen und klaren Linien. |
| LaserLloyd | Optional | dunkel | Laserblau auf fast schwarzem Grau – vom Autor selbst entworfen; passt zu LaserLloyd Light. |
| LaserLloyd Light | Optional | hell | Das helle Pendant zu LaserLloyd. |
| Night Red | Optional | OLED | Ein „Nachttheme“ mit geringer Blaulichtbelastung: rotes Textelement auf Schwarz, keine Blauanteile in irgendeinem Farbwert. |
Drei der vier optionalen Themes sind bewusst auffällig. Electric Yellow nutze ich beim CSS-Review bei Dunkelheit, um die Seite lauter als meinen Editor zu gestalten; LaserLloyd passt zum Blau-Grau-Look dieser Seite und sorgt für Konsistenz zwischen ihr und der App. Night Red ist ein eigenständiges „Nachtprofil“, das der Kontrast-Check gegen einen erweiterten Satz von 171 Zeilen prüft (147 Standardzeilen plus zusätzliche für schwaches Licht); dabei enthält jedes Token des Paletten-Designs keinen Blauanteil (docs/contrast-report.md „Zero-blue audit“; README.md §Night Red; docs/THEMES.md §Night Red).
Fallstricke
-
Ein hardcodierter Farbwert in Ihrem CSS ist das Problem – nicht das Theme. Die Überprüfung prüft lediglich Token; ein
color: #fffim App-Code bleibt in jedem Theme weiß.tools/lint_colors.py(im Repository) sowie die Suche in AGENTS.md §8 erkennen das; der Lint in der CI führt diesen Schritt jedoch nicht aus – daher müssen Sie ihn lokal ausführen, bevor Sie mergen. -
ui-theme.jsmuss als erstes im<head>stehen – klassisch, nicht mitdeferodermodule. Ein Modulskript besitzt keindocument.currentScript; die Laufzeit liest ihre eigenendata-*-Attribute aus dem Tag. Das Symptom: kurzzeitig wird das falsche Theme angezeigt, danach das richtige. -
ui-theme.cssmuss nach dem CSS der App geladen werden – nicht davor. Die Reihenfolge lautet: Basis, Komponenten, App, Token. Eine App-Regel gleicher Spezifität, die nach den Token geladen wird, verliert den Wettbewerb. -
data-themesbestimmt, was der Auswähler anzeigt. Ein gespeichertes Theme, dessen Slug nicht indata-themessteht, wird beim nächsten Laden ignoriert (die Laufzeit greift auf das Standard-Theme zurück). Wenn Sie ein Theme entfernen, fügen Sie bitte einmaldata-legacy-keysowiedata-legacy-maphinzu – dadurch wird der gespeicherte Wert migriert. -
Tailwinds
rounded-mdundfont-sansändern sich nach der Installation. Das ist gewollt: Das Theme definiert die Token–radius-bzw.–font-; deren Werte haben Vorrang. Leisten Sie dagegen keinen Widerstand. -
Next.js Hydration-Warnung. Fügen Sie
suppressHydrationWarningzu<html>hinzu und deaktivieren Sie dieno-sync-scripts-Lint-Regel für den Head-Bereich: Die Laufzeit setzt Attribute auf<html>noch vor der React-Hydration. -
Ein weiteres Bibliothek liest
data-themeaus<html>(z. B. daisyUI, Pico). Die Laufzeit schreibt dortdata-theme=”amoled|dark|light”; prüfen Sie, ob die Bibliothek darauf reagiert. Falls ja, verwenden Sie überdata-mirror-attrein anderes Attribut. -
Bearbeiten Sie nichts innerhalb von
ui-theme/. Der Ordner wird bei Updates überschrieben; der Lint erkennt manuelle Änderungen, und die Installation verweigert das Überschreiben editierter Dateien. Verschieben Sie Änderungen stattdessen in das eigene CSS der App. -
Die in den Stacks genannten Schriftarten werden nicht mitgeliefert. Jeder Stack greift auf Systemschriften zurück; falls Sie Inter, JetBrains Mono, Space Grotesk oder Archivo nutzen möchten, laden Sie diese selbst nach (die Integrations-Dokumentation enthält ein kopierbares
<link>). -
prefers-contrast: moreerhöht die Linienstärke sowie die Sichtbarkeit von sehr hellen Texten. Dafür ist kein Theme-Flag nötig; die Laufzeit reagiert darauf, und das CSS passt sich an. Die Token-Gruppehigh-contraststellt die ältere Variante für denselben Effekt dar.
Wo mich das zurücklässt
Was ich wollte, war eine Möglichkeit, jedem von mir erstellten App ein echtes Theme-System zu verleihen – ohne jedes Mal eins von Grund auf neu schreiben zu müssen. ThemeForge ist die Version davon, die ich gerne beibehalten möchte. Die Ordner, die ich in die Apps einfüge, heißen nun ui-theme/ sowie der Name der jeweiligen App; die vier Head-Block-Tags sowie der Picker sind in jedem Framework gleich. Der Installations-Agent liest dabei die Datei AGENTS.md – nicht eine Slack-Nachricht. Die Kontrastprüfung, die Tests im Headless-Chrome-Modus sowie node –check auf jeder ausgelieferten JS-Datei geben mir das Vertrauen, weiterzumachen. Die Version ist 1.0.0 – schließlich sind Tokens die öffentliche API, und eine Umbenennung von Tokens zählt als Major-Version-Update. Ein Release entspricht einem Git-Tag; der Ordner VERSION stimmt damit überein, und die JSON-Dateien werden mit derselben Prüfsummenliste signiert, gegen die update.py prüft. Die CI des Repos ist unter Linux, Windows sowie Python 3.9 erfolgreich – dieselben Checks funktionieren auch bei einem frischen Klon auf diesem Rechner.
Referenz (für KI-Agenten)
Der Rest dieses Artikels dient als Referenzkarte, die ein Coding-Agent (oder mein zukünftiges Ich) wortgetreu übernehmen kann. Der obige erste Teil besteht aus Fließtext; der zweite Teil ist strukturiert, leicht lesbar und speziell dafür konzipiert, von einem Tool verarbeitet zu werden. Nachfolgend finden Sie jedes Token, jede Komponentenklasse, jede öffentliche Methode in window.UITheme sowie window.UIComponents, jedes Theme, jeden Einstellungsparameter im Script-Tag, jeden Adapter, den vollständigen Installationspfad, die Kontrastvorgaben sowie den Versionsblock.
Dateimanifest
Das Repository enthält zwei wichtige „Baumstrukturen“: das Plug-and-Play-Bundle, das die App kopiert, sowie das Design und die Werkzeuge, mit denen dieses erstellt wird. Der Artikel befasst sich mit dem Bundle.
Drop-in-Bundle – was die App kopiert (ui-theme/):
| Datei | Größe | Zeilen | Beschreibung |
|---|---|---|---|
ui-theme.js |
23.515 B | 575 | Laufzeit: wendet das gespeicherte Theme vor dem ersten Rendern an, folgt der Systemeinstellung „Hell/Dunkel“ mittels data-default="auto", füllt Auswahlfelder aus, synchronisiert Tabs und stellt window.UITheme bereit |
ui-theme-base.css |
13.255 B | — | Standardeinstellungen für Elemente: Text, Links, Überschriften, Code, Fokus-Ring, Scrollbars, reduzierte Bewegung, Textebenen, .ui-markdown, Farben für Highlight.js |
ui-components.css |
51.344 B | — | Komponenten: Buttons, Eingabefelder, Checkboxen, Radio-Buttons, Schalter, Karten, Badges, Hinweiskästen, Tabs, segmentierte Steuerelemente, Tabellen, Dialoge, Menüs, Tooltips, Benachrichtigungen, Fortschrittsanzeigen, Codeblöcke sowie eine App-Struktur |
ui-theme.css |
86.389 B (21.197 B nach GZIP-Komprimierung) | — | Alle zehn Theme-Token – insgesamt ca. 20 KB nach GZIP-Komprimierung |
ui-components.js |
5.441 B | 135 | Optional: themenbezogene Versionen von confirm(), alert(), prompt() und toast() |
ui-theme.d.ts |
2.841 B | — | TypeScript-Deklarationen für window.UITheme und window.UIComponents |
update.py |
16.081 B | — | Installiert und aktualisiert den Ordner; prüft jedes File auf Basis des SHA-256-Hashes |
themes.json |
4.089 B | — | Liste der verfügbaren Themes (Name, Familie, Grundfarbe, Farbpalette, Schriftarten) |
files.json |
1.401 B | — | Liste der Prüfsummen, die von update.py überprüft werden |
VERSION |
30 B | — | Versionsnummer des Ordners (ThemeForge 1.0.0 3db64d9f574f) |
README.md |
6.342 B | — | Anleitungen zur Nutzung des Pakets |
adapters/quasar.css |
24.997 B | — | Zuordnung für NiceGUI/Quasar |
adapters/quasar.js |
1.468 B | 40 | JS-Brücke zwischen NiceGUI und Quasar |
adapters/tailwind.css |
4.399 B | — | Zuordnung für Tailwind CSS v4 mittels @theme inline |
adapters/tailwind-v3.preset.js |
2.915 B | 54 | Preset für Tailwind CSS v3 |
Das Design und die Werkzeuge, die das Bundle erstellen (werden nicht in die App kopiert):
| Datei | Größe | Beschreibung |
|---|---|---|
README.md |
6.592 B | README des Repos |
AGENTS.md |
19.063 B | Installationsanleitung für KI-Agenten in Textform |
CHANGELOG.md |
4.425 B | Versionshistorie (1.0.0 ist die erste Veröffentlichung) |
CLAUDE.md |
1.498 B | Konventionen für Claude im Repo |
CONTRIBUTING.md |
4.476 B | Anleitung zur Mitarbeit an den Themes |
LICENSE |
1.067 B | MIT-Lizenz; Copyright © 2026. Im Originaldokument wird der Autor mit seinem persönlichen Namen genannt; die auf der Website verwendete Form ist die offizielle Bezeichnung. Der Inhalt der Lizenzdatei entspricht dem Original-Lizenztext. Wird nicht im Download-Zip-Archiv enthalten, da die Identität des Autors als potenziell unzulässige Offenlegung angesehen wird. |
docs/TOKENS.md |
15.391 B | Alle Tokens, gruppiert nach Kategorien |
docs/COMPONENTS.md |
13.889 B | Alle Komponentenklassen samt zugehörigem Markup |
docs/THEMES.md |
8.081 B | Die verfügbaren Themes, Designhinweise sowie Anleitung zum Hinzufügen neuer Themes |
docs/INTEGRATIONS.md |
10.604 B | Installationsschritte für verschiedene Frameworks |
docs/TEXT.md |
5.465 B | Textformate sowie die Markdown-Formatierung |
docs/UPDATING.md |
4.134 B | Updates, Caching-Mechanismen sowie die Bedeutung der Prüfsummen |
docs/contrast-report.md |
124.372 B | Kontrast-Audit: 10 Themes × jeweils 147–171 Zeilen |
docs/theme-template.css |
9.854 B | Vorlage für neue Themes, verwendet von tools/sync_theme.py |
tokens/<theme>.json |
ca. 57 KB pro Datei | Aufgelöste Tokens jedes Themes im W3C DTCG JSON-Format |
examples/static-html/ |
3.731 B index | Beispiel mit reinem HTML/CSS/JS |
examples/fastapi-jinja/ |
2.172 B app.py | Beispiel für die Nutzung von FastAPI und Jinja |
specimen/index.html |
17.721 B | Alle Komponenten aller Themes – lokal abrufbar |
tools/check_contrast.py |
43.171 B | Skript zum Durchführen des Kontrast-Audits (wird im CI-Prozess ausgeführt) |
tools/lint_colors.py |
22.711 B | Prüft Farbangaben in der CSS-Datei auf Korrektheit |
tools/sync_theme.py |
41.671 B | Erstellt ui-theme.css, tokens/*.json sowie docs/contrast-report.md aus den Quelldateien in src/css/*.css |
tools/update.py |
16.081 B | Installations- und Verifizierungsskript (entspricht ui-theme/update.py) |
tools/screenshots.py |
3.273 B | Erzeugt Vorschau-Bilder der Themes für docs/images/ |
tests/test_tools.py |
17.606 B | Python-Unit-Tests (32 Tests in diesem Klon; 1 Test wird übersprungen) |
tests/run_browser_tests.py |
3.570 B | Headless-Chrome-Tests des Runtimesystems |
tests/runtime.html |
24.930 B | Testumgebung für Browser-Tests |
.github/workflows/ci.yml |
— | CI-Konfiguration: Kontrastprüfung, node --check, Unit-Tests, Browser-Tests sowie Prüfung auf korrekte Zeilenumbrüche unter Linux, Windows und Python 3.9 |
Die CI des Repos läuft in drei Jobs: „checks“ auf Ubuntu mit Python 3.12, „tools-on-windows“ auf Windows mit Python 3.11 sowie „updater-on-oldest-python“ auf Ubuntu mit Python 3.9. Das lokale Clone besteht den Test „node –check“ für jede ausgelieferte JS-Datei; das Kontrast-Tool reproduziert alle zehn Zeilen des Audits. Zudem bestehen alle Unit-Tests („32 erfolgreich, 1 übersprungen in 1,212 Sekunden“ unter Linux mit Python 3.14 am 05.10.2026).
Design-Tokens (Gruppen, Rolle, Beispielwert)
Jedes Theme löst jedes Token auf. Die unten angegebenen Werte stammen von Purple (dem :root-Basis-Theme); die übrigen Themes haben ihre eigenen aufgelösten Werte in tokens/<theme>.json (DTCG JSON). Verwenden Sie ein Token mittels var(--name). Deklarieren Sie ein Token niemals erneut im App-CSS – vergeben Sie den Variablen der App ein Präfix (--myapp-sidebar-w) oder erstellen Sie einen Alias für das Token (--myapp-brand: var(--accent)). Quelle: docs/TOKENS.md.
| Gruppe | Token | Rolle | Beispiel (Lila) |
|---|---|---|---|
| Oberflächen | --surface-void |
dunkler als die Seite (Vollbild) | #08080f |
| Oberflächen | --surface-0 |
die Seite selbst | #0e0e1b |
| Oberflächen | --surface-1 |
Navigationsleiste | #14142a |
| Oberflächen | --surface-2 |
Karten/Elemente | #1d1d39 |
| Oberflächen | --surface-3 |
Hover-Zustand | #232342 |
| Oberflächen | --surface-4 |
Aktiver Zustand | #262648 |
| Oberflächen | --surface-sunken |
Einliegende Bereiche | #0a0a14 |
| Oberflächen | --surface-overlay |
Menüs, Popovers | #1d1d39 |
| Oberflächen | --glass-1/2/3 |
Transparente Scheiben | rgba(29,29,57,.72/.84/.92) |
| Oberflächen | --glass-highlight |
Glanzeffekt für Glas | rgba(255,255,255,.055) |
| Oberflächen | --code-bg |
Hintergrund für Code | #0b0b16 |
| Text | --text-primary |
Haupttext | #e8e8f0 |
| Text | --text-secondary |
Beschriftungen, Beschreibungen | #a0a0bd |
| Text | --text-tertiary |
Hinweise, Zeitstempel | #8d8db0 |
| Text | --text-disabled |
Deaktivierte Steuerelemente | #717195 |
| Text | --text-inverse |
Text auf hellem Hintergrund | #0e0e1b |
| Text | --text-link / --text-link-hover |
Links sowie akzentuierter Text | #a78bfa / #c4b5fd |
| Text | --on-accent / --on-danger / --on-success / --on-warning / --on-media / --on-media-muted |
Beschriftung auf farbigem Hintergrund | #ffffff / #2a0808 usw. |
| Akzent | --accent / --accent-hover / --accent-pressed |
Markenakzent, Hauptaktionen | #7c3aed / #8250f0 / #6d28d9 |
| Akzent | --accent-subtle / --accent-muted / --accent-glow |
Abgetönter Hintergrund, sanfter Effekt | rgba(124,58,237,.16/.26/.35) |
| Akzent | --accent-rgb |
Für JavaScript: rgba(var(--accent-rgb), .2) |
124,58,237 |
| Akzent | --accent-2 / --accent-2-subtle |
Sekundärakzent | #5eead4 |
| Aktionen | --cta / --cta-hover / --cta-pressed / --on-cta |
Knöpfe für Hauptaktionen | #7c3aed / #8250f0 / #6d28d9 / #ffffff |
| Aktionen | --cta-shadow / --cta-shadow-hover |
Schatteneffekte für solche Knöpfe | 0 6px 20px rgba(124,58,237,.28) / .38 |
| Aktionen | --highlight / --highlight-subtle / --on-highlight |
Markierungen, Farbe von Hinweisen | #fcd34d / rgba(252,211,77,.12) / #251a00 |
| Linien | --border-subtle / --border / --border-strong |
Ränder von Formelementen; --border-strong hat ein Verhältnis von 3:1 |
#21213b / #292945 / #6f6f9c |
| Linien | --divider |
Dünne Linien | #21213b |
| Linien | --focus-ring / --focus-ring-width / --focus-ring-offset |
Fokusring | #a78bfa / 2px / 2px |
| Linien | --glass-stroke / --glass-stroke-strong |
Ränder für Glasoberflächen | rgba(255,255,255,.08/.16) |
| Steuerelemente | --selected / --on-selected |
Aktiv/ausgewählt | je nach Theme |
| Steuerelemente | --unselected-border / --unselected-fg |
Deaktivierter Zustand; Verhältnis 3:1 zu jedem Hintergrund | je nach Theme |
| Status | --success / --warning / --danger / --info |
Punkte, Balken, Füllungen | je nach Theme |
| Status | --success-text / --warning-text / --danger-text / --info-text |
Textfarben zu den jeweiligen Status | je nach Theme |
| Status | --success-subtle / --warning-subtle / --danger-subtle / --info-subtle |
Abgetönte Hintergründe | je nach Theme |
| Status | --success-border / --warning-border / --danger-border / --info-border |
Ränder zu den Status | je nach Theme |
| Status | --idle / --idle-text / --idle-subtle / --idle-border / --idle-hover |
Neutraler Zustand | je nach Theme |
| Status | --live / --live-text / --live-subtle / --live-border / --live-hover |
„Aktiv“-Indikator | je nach Theme |
| Code/Syntax | --syn-bg / --syn-fg / --syn-comment / --syn-keyword / --syn-string / --syn-number / --syn-function / --syn-attr / --syn-tag / --syn-builtin / --syn-type / --syn-variable / --syn-literal / --syn-operator / --syn-title / --syn-addition |
Syntaxhervorhebung | je nach Theme |
| Code/Syntax | --code-header-bg / --code-stroke |
Hintergrund sowie Rahmen von Codeblöcken | je nach Theme |
| Diagramme | --cat-1 … --cat-12 |
Farben für Diagrammdaten; Verhältnis 3:1 zu --surface-0 |
je nach Theme |
| Diagramme | --seq-1 … --seq-5 |
Abstufungen von hell nach dunkel | je nach Theme |
| Diagramme | --div-1 … --div-5 |
Kategorien: schlecht, neutral, gut | je nach Theme |
| Diagramme | --chart-grid / --chart-axis |
Hilfslinien für Diagramme | je nach Theme |
| Chatblasen | --bubble-user-text / --bubble-assistant-text / --bubble-user-bg / --bubble-assistant-bg |
Chatblasen | je nach Theme |
| Chatblasen | --rp-speech / --rp-thought / --rp-shout / --rp-whisper / --rp-ooc / --rp-action / --rp-critical |
Farben für Rollenspiel-Chatblasen | je nach Theme |
| Diff-Ansicht | --diff-add-bg / --diff-add-text / --diff-remove-bg / --diff-remove-text |
Darstellung von Änderungen | je nach Theme |
| Schriftgrößen | --fs-xs / --fs-sm / --fs-md / --fs-lg / --fs-xl / --fs-2xl |
Schriftgrößen | je nach Theme |
| Schriftgewichte | --fw-medium / --fw-semibold / --fw-bold |
Schriftgewichte | je nach Theme |
| Schriftarten | --font-sans / --font-mono / --font-display |
Schriftarten | je nach Theme |
| Abstände | --space-1 … --space-8 |
Abstände von 4 bis 64 Pixeln | je nach Theme |
| Rundungen | --radius-sm / --radius-md / --radius-lg / --radius-pill |
Rundungen von Elementen | je nach Theme |
| Schatten | --shadow-1 / --shadow-2 / --shadow-3 / --shadow-4 |
Stärke der Schatteneffekte | je nach Theme |
| Z-Stapelung | --z-modal / --z-toast / --z-popover / --z-nav |
Reihenfolge von Elementen im Z-Stapel | je nach Theme |
| Animationen | --motion-fast / --motion-med / --motion-slow / --easing-standard |
Geschwindigkeit von Animationen; bei „reduced-motion“ werden Schleifen gestoppt | je nach Theme |
| Markdown | --md-bold / --md-italic / --md-bolditalic / --md-bolditalic-glow |
Formatierung für Markdown im App-Text | je nach Theme |
| Sonstiges | --mark-bg / --selection-text / --selection-bg / --media-filter / --quote-bar / --heartbeat-text / --heartbeat-hover / --offline-text / --on-offline / --canvas-handle |
Kleine Zusatzfunktionen | je nach Theme |
Quelle: docs/TOKENS.md (22 Gruppen, ca. 270 Tokens – grep -oE '\| \(–[a-zA-Z][a-zA-Z0-9-]*)` |’ docs/TOKENS.md | sort -u | wc -lliefert 272 eindeutige Token-Namen; 22 Gruppen mit## `).
Komponentenklassen (jeder Modifikator, jeweils in einer Zeile)
Der Zustand wird über native Attribute bestimmt (disabled, checked, aria-pressed, aria-selected, aria-current, aria-invalid, aria-busy; es werden niemals zusätzliche Klassen verwendet). Die meisten Selektoren bestehen aus nur einer Klasse, sodass später geladene Regeln mit gleicher Spezifität Vorrang haben. Logische Eigenschaften sind überall vorhanden (funktionieren auch bei Rechts-nach-Links-Schreibweise). „Aktiv“, „ausgewählt“ und „aktueller Zustand“ werden durch --selected dargestellt; „deaktiviert“ wird durch einen gestrichelten Rahmen gekennzeichnet. Quelle: docs/COMPONENTS.md.
| Klasse | Modifikatoren / Teile | Beschreibung |
|---|---|---|
ui-stack |
— | Spaltenlayout; Abstand --space-3 |
ui-row |
— | Zeilenlayout, zentriert; Abstand --space-2 |
ui-grid |
--ui-grid-min |
Automatische Erstellung von Spalten; min wird am Element gesetzt |
ui-container |
— | Zentriert; maximale Breite --content-max |
ui-spacer |
— | Schiebt den Rest einer Zeile nach hinten |
ui-app |
__header __nav __main |
App-Shell (Header, Seitenleiste, Hauptinhalt); Navigationsleiste verschwindet unter 760 px |
ui-brand |
— | App-Titel im Header |
ui-nav |
__label __item |
Seitenleiste |
ui-title / ui-heading / ui-subheading / ui-lead / ui-kicker / ui-small / ui-mono / ui-num / ui-kbd / ui-code / ui-divider |
— | Typografie-Elemente (<hr> ist .ui-divider) |
ui-text-primary / -secondary / -tertiary / -disabled / -link |
— | Text-Klassen; für neuen Code sollten die Tokens verwendet werden |
ui-markdown |
— | Container für formatiertes Markdown; siehe docs/TEXT.md |
ui-btn |
--primary --ghost --outline --danger --cta --sm --lg --icon --block |
Knöpfe; funktionieren auch mit <a>; reagieren auf aria-pressed / aria-busy / disabled |
ui-btn-group |
— | Nebeneinanderliegende Knöpfe teilen sich abgerundete Kanten |
ui-field |
— | Container für Formularelemente (Label + Steuerelement + Hilfetext) |
ui-label |
— | Beschriftung eines Formularfeldes |
ui-input |
--sm |
Text-Eingabefeld |
ui-select |
— | Gestyltes <select>; data-ui-theme-picker lädt den Theme-Picker |
ui-textarea |
— | Gestyltes <textarea> |
ui-help |
— | Hilfetext zu einem Feld (verweist auf aria-describedby) |
ui-error |
— | Fehlermeldung zu einem Feld; erscheint bei aria-invalid="true" |
ui-input-group |
— | Kombination aus Eingabefeld und Knopf (z.B. Suchfeld) |
ui-check |
— | Reihe von Checkboxen, Radio-Buttons oder Schaltern |
ui-checkbox |
— | Gestyltes <input type="checkbox"> |
ui-radio |
— | Gestyltes <input type="radio"> |
ui-switch |
— | role="switch"; Checkbox, die wie ein Schalter aussieht |
ui-switch-state |
data-on data-off |
„An“/„Aus“-Beschriftung (aria-hidden); der Schalter meldet selbst seinen Zustand |
ui-range |
— | Gestyltes <input type="range">; Farbe wird durch --slider-color bestimmt |
ui-segmented |
— | Gruppe von Knöpfen, die wie Radio-Buttons funktionieren |
ui-tabs |
ui-tab |
Reiterliste; Links nutzen <a aria-current="page">; Tastaturbedienung ist Aufgabe der App |
ui-card |
__header __title __footer --raised --interactive |
Karte; aria-selected / aria-current kennzeichnen die ausgewählte Karte |
ui-well |
— | Einliegender Bereich (Logs, Vorschauen, sekundäre Inhalte) |
ui-stat |
__label __value |
Paar aus Beschriftung und Wert |
ui-badge |
--success --warning --danger --info --live --accent --neutral |
Pillenförmiges Badge |
ui-dot |
--success --warning --danger --info --live --neutral |
Statuspunkt |
ui-count |
--accent --danger |
Zähler-Chip |
ui-callout |
--info --success --warning --danger __title |
Farbiger Hinweis; bei Fehlern sollte role="alert" verwendet werden |
ui-table-wrap |
— | Umhüllt <table class="ui-table"> für klebende Kopfzeilen/Scrollen |
ui-table |
--hover --compact td.num |
Tabellenstil |
ui-dialog |
— | Gestyltes <dialog> |
ui-drawer |
— | Seitenleiste über <dialog> |
ui-menu |
__item |
Menüliste |
[data-ui-tooltip] |
data-ui-tooltip-side="bottom" |
Tooltip für beliebige Elemente |
ui-progress |
— | Linearer Fortschrittsbalken |
ui-spinner |
— | Ladeanzeige |
ui-skeleton |
— | Skelett-Loading-Animation |
ui-breadcrumbs |
— | Pfadleiste |
ui-pagination |
— | Seitennavigation |
ui-avatar |
— | Kreisförmiges Profilbild |
ui-chip |
__remove |
Entfernbarer/auswählbarer Chip |
ui-details |
— | „Accordion“-Struktur über <details> |
ui-fieldset |
— | Feldsatz mit Legende |
ui-codeblock |
__bar |
<figure> mit <figcaption class="ui-codeblock__bar"> + <pre> |
ui-empty |
— | Leerer Zustand |
ui-bubble |
--user --assistant |
Chatblase |
Öffentliche Methoden von window.UITheme und window.UIComponents
Quelle: ui-theme/ui-theme.d.ts (TypeScript-Deklarationen für beide globale Objekte).
window.UITheme (UIThemeApi):
| Member | Typ | Funktion |
|---|---|---|
version |
string (nur lesen) |
Die Version des Ordners, z. B. "1.0.0" |
config |
Objekt (nur lesen) | { themes, default, auto, storageKey, families, printTheme } |
current() |
() => string |
Der aktuelle Theme-Name |
theme([slug]) |
(slug?) => UIThemeInfo \| null |
Informationen zu einem Theme (oder dem aktiven) |
list() |
() => UIThemeInfo[] |
Alle aktivierten Themes |
set(slug) |
(slug) => string |
Wechsel zu einem Theme; gibt den Namen zurück |
reset() |
() => string |
Zurücksetzen auf das Standard-Theme; gibt den Namen zurück |
partner([slug]) |
(slug?) => string \| null |
Das „Licht“-/„Dunkel“-Partner-Theme einer Familie (z. B. laserlloyd ↔ laserlloyd-light) |
toggleFamily() |
() => string \| null |
Wechsel zum Partner-Theme; gibt den neuen Namen zurück |
onChange(listener) |
(fn) => () => void |
Abonnieren von Änderungen; gibt eine Funktion zum Abmelden zurück; detail.print ist true, wenn der Wechsel für den Druck erfolgt |
token(name, [el]) |
(name, element?) => string |
Der Rohwert eines Tokens (z. B. "#7c3aed") |
tokens(names, [el]) |
(names, element?) => Record<name, string> |
Mehrere Tokens auf einmal |
color(name) |
(name) => string |
Aufgelöster rgb()-Wert für das Canvas |
colors(names) |
(names) => Record<name, string> |
Mehrere aufgelöste Farbwerte für das Canvas |
mountPicker(target, [opts]) |
(elOrSel, options?) => HTMLSelectElement \| null |
Füllt ein Select-Element mit dem Theme-Picker; options sind { label, coreLabel, optInLabel, systemLabel } |
Das Ereignis ui-theme-change wird auf document ausgelöst mit { slug, theme, previous, print }.
window.UIComponents (UIComponentsApi): (erfordert ui-components.js)
| Methode | Signatur | Funktion |
|---|---|---|
confirm |
(opts: UIDialogOptions \| string) => Promise<boolean> |
Themede confirm()-Funktion; Optionen sind { title, message, label, confirmLabel, cancelLabel, danger } |
alert |
(opts: UIDialogOptions \| string) => Promise<void> |
Themede alert()-Funktion |
prompt |
(opts: UIPromptOptions \| string) => Promise<string \| null> |
Themede prompt()-Funktion; bei Abbruch wird null zurückgegeben; zusätzliche Optionen sind { value, placeholder, type } |
toast |
(message, { kind?, timeout? }) => HTMLElement |
Toast mit den Varianten info, success, warning, danger; gibt das Element zurück |
window.UI_THEME_MANIFEST (optional; hat Vorrang vor den Standardwerten aus dem Skript-Tag): { themes, default, defaultDark, defaultLight, storageKey, families, legacy, mirrorAttr, fontsHref, printTheme }. themes akzeptiert entweder ein Array oder eine kommagetrennte Liste.
Einstellungen über das <script>-Tag (data-*-Attribute)
| Attribut | Standardwert | Funktion |
|---|---|---|
data-themes |
Die sechs Kern-Themes (purple,midnight-gold,glacier,forest,paper,daylight) |
Kommagetrennte Liste der aktivierten Themes; steuert den Picker sowie welche gespeicherten Werte berücksichtigt werden. Ohne Angabe von data-themes aktiviert ui-theme.js die sechs Kern-Themes mit set==="core" (ui-theme.js:147-149). |
data-default |
Das erste aktivierte Theme (der erste Name in data-themes, oder purple, falls keines aktiviert ist und nicht auto) |
Der Standard-Theme-Name; bei auto wird das OS-Setting genutzt. Der Text auto aktiviert die automatische Erkennung via prefers-color-scheme (ui-theme.js:164); fehlt oder ist leer, wird das erste aktivierte Theme verwendet (ui-theme.js:177-179). |
data-default-dark |
Das erste nicht-helle aktivierte Theme (erster Name in data-themes, bei dem ground !== "light"; sonst das erste aktivierte Theme oder purple, falls nichts aktiviert ist) |
Entsprechend der Einstellung „auto“: wird bei dunklem OS-Setting ohne explizite Angabe verwendet (ui-theme.js:168-175). |
data-default-light |
Das erste helle aktivierte Theme (erster Name in data-themes, bei dem ground === "light"; sonst das erste aktivierte Theme oder purple, falls nichts aktiviert ist) |
Entsprechend der Einstellung „auto“: wird bei hellem OS-Setting ohne explizite Angabe verwendet (ui-theme.js:168-175). |
data-storage-key |
ui-theme |
Der Schlüssel für localStorage, unter dem die Auswahl des Nutzers gespeichert wird (ui-theme.js:185). AGENTS.md §3 empfiehlt, diesen Wert zu überschreiben mit <appname>.theme, damit die Einstellung der App nicht mit anderen ThemeForge-Apps auf derselben Domain kollidiert. |
data-families |
false |
Gruppiert Themes nach Familien im Picker |
data-print-theme |
auto |
Bestimmt, wie die Seite gedruckt wird: bei dunklem oder OLED-Theme wechselt auto zum hellen Partner-Theme (oder dem ersten hellen Theme bzw. daylight); ein konkreter Name druckt genau dieses Theme; none verändert nichts; bei hellem Theme bleibt die Seite unverändert (ui-theme.js:474-490). |
data-legacy-key |
— | Ein älterer Speicherschlüssel, der einmal migriert werden muss (zusammen mit data-legacy-map) |
data-legacy-map |
— | Eine Zuordnung „von→zu“ für alte Werte (JSON-Objekt) |
data-mirror-attr |
— | Spiegelt das aktive Theme auf ein anderes Attribut – für Bibliotheken, die dies auslesen |
data-fonts-href |
— | Verweist auf eine Stylesheet-Datei, die die Schriftarten des Themes lädt |
Quellen: ui-theme.js:147-149, 164, 168-174, 185, 474-490 (Laufzeit-Standards) sowie AGENTS.md §3, §12 (empfohlene Überschreibungen – z. B. data-themes auf die sechs Kern-Themes setzen, data-default="auto" und data-storage-key="<appname>.theme").
Adapter
| Adapter | Dateien | Funktion |
|---|---|---|
| NiceGUI / Quasar | adapters/quasar.js + adapters/quasar.css |
ui-theme.js direkt nachladen, anschließend adapters/quasar.css via ui.add_head_html. Quasars Toggle-Elemente, Checkboxen und Radio-Buttons nutzen das Design für den Kontrollzustand; deaktivierte Elemente erscheinen gestrichelt mit voller Deckkraft. Entfernen Sie alle Aufrufe von ui.dark_mode() – der Adapter übernimmt dies. |
| Tailwind CSS v4 | adapters/tailwind.css |
@import "./<pfad>/ui-theme/adapters/tailwind.css"; nach @import "tailwindcss";. Bereitgestellt werden z. B. bg-surface-2, text-fg, text-fg-muted, bg-accent, text-on-accent, border-line. Für Text werden fg-*-Werte verwendet, da text-*-Größen zu Tailwind gehören. |
| Tailwind CSS v3 | adapters/tailwind-v3.preset.js |
presets: [require('./<pfad>/ui-theme/adapters/tailwind-v3.preset.js')]. Gleiche Token wie beim v4-Adapter, jedoch als v3-Preset ausgedrückt. |
Der Tailwind-Adapter übersetzt die Theme-Token; der Quasar-Adapter passt die Komponentenklassen an. Beide sind nicht zwingend erforderlich, damit der Rest des Pakets funktioniert.
Vollständiger Installationsweg (wörtlich – der Installationsabschnitt aus AGENTS.md)
AGENTS.md ist das Installationsskript in Textform, geschrieben für KI-Programmierer. Die ersten beiden Abschnitte werden hier vollständig wiedergegeben; sie stellen die Anweisungen dar, die einer KI zugewiesen werden. Zeichen wurden gemäß §8 der Article-Forge-Spezifikation maskiert (ein rohes <blockquote> verarbeitet Markdown direkt, daher werden <, >, & als <, >, & dargestellt).
## 1. Entscheidungen treffen | Frage | Standardantwort | |---|---| | Wo soll der Ordner hin? | In den statischen Ordner der App, unverändert bereitgestellt: `static/ui-theme/` (Flask, FastAPI, Django), `public/ui-theme/` (Vite, Next.js, Create React App), `app/static/ui-theme/` oder neben `index.html` bei reinen Websites. | | Welche Themes? | Die sechs Kern-Themes: `purple,midnight-gold,glacier,forest,paper,daylight`. Optional können weitere Themes (`night-red`, `electric-yellow`, `laserlloyd`, `laserlloyd-light`) hinzugefügt werden, falls der Nutzer sie wünscht. | | Standard-Theme? | `auto`: Das OS-Setting für Helligkeit/Dunkelheit wird übernommen, bis der Nutzer selbst wählt (`data-default-dark="midnight-gold"`, `data-default-light="daylight"`). | | Speicherschlüssel? | `<appname>.theme`, z. B. `notes.theme`. | ## 2. Installation Ausführen im Root-Ordner der App (Python 3.9 oder neuer; ggf. `static/ui-theme` an Ihren Pfad anpassen):Unter Windows nutzen Sie `python` bzw. `py` statt `python3`; die Zeile funktioniert in PowerShell, cmd und Bash gleichermaßen. Das Skript lädt den Installer, der die neueste Version von GitHub abruft, jede Datei gegen eine Prüfsummenliste vergleicht und den Ordner schreibt. Spätere Updates lauten `python3 static/ui-theme/update.py`. Offline-Installation: Laden Sie ein Release-Archiv (`.tar.gz`) an einem anderen Ort herunter und führen Sie aus: `python3 update.py --source <archiv> --dest static/ui-theme` mittels der Datei `update.py` im Ordner `ui-theme/`. Alternativen, falls Python nicht verfügbar ist: - **git:** `git clone --depth 1 https://github.com/LaserLloyd/ThemeForge.git ut-tmp`, kopieren Sie `ut-tmp/ui-theme` in Ihre App und löschen Sie `ut-tmp`. - **Node:** `npx degit LaserLloyd/ThemeForge/ui-theme#v1.0.0 static/ui-theme`. - **Keine Installation (Prototypen, einzelne HTML-Dateien):** Laden Sie die Dateien via jsDelivr, fest auf eine Version gebunden: `https://cdn.jsdelivr.net/gh/LaserLloyd/ThemeForge@v1.0.0/ui-theme/ui-theme.js` (analog für jede CSS-Datei). Vermeiden Sie `@main`; der CDN-Cache hält bis zu 12 Stunden an. Ein CDN-Update erfolgt durch Änderung der Version; `update.py` sowie die Schritte 8.5, 9 und 10 gelten hier nicht.python3 -c "import urllib.request as u,sys;sys.argv=['update.py','--dest','static/ui-theme'];exec(u.urlopen('https://raw.githubusercontent.com/LaserLloyd/ThemeForge/main/ui-theme/update.py').read())"
Der Rest von AGENTS.md (Abschnitte 3–12) erläutert den Head-Block, den Picker, das Erstellen von Tokens, Regeln, Diagramme, die Verifizierung, den Text, der in die eigene AGENTS.md eingefügt werden sollte, damit nachfolgende KIs die Konvention beibehalten, den Update-Befehl, eine Fehlerliste sowie die oben genannten Referenzen.
Kontrast-Prüfung (Zusammenfassung, alle Themes)
tools/check_contrast.py läuft bei jedem Push im CI-System. Der vollständige Bericht ist 124 KB groß (ein Abschnitt pro Theme plus eine Zusammenfassung) und unter docs/contrast-report.md zu finden; die Zusammenfassung lautet:
| Theme | Gruppe | Profil | Prüfungen | Fehler |
|---|---|---|---|---|
| purple | Kern | Standard | 147 | 0 |
| midnight-gold | Kern | Standard | 147 | 0 |
| glacier | Kern | Standard | 147 | 0 |
| forest | Kern | Standard | 147 | 0 |
| paper | Kern | Standard | 147 | 0 |
| daylight | Kern | Standard | 147 | 0 |
| electric-yellow | Optional | Standard | 147 | 0 |
| laserlloyd | Optional | Standard | 147 | 0 |
| laserlloyd-light | Optional | Standard | 147 | 0 |
| night-red | Optional | Nacht | 171 | 0 |
Die Anforderungen, die jedes Theme erfüllen muss: Haupttext 7:1, sekundärer Text 6:1 (im Kontrastbericht wird dies als „Versprechen des 6:1-Standards“ bezeichnet – docs/contrast-report.md kennzeichnet jede Zeile mit text-secondary on surface-2 exakt so); alle Textstufen auf jedem Hintergrund mindestens 4.5:1, deaktivierte Elemente 3:1, on-accent und on-status ebenfalls 4.5:1; Status-Text auf farbigem Hintergrund 4.5:1, on-selected 4.5:1; bei ausgewählten/ nicht ausgewählten Elementen gelten 3:1 für Rand und Schrift; border-strong, control-track sowie der Fokusring müssen ebenfalls 3:1 erreichen; Syntax-Farben auf --syn-bg mindestens 4.5:1 (Kommentare 3.5:1). Die Diagramm-Serien (--cat-1 bis --cat-12) benötigen 3:1 im Verhältnis zu --surface-0. An/Aus nach Form: Ein „an“-Element wird mit --selected gefüllt; ein „aus“-Element zeigt nur einen Rand aus --unselected-border; bei Schaltern fügt „an“ eine Leiste zum Knopf hinzu, „aus“ einen Ring. Deaktiviert erscheint gestrichelt und in der deaktivierten Farbstufe – auch wenn es eigentlich „an“ sein sollte.
Frameworks
Gemäß docs/INTEGRATIONS.md: reines HTML · FastAPI, Flask, Starlette (Jinja-Templates) · Django · Vite, Vue, Svelte, SvelteKit, Astro · Next.js (App Router) · NiceGUI (Quasar) · Tailwind CSS · Electron, Tauri, pywebview · Schriftarten · Diagramme · Content Security Policy. Für jedes Framework: ui-theme/ in den statischen Ordner legen, den Head-Block gemäß AGENTS.md §3 einfügen und den Ordner ohne Cache bereitstellen (z. B. durch Versionierung der URLs), damit Updates sofort sichtbar sind. Im Repository finden Sie zwei konkrete Beispiele: examples/static-html/ (eine einzelne Seite) sowie examples/fastapi-jinja/ (FastAPI + Jinja; 2.172 Byte große app.py).
Druck, Kontrast und Animationen
Drei Aspekte, die der Laufzeitcode erkennt und auf die das CSS reagiert – ohne pro-Theme-Einstellungen:
– Drucken – data-print-theme bestimmt, welches Theme beim Drucken verwendet wird (ui-theme.js:474-490). Wenn das aktive Theme dunkel oder für OLED-Displays geeignet ist, schaltet auto automatisch auf das helle Pendant dieses Themes um – oder auf das erste aktivierte helle Theme bzw. auf „daylight“. Der Bezeichner des gewählten Themes wird beim Drucken verwendet; „none“ bewirkt, dass kein Theme gewechselt wird. Bei einem hellen Theme wird die Seite einfach so gedruckt, wie sie ist. Beim Drucken werden außerdem die Seitenleiste, Toasts, Menüs sowie Tooltips ausgeblendet.
– prefers-contrast: more – In jedem Theme werden die Linienstärken erhöht und der dritte Textgrad auf das Niveau des sekundären Textgrads angehoben.
– prefers-reduced-motion – Alle Animationen werden gestoppt bzw. verkürzt; die Werte der Variablen --motion-* werden auf 0 gesetzt.
Versionen
Aus dem Repository, das in diesem Artikel beschrieben wird (geklont am 05.10.2026):
$ git log -1 --format='%h %ci'
56fb665 2026-10-05 21:46:52 +0900 # ThemeForge 1.0.0
$ cat ui-theme/VERSION
ThemeForge 1.0.0 3db64d9f574f
$ wc -c ui-theme/*.js ui-theme/*.css ui-theme/*.ts ui-theme/*.py 2>/dev/null
23515 ui-theme.js
5441 ui-components.js
2841 ui-theme.d.ts
16081 update.py
13255 ui-theme-base.css
51344 ui-components.css
86389 ui-theme.css
$ node --check ui-theme.js ui-components.js
(node v24.18.0) – Beide Dateien sind in Ordnung; ebenso adapters/quasar.js sowie adapters/tailwind-v3.preset.js.
$ python -m unittest discover -s tests
32 Tests wurden in 1,212 Sekunden ausgeführt.
OK (1 Test übersprungen)
$ python tools/check_contrast.py --fail-on any
…
## Zusammenfassung
| Theme | Gruppe | Profil | Prüfungen | Fehler |
|-------------------|----------|-------------|-----------|--------|
| purple | core | standard | 147 | 0 |
| midnight-gold | core | standard | 147 | 0 |
| glacier | core | standard | 147 | 0 |
| forest | core | standard | 147 | 0 |
| paper | core | standard | 147 | 0 |
| daylight | core | standard | 147 | 0 |
| electric-yellow | opt-in | standard | 147 | 0 |
| laserlloyd | opt-in | standard | 147 | 0 |
| laserlloyd-light | opt-in | standard | 147 | 0 |
| night-red | opt-in | night | 171 | 0 |
Unterstützte Browser: aktuelle Versionen von Chrome, Edge, Firefox und Safari (2024 oder neuer). Die Implementierung nutzt :has(), color-mix() sowie die Popover-API; ältere Browser behalten zwar die Farben bei, doch einige Komponentenzustände sowie Menüs funktionieren dort nicht mehr korrekt.
Verwandte Projekte: ChatForge: ein lokaler NPU-basierter KI-Assistent für den Copilot Key · StudioForge: ein GPU-exklusiver LLM-Server · DisPatch: selbstgehosteter KI-Chat · Mein lokales KI-Agenten-System · Wie man einen LLM dazu bringt, ein beliebiges Projekt an das eigene System anzupassen
Downloads
Kostenlos für die private Nutzung. Wenn es dir einen Nachmittag erspart, ist der Kaffee-Button gleich in der Nähe.