Communitygithub.com

TLucas97/tarcsweb

Hausstil für erklärende Grafiken, die mit mcp__visual__render_ui gezeichnet werden (Diagramme, Abläufe, kleine Diagramme, animierte Erklärungen). Einmal pro Sitzung vor dem ersten erklärenden render_ui-Aufruf lesen. Nicht für Komponenten-Prototypen; diese folgen dem Design, das der Benutzer vorgibt.

Was ist tarcsweb?

Dieses Skill definiert den visuellen Hausstil für erklärende Grafiken, die mit dem `mcp__visual__render_ui`-Tool erstellt werden – darunter Ablaufdiagramme, kleine Diagramme und animierte Erklärungen. Es legt fest, dass das Standbild (der letzte Frame) die Kerninformation eigenständig vermitteln muss, während die Animation lediglich die zeitliche Reihenfolge der Elemente zeigt. Der Stil verwendet einen dunklen Tintenton (`--ink`), einen einzigen grünen Akzent (`--accent`), weißes Hintergrundpapier (immer `#fff`) und feinste Linien anstelle von Schatten. Er ist für Claude Code in Kombination mit dem Render-UI-Plugin optimiert, indem er ein strenges Typografie- und Abstands-Raster vorgibt (z.B. keine Texte unter 16px, Schriftart Atkinson Hyperlegible). Das Layout bevorzugt einen breiten, von links nach rechts gerichteten Fluss mit maximal 5 Knoten pro Zeile. Animationen werden ausschließlich über transform, opacity, filter: blur und stroke-dashoffset gesteuert, mit abgestimmten GSAP- oder CSS-Timings. Zudem bietet das Skill eine Bibliotheksauswahl (GSAP, d3, KaTeX, ELK.js u.a.) und ein vollständiges HTML-Skelett als Startvorlage. Es ist für diejenigen gedacht, die dem KI-Assistenten beibringen wollen, konsistente, lesbare und animierte Visualisierungen zu zeichnen.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TLucas97/tarcsweb/tree/HEAD/mods/visual/skills/visual-explainer

In Ihrer bevorzugten KI fragen

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

Dokumentation

Visueller Erklärer

Das Bild, das der Benutzer sieht, ist der letzte Frame. Der Play-Button spielt die Bewegung einmal ab. Daher muss das Standbild für sich allein erklären; die Bewegung zeigt nur die Reihenfolge der Dinge.

Dies ist der Hausstil: dunkle Tinte, ein grüner Akzent und ruhiges Timing, auf Weiß mit Haarfeinlinien anstelle von Schatten.

Lesbarkeit zuerst

Das Bild wird 1:1 neben Terminaltext von etwa 15px gezeichnet. Alles, was kleiner ist, liest sich schlechter als der Chat darum herum, sodass der Benutzer es nicht lesen kann.

  • Kein Text unter 16px (Code 15px). Wenn es nicht passt, kürzen Sie den Inhalt oder teilen Sie ihn auf zwei Grafiken auf; verkleinern Sie niemals die Schrift.
  • Schriftart: Atkinson Hyperlegible (für Lesbarkeit entwickelt), mit den unten genannten Fallbacks. Textstärke 400, Titel 700.
  • Weniger Dinge pro Bild: etwa 5 Knoten pro Zeile, höchstens zwei Zeilen.

Farben

:root{
  --bg:#fff;          /* immer weiß */
  --ink:#1d2520;      /* primärer Text, Hauptlinien */
  --muted:#5f6561;    /* sekundärer Text, Beschriftungen auf Linien */
  --faint:#9aa19c;    /* inaktive Knoten, hintere/optionale Pfade */
  --line:#e4e4e0;     /* Kartenränder, Trennlinien, Raster */
  --tint:#f4f2ef;     /* seltene Füllung: Code-Chips, hervorgehobene Zeile */
  --accent:#3b7a57;   /* die EINE Farbe: der Pfad, der zählt */
  --bad:#9a4b3c;      /* nur für ein „Nein“ / „blockiert“-Zeichen, niemals dekorativ */
}
body{font:400 18px/1.4 "Atkinson Hyperlegible",Inter,system-ui,sans-serif;color:var(--ink)}
code{font:15px "Intel One Mono",ui-monospace,monospace}
  • Schriftskala: Titel 26px/700, Knotenlabel 18px, Untertitel und Linienlabel 16px. Titel letter-spacing:-.01em. Zahlen erhalten font-variant-numeric:tabular-nums.
  • Linien: Ränder 1px. Verbinder 1.5px, stroke-linecap:round. Nichts dicker als 2px.
  • Radien: Karten 10px, Chips 8px, Token-Pille 999px. Keine anderen Werte.
  • Abstände: 8px-Raster. Innenabstand des Body 24px. Innenabstand der Karte 14px 18px. Abstand zwischen Knoten 96-120px, damit ein Linienlabel Platz hat.
  • Verwendung des Akzents: ein Pfad, ein Rand oder ein Chip. Wenn zwei Dinge grün sind, sollte eines davon nicht sein.

Leinwand

  • Breite = Inhalt + 48px Innenabstand. Typisch 600-1100. Niemals volle Breite „um zu füllen“. Inhalt beginnt oben links.
  • Zeilen: Inhalt Höhe + 48px, geteilt durch 19, aufgerundet. Ein einzeiliger Ablauf ist 9-11 Zeilen; zwei Ebenen 16-20. Maximal 30.
  • Breit und kurz ist besser als hoch. Bevorzugen Sie einen von links nach rechts verlaufenden Ablauf; führen Sie eine zweite Zeile ein, bevor Sie hoch gehen.
  • Der Basisstil ist weiß, 16px padding, box-sizing:border-box, overflow:hidden. Setzen Sie body{padding:24px} und den Hintergrund selbst.

Layout

  • Leserichtung: Titel oben links, dann von links nach rechts, dann von oben nach unten. Die Animation folgt derselben Reihenfolge.
  • Der Titel ist ein einfacher Satz, der die Kernaussage formuliert („Ein Cache-Treffer überspringt die Datenbank“), kein Thema („Caching“).
  • Karten nur für Dinge, die existieren (ein Dienst, eine Tabelle, ein Konto, ein Schritt). Labels, Werte und Notizen sind reiner Text.
  • Verbinder: SVG-Overlay (position:absolute;inset:0;overflow:visible) im selben positionierten Elternelement wie die Knoten. Messen Sie Endpunkte mit getBoundingClientRect(); kodieren Sie niemals Koordinaten fest. Lassen Sie einen Abstand von 8px zwischen Linie und Karte.
  • Pfeilspitzen: ein offener Chevron-Pfad l5 4-5 4 in der Farbe der Linie. Keine gefüllten Dreiecke, keine <marker>-Voreinstellungen.
  • Zuerst gerade Linien. Kurven nur, um etwas herumzuführen: eine kubische, horizontale Tangenten (C midX y1, midX y2, x2 y2).
  • Ein Pfad, der nicht stattfindet: --faint-Farbe, gestrichelt 2 5. Ein blockierter Pfad: dasselbe, plus ein kleines --bad-x in seiner Mitte.
  • Linienlabel zentriert über der Linie in --muted 16px, 2-3 Wörter.
  • Bewegte Daten (eine Anfrage, ein Betrag, eine Nachricht) sind eine kleine dunkle Pille: --ink-Hintergrund, weißer 16px-Text, Radius 999px. Sie endet an dem Ort, an dem sie angekommen ist, sodass das Standbild sie zeigt.
  • Diagramme: eine Achse, 2px-Linie oder dünne Balken, Gitterlinien in --line, die relevante Datenreihe in --accent und der Rest in --faint, direkte Beschriftungen anstelle einer Legende, Werte in Tintenfarbe (niemals in der Farbe der Datenreihe). Wenn eine Zahl der Punkt ist, zeigen Sie die Zahl, kein Diagramm.

Bewegung

  • Jede Szene endet mit einem aussagekräftigen letzten Frame. Keine Ausgänge, keine Schleifen, keine Ausblendungen. Die gesamte Animation endet mindestens 200 ms vor duration_ms.
  • Typische Gesamtdauer 2-4 s. Bleiben Sie unter 6 s, es sei denn, es handelt sich um eine mehrschrittige Geschichte. duration_ms = letztes Ende + 300 ms.
  • Reihenfolge: Titel, dann Knoten in Lesereihenfolge, dann Verbinder zeichnen, dann Beschriftungen, dann bewegtes Token, dann Endzustandsänderung. Ein Ding beginnt, während sich das vorherige beruhigt (Überlappung ~0.1-0.3 s); niemals alle auf einmal, niemals streng nacheinander.
  • Werte:
WasVonDauerEasing (GSAP / cubic-bezier)
Titelopacity 0, y 80.6spower3.out / .16,1,.3,1
Karteopacity 0, y 12, scale .970.8s, Staffelung 0.12sexpo.out / .16,1,.3,1
Verbinder zeichnendashoffset L+40.7s, Staffelung 0.1-0.3spower2.inOut / .65,0,.35,1
Pfeilspitzeopacity 00.2s, wenn Linie endetlinear
Linienlabelopacity 0, y 40.5spower3.out
Token-Wegentlang der Linie1.0spower2.inOut
Wertwechselalt: y -8, blur 3px, out 0.35s; neu: y 8, blur 3px, in 0.5spower2.in / power3.out
  • Animieren Sie nur transform, opacity, filter: blur und SVG stroke-dashoffset.
  • Niemals von scale(0); beginnen Sie bei .97. Kein Bounce, kein Überschwingen, kein elastisches Verhalten. Die einzige Ausnahme: ein kleiner back.out(1.6)-Pop für ein „Nein“-Zeichen.
  • Animieren Sie niemals Text, den der Leser lesen muss, während er sich bewegt; lassen Sie ihn zuerst landen, dann bewegen Sie das nächste Ding.
  • Physische Metapher, wenn es passt: Wenn das Ding ein Brief, eine Rechnung oder eine Karte ist, bewegen Sie es wie das reale Objekt.

Bibliotheken

Wählen Sie die Bibliothek basierend auf dem, was das Bild darstellt, bevor Sie HTML schreiben. Von Hand das nachzubauen, was eine Bibliothek bereits kann (ein Kraftlayout, eine mathematische Formel, Code-Hervorhebung), sieht schlechter aus und geht häufiger kaputt.

Das Bild istVerwenden SieWarum
Karten und Pfeile, ein Ablauf, eine Abfolge von SchrittenHTML-Karten + SVG-Overlay + GSAP-TimelineVolle Kontrolle über den Stil; GSAP ordnet die Schritte
Ein kurzer Auftritt, eine Liste erscheintMotion animate + stagger, oder CSS @keyframesWeniger Code als eine Timeline
Ein Graph mit vielen Knoten, deren Positionen Sie nicht von Hand auswählen könnenelkjs (geschichtetes Layout) oder d3-force, dann in unserem Stil zeichnenLayout-Mathematik ist schwer von Hand richtig hinzubekommen
Ein echtes Diagramm (Achsen, viele Punkte, eine Skala)d3 (Skalen, Achsen, Formen) von Hand gestyltChart.js nur für einen schnellen Balken/Linie; seine Voreinstellungen umgestalten
Mathematik, FormelnKaTeXEchtes mathematisches Setzen
Codehighlight.js mit dem github-Theme, Schriftart 15pxLesbare Farben auf Weiß
Viele Partikel, eine Simulation, Physik<canvas> mit rAF, gesteuert von performance.now()Das DOM ist zu langsam für hunderte Elemente
Etwas 3Dthree.js (ES-Modul + importmap)Nur wenn Tiefe der Punkt ist
Eine „Skizzen“-Ideerough.jsAbsichtlich handgezeichnete Linien

Niemals Mermaid für Erklärer: Sein Standard-Look kämpft gegen diesen Stil. Verwenden Sie stattdessen elkjs für das Layout.

Festgepinnt, alle geprüft auf cdn.jsdelivr.net (Präfix https://cdn.jsdelivr.net/npm/):

Asynchrones Layout (elkjs, Schriftarten, KaTeX): Bauen Sie die Szene, dann starten Sie die Timeline. Der letzte Frame wird bei duration_ms aufgenommen, also muss das Ganze trotzdem rechtzeitig fertig sein.

Tücken:

  • Motion: Der End-Keyframe muss dieselben Transform-Funktionen verwenden wie der Start. ['translateY(12px) scale(.97)','none'] rendert scale(0), also verschwindet das Element. Schreiben Sie 'translateY(0px) scale(1)'.
  • Linien zeichnen: Niemals pathLength="1"; GSAPs Offset-Tween ignoriert es und die Linie erscheint komplett. Messen Sie L=p.getTotalLength(), setzen Sie strokeDasharray:${L} ${L+4}``, strokeDashoffset:L+4 (die +4 versteckt den runden Endpunkt), tween Sie den Offset auf 0. Ein gestrichelter Pfad kann so nicht gezeichnet werden; blenden Sie ihn ein.
  • Fügen Sie gemessene SVG und Labels vor dem Start der Animation ein, und messen Sie, bevor eine Transformation angewendet wird.
  • Skripte am Ende von <body>; laden Sie das CDN-Tag vor dem Inline-Skript.

Niemals

  • Verläufe, Leuchten, Neon, Glas sieht man durchschimmern, schwere oder farbige Schatten.
  • Lila oder mehr als ein Akzent-Farbton. Farbige Hintergründe auf großen Flächen.
  • Emoji- oder Icon-Font-Dekoration. Ein kleines Inline-SVG mit 1.5px Linie, wenn ein Icon wirklich nötig ist.
  • Alles in Boxen. Zentrierte Hero-Karte. Eine Karte in einer Karte.
  • Eine Leinwand, die auf volle Breite gestreckt ist, mit dem Inhalt, der in der Mitte schwebt.
  • Pfeile, die sich kreuzen, Linien, die Karten berühren, Labels, die Linien überlappen.
  • Bildunterschriften, die den Titel wiederholen. Mehr als ~12 Wörter Text innerhalb des Bildes.
  • Text unter 16px oder eine andere Schriftart als die oben genannte in einem Erklärer.

Nach dem Rendern: Lesen Sie das PNG und prüfen Sie: Lücken, Überlappungen, abgeschnittener Text, leere rechte Seite.

Grundgerüst

<style>/* Farben von oben */ h2{font-size:26px;font-weight:700;letter-spacing:-.01em;margin:0 0 32px}
.row{position:relative;display:flex;gap:112px;width:max-content}
.node{padding:14px 18px;border:1px solid var(--line);border-radius:10px}
.node small{display:block;color:var(--muted);font-size:16px}
.hot{border-color:var(--accent)} svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
path{fill:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}</style>
<h2>Ein Cache-Treffer überspringt die Datenbank</h2>
<div class="row" id="row">
  <div class="node" id="a">Anfrage<small>GET /user/42</small></div>
  <div class="node hot" id="b">Cache<small>Redis, 5 Min. TTL</small></div>
  <svg id="s"></svg>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script>
const R=row.getBoundingClientRect();
function link(p,q,color){ const a=p.getBoundingClientRect(),b=q.getBoundingClientRect();
  const y=a.top+a.height/2-R.top, x1=a.right-R.left+8, x2=b.left-R.left-8;
  s.insertAdjacentHTML('beforeend',`<path class="l" stroke="${color}" d="M${x1} ${y}H${x2}"/><path class="h" opacity="0" stroke="${color}" d="M${x2-5} ${y-4}l5 4-5 4"/>`); }
link(a,b,'#3b7a57');
s.querySelectorAll('.l').forEach(p=>{const L=p.getTotalLength();gsap.set(p,{strokeDasharray:`${L} ${L+4}`,strokeDashoffset:L+4})});
gsap.timeline()
  .from('h2',{opacity:0,y:8,duration:.6,ease:'power3.out'})
  .from('.node',{opacity:0,y:12,scale:.97,duration:.8,ease:'expo.out',stagger:.12},.2)
  .to('.l',{strokeDashoffset:0,duration:.7,ease:'power2.inOut'},1)
  .to('.h',{opacity:1,duration:.2},1.6);
</script>

Aufruf mit width ≈ 560, rows: 10, duration_ms: 2200.

Verwandte Skills