Communitygithub.com

cdesiles/design-system

Erstelle ein Designsystem aus zwei CSS-Dateien (tokens.css und components.css), die andere Apps kopieren können, dokumentiert durch eine Musterkarte. Lies dies, bevor du etwas mit mehr als einem Bildschirm entwirfst, und immer dann, wenn das Projekt noch kein bestehendes System hat.

Was ist design-system?

Dieses Skill erzeugt ein modulares Designsystem, das als zwei separate CSS-Dateien – `tokens.css` (Custom Properties) und `components.css` (darauf aufbauende Klassen) – ausgegeben wird. Die Idee ist, dass diese Dateien von anderen Projekten einfach kopiert werden können, ohne zusätzliche Build-Schritte oder Abhängigkeiten. Eine dritte Datei, die Musterkarte `Design System.html`, dient als lebende Dokumentation, die beide CSS-Dateien einbindet und alle Tokens sowie Komponenten mit ihren realen Zuständen anzeigt. Der Fokus liegt auf Wartbarkeit: Durch die strikte Trennung in Primitive und semantische Tokens sowie die Verwendung von Oklch-Farben und skalaren Größen wird ein Rebranding oder eine Erweiterung zum Austausch weniger Werte. Das Skill ist plattformunabhängig und funktioniert mit React, statischen Seiten oder anderen Tools, da reines CSS ohne Präprozessoren und ohne globale Seiteneffekte verwendet wird. Die Musterkarte listet die Komponenten (Button, Input, Card, Navigation, etc.) mit ihrem Markup auf, sodass Entwickler sie direkt übernehmen können. Zudem enthält es Regeln für Barrierefreiheit, Kontrastmessung und Versionsverwaltung, die sicherstellen, dass das System konsistent und erweiterbar bleibt.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/cdesiles/opencode-kit/tree/HEAD/skills/design-system

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Designsystem

Das System ist das Artefakt. Alles andere wird daraus gebaut. Ein Auslieferungsgegenstand, der seine eigenen Farben und Abstände erfindet, ist ein Einzelstück; ein auf Tokens aufbauendes Auslieferungsgegenstand kann erweitert, umbenannt und konsistent gehalten werden.

Ausgabe

Drei Dateien, und die Trennung ist der springende Punkt:

  • design/tokens.css – die Tokens und sonst nichts. Reine CSS-Custom-Properties.
  • design/components.css – die Komponenten als Klassen, die nur aus den semantischen Tokens aufgebaut sind.
  • design/Design System.html – die Musterkarte. Sie <link>t beide Dateien und dokumentiert sie. Nur Dokumentation: Sie deklariert keine eigenen Werte.

Die beiden CSS-Dateien sind das System: Sie werden von anderen Apps kopiert. Die Musterkarte bleibt im Projekt als deren Dokumentation.

Abschnitte in der Musterkarte, in dieser Reihenfolge:

  1. Absicht – drei Sätze: für wen dies ist, wie es sich anfühlen soll, was es explizit nicht ist.
  2. Farbe – jeder Farbmuster mit seinem Token-Namen, dem aufgelösten Wert und den Paarungen, die den Kontrast bestehen.
  3. Schrift – Schriftfamilien, -stärken, die Skala mit einer benannten Rolle pro Schritt und ein Absatzbeispiel in Körpergröße.
  4. Raum und Form – die Abstandsskala, Radien, Schatten, Rahmen.
  5. Komponenten – jede in ihren echten Zuständen dargestellt, neben dem Markup, das eine App kopiert.
  6. Regeln – die fünf oder sechs Entscheidungen, die jemand sonst falsch machen würde.
  7. In einer App verwenden – die Version, die zwei zu kopierenden Dateien, die Reihenfolge zum Laden, der Font <link>, die root-Klasse und was sich seit der letzten Version geändert hat.

Tokens

Zwei Schichten. Primitive halten Rohwerte; semantische Tokens benennen eine Aufgabe und verweisen auf ein Primitiv. Komponenten referenzieren ausschließlich semantische Tokens – das macht ein Rebranding zu einer einzeiligen Änderung.

Schreibe dies in design/tokens.css. Dies ist die einzige Datei im Projekt, in der ein Rohwert vorkommen darf. acme steht für das Präfix des Systems (siehe Teilen):

/* Acme design system 1.0.0 — tokens. Copy this file as is; change it in its source project. */
:root {
  /* primitives */
  --acme-ink-900: oklch(0.22 0.02 260);
  --acme-ink-600: oklch(0.48 0.02 260);
  --acme-paper-50: oklch(0.99 0.005 90);
  --acme-paper-100: oklch(0.96 0.008 90);
  --acme-line-200: oklch(0.90 0.006 90);
  --acme-accent-500: oklch(0.55 0.14 35);
  --acme-accent-600: oklch(0.45 0.15 35);
  --acme-accent-100: oklch(0.94 0.03 35);

  /* semantic */
  --acme-text: var(--acme-ink-900);
  --acme-text-muted: var(--acme-ink-600);
  --acme-bg: var(--acme-paper-50);
  --acme-surface: var(--acme-paper-100);
  --acme-border: var(--acme-line-200);
  --acme-accent: var(--acme-accent-500);
  --acme-accent-hover: var(--acme-accent-600);
  --acme-accent-wash: var(--acme-accent-100);

  /* type */
  --acme-font-display: "Fraunces", Georgia, serif;
  --acme-font-text: "Public Sans", system-ui, sans-serif;
  --acme-step--1: 0.875rem;
  --acme-step-0: 1rem;
  --acme-step-1: 1.25rem;
  --acme-step-2: 1.5625rem;
  --acme-step-3: 1.953rem;
  --acme-step-4: 2.441rem;
  --acme-step-5: 3.052rem;

  /* space, on a 4px base */
  --acme-s-1: 4px;  --acme-s-2: 8px;   --acme-s-3: 12px;  --acme-s-4: 16px;
  --acme-s-5: 24px; --acme-s-6: 32px;  --acme-s-7: 48px;  --acme-s-8: 64px;  --acme-s-9: 96px;

  /* shape and motion */
  --acme-radius-sm: 4px; --acme-radius: 8px; --acme-radius-lg: 16px;
  --acme-border-width: 1px; --acme-ring-width: 2px;
  --acme-shadow-1: 0 1px 2px oklch(0.2 0.02 260 / 0.06);
  --acme-shadow-2: 0 4px 16px oklch(0.2 0.02 260 / 0.08);
  --acme-ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --acme-dur: 160ms;
}

Dieser Block ist ein Ausgangspunkt, keine blind zu kopierende Vorlage. Ändere den Akzentfarbton, die Schriftkombination und die Wärme der Tinte entsprechend der Vorgabe – aber behalte die Struktur bei.

Regeln für die Tokens

  • Kontrast wird gemessen, nicht abgeschätzt. Fließtext 4,5:1 gegen seinen tatsächlichen Hintergrund; großer Text und UI-Rahmen 3:1. Jede Farbmuster-Seite gibt ihre Paarungen an.
  • Oklch, nicht zufälliges Hex. Gleichmäßige Helligkeitsschritte verhindern, dass Paletten matschig aussehen. Halte die Chroma über eine Farbfamilie hinweg annähernd konstant.
  • Keine ungenutzten Tokens. Wenn nichts auf einen Token verweist, lösche ihn.
  • Keine Werte außerhalb dieser Datei. Ein Hex-, oklch()-Literal, px-Größe oder Schatten an anderer Stelle ist ein Token, der noch nicht benannt wurde.
  • Zwei Schriftfamilien. Eine Display-, eine Textschrift. Fallback-Stapel müssen echt sein, nicht nur sans-serif.
  • Skalieren, nicht ad-lib. Wenn ein Wert nicht auf der Abstands- oder Schriftskala liegt, füge ihn entweder bewusst hinzu oder verwende den nächstgelegenen.
  • Dark Mode nur auf Anfrage – aber halte die Farben semantisch, sodass das spätere Hinzufügen ein Tokentausch ist, keine Neuschreibung.

Komponenten

Schreibe sie in design/components.css und stelle jede in der Musterkarte in den Zuständen Standard, Hover, Fokus, Aktiv und Deaktiviert dar, wo sie zutreffen:

  • Button – primär, sekundär, Geist. Eine Größe reicht normalerweise aus.
  • Texteingabe und Select, mit Label, Hilfetext und Fehlerzustand.
  • Karte, mit einem echten Inhaltsbeispiel, nicht „Lorem ipsum".
  • Navigation, sowohl in Desktop- als auch in schmaler Breite.
  • Tabellen- oder Listenzeile mit einem Header.
  • Badge und Tag.
  • Modal oder Dialog.
  • Leerer Zustand.
  • Toast oder Inline-Hinweis.

Jede Komponente verwendet ausschließlich semantische Tokens. Wenn eine Komponente einen Wert benötigt, der keinen Token hat, ist das eine Lücke im System – füge den Token hinzu, kodiere den Wert nicht fest.

/* Acme design system 1.0.0 — components. Needs tokens.css from the same version, loaded first. */

.acme {
  font-family: var(--acme-font-text);
  font-size: var(--acme-step-0);
  color: var(--acme-text);
  background: var(--acme-bg);
}

.acme-button {
  font: inherit;
  padding: var(--acme-s-2) var(--acme-s-4);
  border: var(--acme-border-width) solid transparent;
  border-radius: var(--acme-radius);
  background: var(--acme-accent);
  color: var(--acme-bg);
  transition: background var(--acme-dur) var(--acme-ease);
}
.acme-button:hover { background: var(--acme-accent-hover); }
.acme-button:focus-visible { outline: var(--acme-ring-width) solid var(--acme-accent); outline-offset: var(--acme-ring-width); }
.acme-button--ghost { background: transparent; color: var(--acme-accent); border-color: var(--acme-border); }

Teilen

Andere Apps übernehmen das System, indem sie tokens.css und components.css kopieren. Die folgenden Regeln sorgen dafür, dass eine Kopie überall funktioniert.

  • Alles mit Präfix versehen. Wähle einen kurzen Namen für das System vor dem ersten Token und setze ihn auf jede Custom Property und jede Klasse: --acme-accent, .acme-button. Kopierte Dateien liegen dann neben dem eigenen CSS der App ohne Kollisionen. Das Präfix ist Teil der API; ändere es nie.
  • Reines CSS in beiden Dateien. Keine Tailwind-Direktiven, keine Präprozessor-Syntax, kein Nesting, keine @layer-Anforderung, kein @import zwischen ihnen. Eine React-App, eine statische Seite oder ein anderes Designtool muss mit einer direkten Kopie identische Ergebnisse erzielen.
  • Alles wird zur Laufzeit aufgelöst. Keine Build-Zeit-Farbmathematik, keine kompilierte Ausgabe.
  • Nichts Globales in components.css. Keine Resets, keine Elementselektoren, nichts auf html oder body: Das Einfügen der Datei in eine App darf diese nicht umgestalten. Basis-Textstile leben auf der root-Klasse .acme, die eine App dort hinzufügt, wo sie sie haben möchte.
  • Zustände kommen aus dem Markup. Gestalte :hover, :focus-visible, :disabled, [aria-invalid="true"], [aria-current] und [aria-expanded] anstelle von Zustandsklassen, die eine App umschalten müsste, damit die Komponenten mit jedem Framework-HTML funktionieren.
  • Einfach zu überschreiben. Nach Möglichkeit eine Klasse pro Regel, keine IDs, kein !important.
  • Eine Version für beide Dateien. Die erste Zeile jeder Datei nennt das System und seine Version; erhöhe sie bei jeder Änderung in beiden Dateien. Patch für einen geänderten Wert, Minor für einen neuen Token oder eine neue Komponente, Major für eine Entfernung. Umbenennen durch Hinzufügen des neuen Tokens und Beibehalten des alten als Alias, --acme-old: var(--acme-new);, bis die Apps umgestellt sind; das Entfernen des Alias ist der Major-Bump.
  • Projektspezifisches bleibt in der Musterkarte. Font-<link>-Tags, Containerbreiten und Asset-Pfade sind keine Tokens. Die Musterkarte zeigt den Font-<link>, damit eine App ihn mit den Dateien kopieren kann.

Wenn das Zielprojekt bereits eine Tokendatei hat, passe dich deren Benennung an, bevor du eigene erfindest. Ein gemeinsames Vokabular ist mehr wert als ein besserer Name.

Musterkarten-Seite

Die Musterkarte ist eine Dokumentation für Menschen, keine Komponentengalerie zum Bewundern. Zeige den Token-Namen neben dem Farbmuster. Zeige jede Komponente mit dem Markup, das eine App kopiert. Notiere die Zustände, die schwer zu sehen sind (Fokusringe, deaktiviert).

Binde beide Dateien ein, zuerst die Tokens, und setze die root-Klasse auf <body>. Verwende die eigenen Schrift- und Abstandsangaben des Systems, um die Musterkarte zu gestalten – es ist der erste Beweis, dass das System funktioniert.

Lies die Werte aus der Datei, anstatt sie abzutippen, damit die Dokumentation nicht abweichen kann:

<link rel="stylesheet" href="tokens.css">
<link rel="stylesheet" href="components.css">
…
<body class="acme">
<figure class="swatch" data-token="--acme-accent-500"></figure>
…
<script>
  for (const el of document.querySelectorAll('[data-token]')) {
    const name = el.dataset.token;
    const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
    el.dataset.value = value;                // printed by CSS
    el.style.setProperty('--swatch', value); // painted by CSS
  }
</script>

Der Farbmuster malt sich selbst aus dem Token und gibt den vom Browser aufgelösten Wert aus. Ein handgetipptes Hex ist eine zukünftige Lüge.

Abschluss

Führe design-verify auf der Musterkarte aus. Es listet jedes Farbliteral in der Musterkarte oder in components.css auf; es sollte keines geben. Überprüfe, ob jedes Farbmuster-Label lesbar ist, jede Komponente auf dem gleichen Basislinienraster ausgerichtet ist und kein Beispieltext bei 1024px Breite seinen Container überläuft.

Wenn das System an eine andere App geht, kopiert diese tokens.css und components.css unverändert sowie den Font-<link> aus der Musterkarte – nicht die Musterkarte selbst. Exportiere eine eigenständige Kopie der Musterkarte nur, wenn sie ohne den Ordner irgendwo gelesen werden muss.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Verwandte Skills