Communitygithub.com

pafelab/stretchy-morph-ui

Verwandelt Web-Oberflächen in geschmeidige Morph-UI, bei der Übergänge auf Federn basieren: sie stauchen, dehnen, überschießen und beruhigen sich – anstatt auf Easing-Kurven zu setzen.

Was ist stretchy-morph-ui?

Diese Skill verwandelt statische Web-UI-Komponenten in lebendige, federnde Oberflächen, bei denen jeder Zustandswechsel wie ein physischer Vorgang wirkt: Ein Tab-Indikator streckt sich wie ein Wurm zum nächsten Tab, eine Schaltfläche schrumpft zu einem Ladekreis und schwillt wieder an, ein Produktbild hebt sich von seiner Karte ab, schrumpft zu einem Chip und fällt in den Warenkorb. Die zentrale Idee ist, dass Dehnung stets eine physikalische Ursache hat – sei es, dass die Ränder einer Komponente zu unterschiedlichen Zeiten ankommen, oder dass sie sich durch Geschwindigkeit verformt. Der Skill enthält eine leistungsfähige Feder-Engine (gedämpfter harmonischer Oszillator), 24 voll funktionsfähige Referenzkomponenten aus einem Showcase, einen UI-Scanner zur Analyse bestehender Projekte, ein Browser-Check-Skript und eine detaillierte Methodik, um völlig neue geschmeidige Komponenten zu entwerfen. Er ist für Claude Code, Cursor und ähnliche KI-Agenten konzipiert und unterstützt Entwickler dabei, Mikrointeraktionen mit bouncigen, elastischen oder klebrigen Effekten zu realisieren – mit besonderem Fokus auf Barrierefreiheit, reduced-motion-Respektierung und robuste Implementierung.

Funktioniert mit✓Claude Code~Codex CLI~Cursor✓Antigravity
npx skills add https://github.com/pafelab/stretchy-morph-ui/tree/HEAD

In Ihrer bevorzugten KI fragen

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

Dokumentation

Geschmeidige Morph-UI

Diese Skill erzeugt Oberflächen, bei denen jeder Zustandswechsel morphiert: Ein Tab-Indikator streckt sich wie ein Wurm auf dem Weg zum nächsten Tab, eine Schaltfläche quetscht sich in einen Ladekreis und schwillt zurück, ein Produktbild hebt sich von seiner Karte ab, schrumpft zu einem Chip und fällt in den Warenkorb. Sie wurde aus dem Bau einer 24-Komponenten-Showcase (in assets/showcase.html) destilliert, inklusive aller Bugs und Designkorrekturen, die dabei aufgetreten sind.

Das Erscheinungsbild basiert auf einer Idee: Dehnung wird durch etwas verursacht. Ein Element verformt sich, weil seine Teile uneins sind (ein Rand kommt vor dem anderen an), weil es sich schnell bewegt (es verlängert sich entlang seines Pfades), weil es zusammengedrückt wird (es wölbt sich in die andere Richtung, um sein Volumen zu erhalten), oder weil es gerade getroffen wurde (es wackelt). Ein zufälliges Wackeln in einer Schleife wirkt billig; Dehnung mit einer Ursache wirkt wie Material.

Schritt 0, jedes Mal: Überprüfen Sie den Code des Benutzers und bestätigen Sie

Bevor Sie etwas bauen oder bearbeiten, finden Sie heraus, was in der eigenen Oberfläche des Benutzers geschmeidig werden kann, und lassen Sie ihn wählen. Details, Bewertungskriterien und Nachrichtenvorlagen finden Sie in references/audit.md; die Kurzfassung:

  1. Finden Sie den Code: eingefügten Code, angehängte Dateien (auf claude.ai, listen Sie /mnt/user-data/uploads auf), das Arbeitsverzeichnis oder Repository, einen Artefakt-Link (lesen Sie ihn mit dem Artefakt-Tool) oder eine Quelle, auf die der Benutzer verweist. Wenn es keine gibt, sagen Sie, wonach Sie gesucht haben, und bieten Sie zwei Wege an: Teilen Sie den Code, oder bauen Sie etwas Neues von Grund auf.
  2. Scannen Sie ihn: python scripts/audit_ui.py <pfade> meldet den Stack, vorhandene Animationen, fehlende Reduced-Motion-Behandlung und Kandidaten pro UI-Kategorie mit datei:zeile, jeweils abgebildet auf eine Showcase-Komponente und Technik.
  3. Lesen Sie jeden Treffer im Kontext und behalten Sie nur echte Kandidaten. Notieren Sie für jeden, wo er ist, was jetzt passiert, den Morph-Satz, den er werden würde, den Aufwand (klein, mittel, groß) und etwaige Risiken (Komponentenbibliothek-Markup, eine vorhandene Animationsbibliothek, ein natives Steuerelement, dessen mobiler Picker verloren ginge, sehr lange Listen).
  4. Priorisieren Sie nach Sichtbarkeit × Häufigkeit × Passgenauigkeit, gruppieren Sie Duplikate (alle Schaltflächen, die eine gemeinsame Button-Klasse verwenden, sind ein Element), begrenzen Sie die Liste auf etwa zehn, und listen Sie alles auf, wovon Sie abraten, mit Begründung.
  5. Fragen Sie nach Bestätigung in der Sprache des Benutzers: die nummerierten Vorschläge, dann eine Frage, die ihn einlädt, Nummern auszuwählen, alle empfohlenen zu nehmen oder zusätzliche Teile einzugeben, die geschmeidig sein sollen und nicht auf der Liste stehen. Verwenden Sie ein tippbares Auswahlwerkzeug, falls die Umgebung eines bietet, andernfalls Klartext. Beenden Sie den Zug damit; nehmen Sie keine Änderungen vor der Antwort vor.
  6. Bauen Sie, was sie gewählt haben, plus alles, was sie hinzugefügt haben, befolgen Sie dann den Workflow und berichten Sie pro Element.

Wenn der Benutzer die gewünschten Teile bereits genannt hat, überprüfen Sie trotzdem: Setzen Sie seine Teile an die erste Stelle, bieten Sie den Rest als optional an und halten Sie die Frage kurz.

Dateien

Alle Pfade sind relativ zum Ordner dieser Skill (dem Ordner, der diese SKILL.md enthält), nicht zum Projekt des Benutzers. Lösen Sie sie gegen den Skill-Ordner auf, wenn Sie sie lesen oder ausführen.

PfadWas es istWann öffnen
assets/stretchy-core.jsDie Feder-Engine plus Hilfsfunktionen (Randpaare, segmentierter Indikator, Volumenskala, gewölbte SVG-Ränder, FLIP-Neuordnung, geworfene Objekte)In jede Seite einfügen, die Sie bauen. Einmal lesen, um die Hilfsfunktionen zu kennen.
assets/starter.htmlSeiten-Grundgerüst: Hell/Dunkel-Tokens, Thai-fähige variable Schriftart, Reduced-Motion-Handhabung, die eingebundene Engine, eine BeispielkomponenteEine neue Seite davon starten
assets/showcase.htmlAlle 24 funktionierenden Komponenten des Originalbaus. Jeder JS-Abschnitt beginnt mit einem Banner wie /* ---------- tabs ---------- */Wenn eine Anfrage zu einer Katalogkomponente passt, grep -n "/\* ---------- " assets/showcase.html und nur diesen Abschnitt plus sein CSS lesen
references/audit.mdWie man den Code des Benutzers findet, scannt, bewertet und priorisiert, sowie die Bestätigungsnachrichtenvorlagen (Thai und Englisch)Bei Schritt 0, jedes Mal
references/techniques.mdDie 11 Dehnungstechniken im Detail, mit Code und AbstimmungswertenBevor Sie etwas bauen, das Sie noch nicht gebaut haben
references/components.mdKatalog: Rezept jeder Komponente, Federwerte und FallstrickeWenn die Anfrage eine Katalogkomponente nennt oder ihr ähnelt
references/new-components.mdWie man eine geschmeidige Version jeder Komponente entwirft, plus 14 ausgearbeitete Designs, die nicht im Showcase sindImmer wenn die Anfrage außerhalb des Katalogs liegt
scripts/audit_ui.pyScanner für den Code des Benutzers: Stack, vorhandene Animationen und geschmeidige Kandidaten mit datei:zeileBei Schritt 0, jedes Mal
scripts/check_page.pyHeadless-Browser-Prüfung: JS-Fehler, seitlicher Überlauf auf Telefon und Desktop, unsichtbare Elemente, die Klicks stehlen, und Kontaktbögen von AnimationsframesNach jedem Bau, bevor Sie etwas übergeben

Wenn eine visuelle Design-Skill verfügbar ist (z.B. frontend-design oder ui-ux-pro-max), lesen Sie sie ebenfalls. Diese Skill entscheidet, wie die Seite aussieht (Palette, Schriftart, Layout); diese hier entscheidet, wie sie sich bewegt. Bewegungspolitur kann eine generisch aussehende Seite nicht retten.

Workflow (nach Bestätigung durch den Benutzer)

  1. Schreiben Sie den Morph-Satz für jede Komponente. "Wenn Auslöser, wird Form A zu Form B, und sie dehnt sich, weil Ursache." Beispiel: "Wenn ein Tab angeklickt wird, bewegt sich der Indikator zu ihm, und er dehnt sich, weil seine Vorderkante steifer ist als seine Hinterkante." Wenn Sie die Ursache nicht ausfüllen können, wählen Sie eine aus der Tabelle unten. Dieser Satz ist das Design; alles andere ist Implementierung.
  2. Wählen Sie die Technik(en) aus der Tabelle. Die meisten Komponenten verwenden eine primäre Dehnung plus ein kleines Rückmeldungswackeln.
  3. Definieren Sie Ruhezustände als Zahlen: Breiten, Höhen, Radien, Positionen, Fortschritt 0 bis 1. Federn animieren Zahlen und Sie schreiben sie in style im onUpdate. CSS-Übergänge behandeln nur Farbe und Deckkraft (und kurze Inhaltsüberblendungen).
  4. Planen Sie den Inhalt. Text und Symbole dürfen nicht umfließen oder gequetscht werden, während der Container morphiert. Geben Sie jedem Inhaltszustand seine eigene Ebene in seiner endgültigen Größe, verankert (normalerweise zentriert), und überblenden Sie: schnell ausblenden (≈150 ms), nach einer Verzögerung von ≈100–150 ms mit leichtem Skalieren oder Weichzeichner einblenden. Das overflow:hidden des Containers gibt den Inhalt frei, während er wächst.
  5. Bauen Sie von assets/starter.html mit der eingebundenen Engine. Schreiben Sie Styles direkt in Feder-Callbacks; lösen Sie niemals ein Framework-Neu-Rendering pro Frame aus.
  6. Barrierefreiheit und Unterbrechungsprüfung (Checkliste unten).
  7. Testen und anschauen. Führen Sie scripts/check_page.py aus, erfassen Sie dann Frame-Kontaktbögen der wichtigen Interaktionen und schauen Sie sie sich tatsächlich an. Die Add-to-Cart-Animation im Originalbau "funktionierte", sah aber billig aus, bis die Frames inspiziert wurden; die Korrekturen befinden sich in "Damit es gut aussieht".

Woher die Dehnung kommt

SituationTechnik (Details in references/techniques.md)Zu sehen in
Etwas bewegt sich zwischen PlätzenRandpaar: zwei Federn für Vorder- und Hinterkante, Vorderkante steif, je nach Richtung getauschtTabs, Karussell-Punkte, Schalter, Auswahlchips, Radio-Punkt, Schrittanzeige, Dropdown-Hervorhebung, Bewertungskapsel, Seitenleisten-Navigation
Ein Container ändert Größe oder FormGeteilte Achsen: separate Federn für Breite, Höhe, Radius mit unterschiedlicher Steifigkeit, sodass eine Achse führtDynamic Island, FAB zu Formular, Modal aus Schaltfläche, Dropdown, Add-to-Cart-Schaltfläche
Etwas wird schnell schmaler oder breiterVolumenerhaltung: Skalieren Sie die andere Achse um die Geschwindigkeit, scaleY = clamp(1 − v/k)Senden-Schaltfläche, Suchfeld, Dropdown-Breite
Etwas bewegt sich schnellGeschwindigkeitsdehnung: Verlängern in Bewegungsrichtung, quer dazu verschmälernSchieberegler-Griff, geworfenes Warenkorb-Element, Karussell-Karten (Schrägstellung), Tooltip
Eine große Fläche bewegt sichAusbeulender Rand: Zeichnen Sie die Fläche als SVG-Pfad, dessen Rand-Kontrollpunkt um −Geschwindigkeit versetzt istSeitenleiste, Bottom Sheet
Ein Teil hängt an einem sich bewegenden TeilNachhinkender Folger: eine weichere Feder jagt der Hauptfeder hinterher; verwenden Sie den Abstand für Neigung oder VersatzSchieberegler-Werte-Blase, Akkordeon-Innentext
Rückmeldung für einen Tipp oder ein EintreffenKick: Geschwindigkeit zu einer Feder hinzufügen, die bei 0 ruht, sie wackelt und beruhigt sichCheckbox, Chips, Warenkorb, Sterne, Abzeichen, Mengenlimit-Schütteln
Klumpen verschmelzen oder teilen sichGoo-Filter: Weichzeichner plus Alpha-Schwelle, scharfe Quelle darüber komponiertGoo-Menü
Ein Element wird zu einem anderen ElementContainer-Transformation: Starten Sie beim Rechteck des Auslösers, federn Sie zum Zielrechteck, überblenden Sie den InhaltModal, FAB, Warenkorb-Wurf
Die Änderung benötigt eine Pause dazwischenSequenzierter Morph durch eine Zwischenform, die Bedeutung trägt (Spinner, Häkchen)Senden-Schaltfläche, Add-to-Cart-Schaltfläche
Ziehen über ein Limit hinaus oder eine Liste wird neu geordnetGummiband (Überscrollen durch ≈3 teilen) und FLIP mit Federn, die die Geschwindigkeit beibehaltenKarussell, Blatt, sortierte Produktliste

Die Engine in einem Absatz

Spring ist ein gedämpfter harmonischer Oszillator, integriert mit semi-implizitem Euler in 8 Unterschritten pro Frame (Frame-Delta auf 1/30 s begrenzt, damit ein Hintergrund-Tab sie nicht explodieren lässt). to(ziel) setzt das Ziel neu ohne die Geschwindigkeit zurückzusetzen, was schnelle Klicks kontinuierlich statt neustartend wirken lässt. set(x) springt ohne Animation, drag(x, v) folgt einem Zeiger, während die Geschwindigkeit aufgezeichnet wird, kick(v) injiziert einen Impuls. Die Dämpfung wird bei jedem Tick mit einem globalen bounce-Faktor multipliziert, sodass ein einziger Steuerelement auf Seitenebene (weich 1.8, hüpfend 1, dehnbar 0.5) jede Komponente live nachstimmt. Unter prefers-reduced-motion: reduce springt to() sofort zum Ziel und feuert onRest sofort, sodass Logik, die auf eine Animation wartet, trotzdem läuft.

Dämpfungsverhältnis ζ = c / (2√k). UI-Zustandsänderungen fühlen sich richtig an bei ζ 0.6–0.8; spielerisches Feedback bei 0.3–0.5; über 1 überschießt nichts. Die Voreinstellungen im gesamten Showcase:

RollekcAnmerkungen
Vorderkante eines Randpaars420–52030–34Kommt zuerst an
Hinterkante140–17017–19Hinkt hinterher, was die Dehnung erzeugt
Container-Breite (Morph)240–32018–24
Container-Höhe (Morph)150–17015–17Langsamer als Breite, sodass sich die Form zuerst seitlich dehnt
Zeiger-Folger (Schieberegler)65042Straff, aber immer noch mit ablesbarer Geschwindigkeit
Nachhinkender Folger (Blase)15011Absichtlich locker
Kick-Feedback380–42012–16Kick mit 6–10
Höhe mit sichtbarem Überschwingen (Akkordeon)21014

Faustregeln

  • Jede Verformung begrenzen. Steuerelemente: Volumenerhaltung innerhalb ±7–15 %. Kleine schnelle Dinge (ein geworfener Chip, ein Schieberegler-Griff): bis zu 35–70 % Dehnung. Größen immer auf ein positives Minimum begrenzen, da eine unterdämpfte Feder unter Null unterschreiten kann.
  • Steifigkeit nach Richtung tauschen. In einem Randpaar bekommt der Rand, der der Bewegungsrichtung zugewandt ist, die steife Feder. Ohne den Tausch dehnt sich der Indikator in eine Richtung korrekt und staucht in die andere.
  • Gegenteiliges Timing auf dem Rückweg. Wenn die Breite beim Öffnen der Höhe voraus ist, lassen Sie die Höhe beim Schließen der Breite voraus sein. Die Form zeichnet dann einen anderen Pfad nach, was sich wie elastisch statt wie ein Zurückspulen liest.
  • Federn für Zustandsänderungen, zeitbasierte Kurven für Pfade, deren Form wichtig ist. Ein geworfenes Objekt braucht einen vorhersagbaren Bogen (quadratische Bézier, Ease-In-Out-Fortschritt, etwa 800 ms). Unabhängige x/y-Federn ergeben wandernde Pfade. Leiten Sie die Dehnung in beiden Fällen aus der Geschwindigkeit von Frame zu Frame ab.
  • Inhalt aufrecht halten. Um etwas entlang einer beliebigen Richtung zu dehnen, ohne sein Bild oder seinen Text zu drehen, verwenden Sie rotate(a) scale(1+s, 1−s·0.45) rotate(−a).
  • Eine kühne Bewegung pro Komponente. Der Rest der Komponente bleibt ruhig: ein Farbwechsel, eine kurze Einblendung.
  • Ruhig im Leerlauf. Nichts wackelt von selbst. Höchstens ein orchestrierter Moment beim Seitenladen (die Showcase öffnet die Insel einmal nach 900 ms).

Damit es gut aussieht (Lehren aus dem Bau)

Die erste Add-to-Cart-Version ließ eine einfarbige Kugel entlang zweier unabhängiger Federn fliegen, schrumpfte die Schaltfläche zu einer leeren violetten Ellipse und quetschte den Warenkorb. Der Benutzer sagte, es sei nicht hübsch. Was es behoben hat, verallgemeinert sich:

  • Bewegen Sie das echte Ding. Klonen Sie das Produktbild, heben Sie es leicht mit einem Schatten an, schrumpfen Sie es dann zu einem runden Chip, der das Bild immer noch zeigt, während es fliegt. Abstrakte Punkte lesen sich wie Debug-Ausgabe.
  • Zwischenformen müssen Bedeutung tragen. Eine geschrumpfte Schaltfläche ist ein leerer Klecks, es sei denn, sie zeigt etwas: einen Spinner, ein Häkchen, das sich selbst zeichnet, eine Zählung. Die Hinzufügen-Schaltfläche wird jetzt zu einem grünen Kreis mit einem Häkchen, dann wächst sie zum − n + Schrittschalter.
  • Subtiles Volumen bei Steuerelementen. Eine ±18 % vertikale Wölbung bei einer Schaltfläche sah aus wie ein pillenförmiges Ei. ±7 % liest sich wie weiches Material.
  • Ankunft braucht einen Empfänger. Das Warenkorb-Symbol neigt sich und kippt, ein Ring pulsiert heraus, das Abzeichen poppt auf. Etwas muss sichtbar fangen, was geworfen wurde.
  • Statusmarken nicht abschneiden. Ein Abzeichen innerhalb einer morphierenden overflow:hidden-Pille wird abgeschnitten; setzen Sie es in einen Wrapper außerhalb des Clips.
  • Informationen nicht wiederholen. Die Warenkorb-Pille zeigte "3 ชิ้น 195 บาท" neben einem Abzeichen mit 3. Sie zeigt jetzt nur noch die Gesamtsumme.
  • Illustrationen mit festem Seitenverhältnis zeichnen. Prozentual positionierte CSS-Formen innerhalb einer Kachel dehnen sich, wenn die Kachel breiter wird. Verwenden Sie ein Inline-SVG mit einer viewBox, zentriert in der Kachel.

Barrierefreiheit und Robustheits-Checkliste

  • Reduced Motion respektieren (die Engine tut es; stellen Sie sicher, dass CSS-Keyframes und -Übergänge ebenfalls in einer prefers-reduced-motion Media Query ausgeschnitten werden).
  • Echte button, input, role="switch", role="tab", role="slider" usw. mit dem richtigen aria-*-Zustand verwenden, aktualisiert im selben Aufruf, der die Animation startet.
  • Inhalt, der durch einen Morph verborgen wird, bekommt inert (und darf keine Klicks abfangen: unsichtbaren Ebenen pointer-events:none geben, dann mit dem sichtbaren Zustand wieder einschalten).
  • Fokus absichtlich verschieben, wenn das fokussierte Steuerelement in einem Morph verschwindet: zum Ersatz-Steuerelement, zurück zum Auslöser, nachdem ein Dialog geschlossen wurde, und erst, nachdem das Element wieder sichtbar ist (ein visibility:hidden-Element kann nicht fokussiert werden).

Verwandte Skills