Skip to content
Conduit

skill

button-motion

Semantic button motion library — one Web Component runtime, pluggable story-driven recipes (delete, search). React/Vue wrappers, agent-skill compatible.

youwenjiujiu/button-motioncommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/youwenjiujiu/button-motion itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 27, 2026

button-motion

Semantic button motion library — every recipe animates the button's own story instead of a generic bounce or fade. Delete sweeps its label into an open trash bin; Search morphs a magnifier into sunglasses that glance around a growing search field.

License: Apache-2.0 Agent Skills

One zero-dependency Web Component runtime; recipes plug in as pure data (CSS keyframes + SVG). No Figma, no Lottie, no external assets. SSR-safe, Shadow-DOM isolated, respects prefers-reduced-motion.

→ Open the gallery

Recipes

RecipeNarrativeDurationResult state
deleteLid lifts level → broom winds up, sweeps the label away letter-by-letter in one stroke → debris arcs into the bin mouth → returning stroke reveals "Done" → lid drops with a settle bounce. Seam-free loop.4.18 sresult-label
searchMagnifier → search field grows → lens splits into sunglasses (bridge draws in, handle vanishes) → gradient ring spins in → placeholder slides in → idle glance left/right → symmetric collapse.6.5 s—

Planned: send, like, save, add-to-cart, refresh, upload, copy, submit.

Install

npm i button-motion        # or copy core/ + recipes/ into your project

Use

Web Component (any framework)

import "button-motion/recipes/delete.js";   // registers <icon-motion> + the recipe
<button type="button" aria-label="Delete" id="del"
        style="position:relative;width:202px;height:62px">
  <icon-motion id="m" recipe="delete" accent="#CC0033" label="Delete" result-label="Done"
    autoplay="false" loop="false" presentation="inline" aria-hidden="true"
    style="position:absolute;inset:0;overflow:visible"></icon-motion>
</button>
<script>
  del.addEventListener("click", () => m.restart());
  m.addEventListener("motion-complete", () => {/* real delete */});
</script>

React

import { IconMotion } from "button-motion/react";
import "button-motion/recipes/delete.js";

<button aria-label="Delete" onClick={() => ref.current?.restart()}
        style={{ position: "relative", width: 202, height: 62 }}>
  <IconMotion ref={ref} recipe="delete" accent="#CC0033"
    label="Delete" resultLabel="Done" onMotionComplete={onDelete}
    aria-hidden="true" style={{ position: "absolute", inset: 0, overflow: "visible" }} />
</button>

Vue 3

<script setup>
import { IconMotion } from "button-motion/vue";
import "button-motion/recipes/search.js";
</script>
<template>
  <IconMotion recipe="search" label="搜索商品…" autoplay loop />
</template>

Runtime API

KindNames
Attributesrecipe accent light background bar foreground muted shadow label result-label duration autoplay loop paused presentation
Methodsplay() pause() restart() seek(ms) setProgress(0..1)
Eventsmotion-ready motion-play motion-pause motion-seek motion-loop motion-complete
  • Booleans must be explicit when false: autoplay="false".
  • duration rescales the whole timeline — beats are percentage-based, rescaling is safe.
  • recipe can be swapped at runtime; the element rebuilds and re-emits motion-ready.
  • Slot aspect: delete 202 × 62, search 250 × 62 (from each recipe's defaults.hostWidth/Height).

As an Agent Skill

The repo root doubles as a Claude Code skill — clone and go:

git clone https://github.com/youwenjiujiu/button-motion.git ~/.claude/skills/button-motion

Then ask naturally: "give this delete button the delete motion" / "给搜索框加动效". The skill locates the target button, copies the library in, swaps the visual while preserving the real <button> semantics (click handler, focus, aria-label), and wires motion-complete to the real action.

Motion craft rules (why it feels right)

  • One-stroke principle: a primary action travel is a single keyframe pair with a single easing curve — segment chains read as multiple pushes.
  • Contact-coupled coordination: the label starts erasing exactly when the broom foot reaches its last letter, and the erase edge tracks the foot.
  • Anticipation / follow-through / smear live on child elements (the broom arm swings around its foot pivot), never on the travel track.
  • Seam-free loops: every property resolves to its 0 % value by 100 %.
  • transform-box: fill-box discipline: all transform-origin values are bounding-box-relative, pre-converted. Do not edit them.

Authoring a new recipe

  1. Reference material → beat sheet (motion-plan style, percentages).
  2. Author CSS keyframes + SVG in a standalone sample page.
  3. Audit with toolkit/render-range.mjs (frame strips: contact coupling, velocity continuity, seam).
  4. Extract with toolkit/extract-recipe.mjs <fused.js> <name> <hostW> <hostH> recipes/<name>.js.
  5. Add to recipes/index.js, gallery RECIPES, and run npm test (pixel parity + events).

License

Apache-2.0

↑↓ navigate openesc close