Communitygithub.com

OpenLabs-so/oa-design

Die Designsprache von [Open Analytics](https://getopen.so) in einer einzigen Datei, geschrieben für KI-Agenten und die Menschen, die sie steuern.

Was ist oa-design?

Dieses Skill definiert die vollständige Designsprache von Open Analytics in einer kompilierten, einfügbaren Datei für KI-Agenten wie Claude Code, Cursor oder Codex. Es enthält alle Token (Farben, Radien, Schriften, Schatten, Abstände), Layout-Konventionen (Platten, Grids, Seitenanatomie), detaillierte Komponenten-Spezifikationen (Squirl-Cards, Buttons, Dropdowns, Modals, Tab-Bars, Skeletons, Toasts, Notices) und ein Motion-System mit benannten Federn. Jeder Wert ist im Produkt ausgeliefert: Hex-Codes, Federkonstanten, Radien, Easings. Entwickler können diese Datei in den Kontext ihres Agenten einfügen oder als Regeldatei in ihr Repository legen, um Bildschirme „im OA-Stil“ zu generieren. Die gleiche Sprache ist auch als vollständiger Agenten-Skill mit typgeprüften Quellen und als CLI (`npx getopen-design add <component>`) verfügbar.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/OpenLabs-so/oa-design/tree/HEAD

In Ihrer bevorzugten KI fragen

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

Dokumentation

DESIGN-SKILL.md

Die Designsprache von Open Analytics in einer einzigen Datei, geschrieben für KI-Agenten und die Menschen, die sie steuern. Jeder Wert hier wird im Produkt ausgeliefert: Hex-Codes, Federkonstanten, Radien, Easings. Fügen Sie diese Datei in den Kontext Ihres Agenten ein (oder legen Sie sie als Regeldatei in Ihr Repository) und bitten Sie um Bildschirme „im OA-Stil“.

Dies ist die kompilierte Einzelfile-Ausgabe, zum Einfügen gemacht. Die gleiche Sprache wird in diesem Repository auch als echter Agenten-Skill ausgeliefert (skills/oa-design/: komponentenspezifische Rezepte mit der vollständigen typgeprüften Quelle eingebettet) und als CLI (npx getopen-design add <component>); bevorzugen Sie diese für Claude Code und andere Skill-bewusste Agenten.

Der Look in einem Satz: weiße Oberflächen mit kontinuierlich gekrümmten Ecken, ruhend auf einer stillen grauen Bühne, gezeichnet in einer einzigen Tinte, bewegt von einer einzigen Feder.


1. Die zehn Regeln

  1. Eine Tinte, alles abgeleitet. Das gesamte neutrale System ist eine Farbe, gemischt mit Transparenz in festen Prozentsätzen. Nie eine zweite Graustufe wählen.
  2. Zwei Schichten, und der Zwischenraum ist die Seite. Oberflächen sind ein weißer Rahmen, der einen vertieften grauen Einsatz hält; Abschnitte sind Platten und der Seitenhintergrund zwischen ihnen ist der einzige Trenner. Keine horizontalen Linien.
  3. Squirl-Formen für Oberflächen, Pillen für Aktionen. Karten erhalten kontinuierlich gekrümmte Ecken; alles Anklickbare, das keine Karte ist, ist eine Pille.
  4. Eine Federfamilie. Sieben benannte Federn decken das gesamte Produkt ab. Erfinden Sie keine achte.
  5. Chrome wartet nie. Layout und Titel werden sofort gerendert; nur Daten wechseln aus einem pixelgenauen Skelett, ankommend durch Unschärfe, nicht durch Aufpoppen.
  6. Gewicht stoppt bei 500. Nichts Fettschrift. Hierarchie kommt von Größe, Farbe und Abstand.
  7. Ein Akzent, an einem Ort verbraucht. Ein einzelnes Blau für primäre Aktionen und die primäre Diagrammlinie; semantische Farben sind Texttönungen, keine Füllungen.
  8. Zustände erhalten Pillen, Ereignisse beenden sich selbst. Anhaltende Bedingungen werden als nicht entfernbare Streifen gerendert, die genau so lange leben wie der Zustand; einmalige Ergebnisse sind Toasts, die sich allein zurückziehen.
  9. Text ist Teil des Designs. Satzfall; Schaltflächen sagen, was passiert; Fehler nennen die Ursache und den Ausweg, ohne Schuldzuweisung.
  10. Qualitätsniveau, immer. Fokusringe, role="status", aria-hidden Dekorationen, prefers-reduced-motion und kein horizontales Seiten-Scrolling.

2. Tokens

Hell

:root {
  --ink: #292929;

  --background: #f6f6f6;     /* die graue Bühne zwischen den Platten */
  --card: #ffffff;
  --popover: #ffffff;

  /* tintenabgeleitete Neutrale: die Prozentangaben SIND das System */
  --border: color-mix(in srgb, var(--ink) 12%, transparent);
  --input:  color-mix(in srgb, var(--ink) 14%, transparent);
  --accent: color-mix(in srgb, var(--ink) 5%, transparent);  /* Hover-Waschung */
  --muted:  color-mix(in srgb, var(--ink) 5%, transparent);
  --muted-foreground: #6d6d6d;
  --foreground: var(--ink);

  --primary: #305dde;             /* der eine Akzent */
  --primary-foreground: #ffffff;
  --ring: #3ba6f1;

  --secondary: #e9e9e9;           /* flache graue Steuerelemente, kein Rand */
  --secondary-foreground: var(--ink);

  /* semantisch, als TEXT-Tönungen auf hellem Grund (Tailwind-Skala, Zeile 700) */
  --destructive: var(--color-red-500);
  --destructive-foreground: var(--color-red-700);
  --success-foreground: var(--color-emerald-700);
  --warning-foreground: var(--color-amber-700);
  --info-foreground: var(--color-blue-700);

  --chart-1: #296FF0;             /* primäre Diagrammlinie */
  --radius: 0.625rem;
}

Benötigen Sie einen stärkeren Trenner? Erhöhen Sie den Tintenprozentsatz (das Produkt verwendet nur 4, 5, 10, 12, 14). Semantische Farben kommen auf Wörter und 8px Punkte, niemals auf Panel-Füllungen.

Dunkel

Gleiches Rezept, neu eingefärbt, mit zwei systematischen Verschiebungen: Haarstrich-Prozentsätze steigen um 2 Punkte, und semantischer Text bewegt sich von der Zeile 700 zur Zeile 400.

.dark {
  --ink: #ededed;
  --background: #191919;
  --card: #212121;
  --popover: #242424;
  --border: color-mix(in srgb, var(--ink) 14%, transparent);
  --input:  color-mix(in srgb, var(--ink) 16%, transparent);
  --muted-foreground: #969696;
  --secondary: #2e2e2e;
  --primary: #296FF0;
  --destructive-foreground: var(--color-red-400);
  --success-foreground: var(--color-emerald-400);
}

Radius

Eine Basis, multipliziert; niemals ein maßgeschneiderter Radius:

--radius: 0.625rem;  /* sm ×0.6, md ×0.8, lg ×1, xl ×1.4,
                        2xl ×1.8, 3xl ×2.2, 4xl ×2.6 */

rounded-full ist für Pillen reserviert. Squirl-Oberflächen haben ihre eigenen größeren Radien (Abschnitt 4).

Typografie

  • Inter Tight, variabel, Gewichte 300 bis 500, selbst gehostet (Schriftart-CDN brechen Builds; die woff2 im Repository behalten).
  • Geist Mono für code, kbd, samp, pre, Tasten und Schnipsel.
  • Die Gewichtsobergrenze ist die Identität: nichts wird schwerer als 500 gerendert. Hierarchie kommt von Größe, text-foreground/80 vs text-muted-foreground, und Abstand.
  • Überschriften: font-medium tracking-tight; Marketing-Überschriften fügen text-wrap: balance hinzu.
  • Daten: tabular-nums bei jeder Zahl in einer Spalte oder bei Aktualisierung an Ort und Stelle.
  • Standard-UI-Stimme ist 14px; sekundäre Zeilen 12px, mit leading-5/leading-6.

Schatten

Die Erhebung ist binär:

/* ruhende Karte */    box-shadow: 0 1px 2px rgba(0,0,0,0.06);
/* schwebendes Chrome */ box-shadow: 0 1px 2px rgba(0,0,0,0.08),
                                  0 8px 24px rgba(0,0,0,0.08);

Hintergrund-Disziplin

body ist weiß (Überlauf zeigt den Körper; Grau, das hinter einem weißen Bildschirm hervorlugt, liest sich wie eine andere Seite). Bildschirme, die die graue Bühne wollen, malen ihren eigenen Hintergrund. Root erhält overflow-x: clip.


3. Layout

Platten. Abschnitte sind in sich geschlossene Panels; der Seitenhintergrund, der zwischen ihnen sichtbar ist, ist die einzige Grenze. Vertikale Abstände großzügig (gap-12 sm:gap-20 Marketing, gap-6 in der App), seitlicher Abstand enger (px-4 sm:px-6). Geschwister werden durch den gap des Elternteils beabstandet, niemals durch Ränder pro Kind. Kein <hr>, kein border-b zwischen Abschnitten.

Breiten pro Bereich: Marketing 76rem (6.5xl), App-Seiten max-w-6xl, Listen-/Auswahlbildschirme max-w-5xl, Leseflächen ~65ch. Zentriert, mx-auto.

App-Seitenanatomie:

fester Header (h-14) → Container pt-14
  optionale schwebende Pille (fixed top-16, zentriert)
  <main class="px-4 pb-36 pt-8 sm:px-6 bg-white">
    Titelzeile: h1 text-xl font-medium tracking-tight + EIN Steuerelement auf der rechten Seite
    optionale Hinweisstreifen
    Platten: flex flex-col gap-6

Die Titelzeile enthält genau ein Steuerelement. pb-36 hält den Inhalt von der Ansichtsfenstergrenze fern.

Raster: grid gap-3, responsive Spalten (grid-cols-2 sm:grid-cols-4 für Statistiken). Karten teilen sich eine feste Inhaltshöhe und scrollen intern; die Grundlinie des Rasters bricht nie.

Responsive: Design bei 390px und 1280px. Horizontale Paarungen stapeln unter sm: mit der Aktion zuletzt. Breiter Inhalt scrollt in seinem eigenen overflow-x-auto Container; die Seite scrollt niemals seitwärts.

Einstellungen: schmale Registerkartenleiste + Inhalts Spalte von Abschnittspanels; jeder Abschnitt beginnt mit einem Überschriftsblock (Titel + ein grauer Satz, optionale einzelne Aktion auf der rechten Seite). Verlinken Sie tief auf Registerkarten via ?tab=<id>.


4. Komponenten

Die Squirl-Oberfläche

Kontinuierlich gekrümmte Ecken via eines CSS shape() Clip-Pfads, parametrisiert durch zwei Variablen, mit corner-shape: squircle wo unterstützt:

.squircle {
  border-radius: 26px;
  --card-clip-radius: 14px;
  --card-clip-handle: 2.25px;
  clip-path: shape(
    from var(--card-clip-radius) 0px,
    line to calc(100% - var(--card-clip-radius)) 0px,
    curve to 100% var(--card-clip-radius)
      with calc(100% - var(--card-clip-handle)) 0px / 100% var(--card-clip-handle),
    line to 100% calc(100% - var(--card-clip-radius)),
    curve to calc(100% - var(--card-clip-radius)) 100%
      with 100% calc(100% - var(--card-clip-handle)) / calc(100% - var(--card-clip-handle)) 100%,
    line to var(--card-clip-radius) 100%,
    curve to 0px calc(100% - var(--card-clip-radius))
      with var(--card-clip-handle) 100% / 0px calc(100% - var(--card-clip-handle)),
    line to 0px var(--card-clip-radius),
    curve to var(--card-clip-radius) 0px
      with 0px var(--card-clip-handle) / var(--card-clip-handle) 0px,
    close
  );
  corner-shape: squircle;
}
@media (min-width: 640px) {
  .squircle { border-radius: 50px; --card-clip-radius: 20px; --card-clip-handle: 3px; }
}

Die Minikarte

äußere Squirl-Form: bg-card, border, p-1, ruhender Schatten
├── Kopfstreifen (pb-2 pl-3.5 pr-2 pt-1.5):
│     16px gedämpftes Icon + text-sm font-medium text-foreground/80 Titel
│     optionaler Chip auf der Mittellinie des Titels
│     "Alle ansehen ›" (text-xs muted; hover: accent wash, Pfeil gleitet 2px)
└── innere Squirl-Form: bg #f6f6f6, border, rounded-[22px] sm:rounded-[44px],
      FESTE Höhe (h-44 = fünf 32px Zeilen), overflow hidden

Karten wachsen nie mit Daten; längere Listen scrollen innen. Überlauf zeigt einen 24px Chevron-Chip unten rechts, der y:[0,2.5,0] auf und ab wippt (1,4s easeInOut Schleife), ausgeblendet (0.18s, Skalierung 0.7) am Ende des Scrollens. Zeilen: 32px, vollflächige Akzent-Waschung bei Hover, tabular-nums Werte.

Schaltflächen

Pillen, font-medium, physisch gedrückt: active:translate-y-px active:scale-[0.98].

  • primär: Akzentblau mit einer Abschrägung (Hintergrund/Rand farbgemischt in Richtung eines tiefen Indigos, inset 0 1px 0 rgba(255,255,255,0.22) oben, dunkel inset unten); Hover hellt in Richtung reines Primär auf.
  • sekundär: flach --secondary, transparenter Rand, Hover mischt 5% Tinte. Das Arbeitstier.
  • ghost: nur gedämpfter Text. destructive: rote Füllung, nur Bestätigungsschritt.
  • Größen h-9 / h-8 / h-7; App-Chrome läuft meist mit den kleinen.
  • Laden behält das Label und fügt einen 14px Ring-Spinner hinzu (border-2 border-current border-t-transparent); Breite springt nie.
  • focus-visible:ring-[3px] in --ring/50. Niemals entfernt.

Dropdown-Panels (Menüs, Auswahlen, Schalter)

Auslöser-Pille → schwebendes Panel (schwebender Schatten, Rand, weiß, rounded-2xl+), einschwingen bei PANEL (550/38) mit kleinem y/scale-Offset, schnellerer Ausgang. 32px rounded-lg Elemente mit Akzent-Waschung bei Hover; die aktive Hervorhebung ist ein gemeinsames element, das sich bewegt (layoutId oder width/height Federn), niemals umzeichnen pro Element. Schließen bei außerhalb pointerdown und Escape.

Modals

Hintergrund blendet ~0,15s ein; Panel schwingt bei POP (400/26) ein von opacity 0, scale .96, Ausgang bei 380/28. Mehrschritt-Dialoge behalten ein Panel, dessen Höhe zu jedem Schritt gemessener Größe animiert (LAYOUT 550/40 + ResizeObserver), während Schritte durchgleiten (x: ±12px, popLayout, 0.16s easeOut ausgeblendet). Fußzeile: h-12 Streifen, Zurück (sekundär xs) + primär xs, rechts ausgerichtet.

Registerkartenleiste

Die aktive Pille ist ein festes Fenster; Labels gleiten dahinter. Das eingehende Label tritt aus der Bewegungsrichtung bei 110% seiner eigenen Breite ein; das ausgehende verlässt ein festes 130px auf die andere Seite (ein Prozentsatz reicht nicht aus, wenn die Pille in Richtung eines längeren Wortes wächst). Pillenbreite/-höhe folgen dem gemessenen Label auf LAYOUT-Federn. Volle Deckkraft während des gesamten Vorgangs; die Maske erledigt die Arbeit.

Skelette

  1. Chrome wartet nie; nur der Datenbereich ist Skelett.
  2. Pixelgenau: Ein Balken sitzt im gleichen Zeilenhöhen-Slot wie der Text, den er repräsentiert (flex h-6 items-center, das einen h-3 Balken umschließt); der Austausch bewegt nichts.
  3. Daten kommen durch Fokus an: eine einmalige Animation von opacity ~0.4 + blur(4px) zu scharf. Eine Animation, kein Übergang (der Inhalt wird bereits endgültig eingehängt; ein Übergang hat keinen vorherigen Wert). Behalten Sie filter: blur(0) danach bei.

Balken: rounded bg-muted-foreground/15, langsamer Hintergrundpositions-Durchlauf (2s linear unendlich, -1s Startversatz, so dass Balken phasenverschoben sind).

Hinweise, leere Zustände, die schwebende Pille

Hinweisstreifen oberhalb des Inhalts, den er erklärt:

<div class="flex flex-col gap-2 rounded-2xl border border-border bg-card
            px-4 py-3 sm:flex-row sm:items-center sm:justify-between"
     role="status">
  <p class="text-sm leading-6 text-muted-foreground">
    <span class="font-medium text-foreground">Noch keine Ereignisse.</span>
    Wenn das Snippet live ist, durchsuchen Sie Ihre Website und wir erfassen den ersten
    Seitenaufruf innerhalb von Sekunden.
  </p>
  <button class="…secondary pill…">Installation prüfen</button>
</div>

Eine fette Behauptung, ein grauer Satz, eine sekundäre Aktion; stapelt unter sm:; lebt genau so lange wie der Zustand; keine Entfernung.

Schwebende Pille für app-weite anhaltende Zustände: fixed top-16, zentriert, rounded-full bg-card py-1.5 pl-3 pr-4 text-xs font-medium, schwebender Schatten, 8px Statuspunkt (pulsierend bei Dringlichkeit), einschwingend bei BANNER (400/30) von y:-8, Ausgang 0.15s. Die ganze Pille verlinkt dorthin, wo der Zustand aufgelöst wird. Zustandspillen entfernen sich nie selbst; Ereignispillen ziehen sich nach ~6s zurück.

Toasts

Unter 0,35s, Easing cubic-bezier(0.5, 1, 0.89, 1):

  • Erfolg: Puls scale 1 → 1.025 → 0.99 → 1 (0,32s).
  • Fehler: Schütteln x 0 → -3 → 3 → -3 → 0 px (0,28s).

Abwechselnde ungerade/gerade Keyframe-Kopien, so dass Wiederholungen neu starten.


5. Bewegung

NameWertVerwendung für
PANEL550 / 38Dropdowns, Menüs, Boards, Schalter
LAYOUT550 / 40gemessene Höhe/Breite, gleitende Pillen
POP400 / 26Modaleingang
POP_EXIT380 / 28Modalausgang
BANNER400 / 30schwebende Pillen, Seitenbanner
FLICK900 / 50Mikrobewegungen von Icons
CHART300 / 25-30Diagramm-Tooltips, Fadenkreuz

Mikroausblendungen: 0,1s bis 0,18s easeOut. Nichts in App-Chrome tweened länger als 0,2s; wenn es sich langsam anfühlt, verringern Sie die Dämpfung, nicht die Dauer verlängern.

Signaturbewegungen: gemessene Höhenchoreographie (ein konstantes Panel, Schritte durchgleitend), die wandernde Hervorhebung (ein gemeinsames aktives Element, niemals umzeichnen pro Element), Eingangs-/Ausgangsasymmetrie (Ausgänge immer schneller), Hover als nur Farbe (plus höchstens einen 2px Pfeil-Schlitten; Karten heben oder skalieren nie) und höchstens eine winzige Umgebungsschleife pro Bildschirm.

Regeln: AnimatePresence für alles, was ausgehängt wird; respektieren Sie prefers-reduced-motion (Einklappungen auf sichtbar reduzieren, Schleifen stoppen); animieren Sie nie ungemessenes Layout; lesen Sie nie die Wanduhr während des Renderns (abonnieren Sie einen laufenden Store in Minutenblöcken).


6. Landingpages

Gleiche Tokens, s

…

[gekürzt zur Übersetzung]

Verwandte Skills