{"id":"ss-motion","name":"ss-motion","summary":"名前付きのStyleSeedモーションをコンポーネントに適用してください。例えば、5つのパーソナリティシード(Spring/Silk/Snap/Float/Pulse ×入口/出口/ホバー/プレス/レイアウト)か、モーションライブラリのユニークなキーワードムーブ(トグルフリップ、トグルカーテン、リビールブラー、ポップ…","body":"# Motion Seed Applier\n## Registry-first artifact boundary\n\nWhen `.styleseed/project.json` and `.styleseed/artifacts/index.json` exist, resolve the requested artifact ID first, then read only `.styleseed/bundles/<artifact-id>.md` and `.styleseed/manifests/<artifact-id>.json`. Never fall back to the global legacy bundle for a registry project. Legacy projects may use `.styleseed/effective-rules.md` only when no registry exists.\n\n## When NOT to use\n\n- For general framer-motion docs or learning → use the framer-motion site\n- For non-React motion (CSS-only transitions, GSAP) — this skill targets `motion.X` JSX only\n- For full scroll-linked timelines or parallax — out of scope for *this* skill (it does per-component\n  seeds/moves). Note these ARE allowed on a marketing/landing/brand page (DESIGN-LANGUAGE §43\n  Cinematic tier); just build them with a scroll library, not this skill. On app/data surfaces they\n  stay banned.\n- For tweaking the existing FadeIn/FadeUp/Stagger wrappers — edit `engine/components/ui/motion.tsx` directly\n\n## Vibe → Seed mapping\n\nTranslate the user's prompt to one of the five seeds before applying. Use this lookup table from `engine/motion/index.ts`:\n\n| Words the user might say | Seed |\n|---|---|\n| bouncy, springy, playful, energetic, alive | **Spring** |\n| smooth, silky, fluid, elegant, composed, continuous | **Silk** |\n| snappy, quick, instant, decisive, sharp, precise | **Snap** |\n| floaty, gentle, weightless, dreamy, ambient, drifting | **Float** |\n| rhythmic, punchy, pulsing, heartbeat, beat | **Pulse** |\n| \"Toss style\", \"Arc style\" | **Spring** (per brand default) |\n| \"Stripe style\", \"Notion style\" | **Silk** |\n| \"Linear style\", \"Raycast style\", \"Vercel style\" | **Snap** |\n\nIf the user says only a *brand* name, use that brand's default seed from `BRAND_DEFAULT_SEED`. If the user is explicit about a seed name (`spring`, `silk`, etc.), respect it verbatim.\n\n## Recommend mode — use-case → motion (when the user describes the *moment*, not the vibe)\n\nIf the user describes **what the thing is** (\"a like button\", \"a modal\", \"the loading\nstate\", \"items in a feed\") rather than a feeling, recommend from the use-case map\n(`MOTION_BY_USECASE` in `engine/motion/library.ts`, exported from `@engine/motion`):\n\n| Use case | Reach for | Why |\n|---|---|---|\n| Primary button / CTA press | `spring · press` | tactile, confident — the press should \"give\" |\n| Modal / dialog / sheet enter | `silk · entrance` | smooth; never bounce serious/destructive content |\n| Dropdown / popover / menu | `snap · entrance` | instant, precise — frequent UI shouldn't wait |\n| Toast / inline notification | `spring · entrance` | small friendly arrival, non-blocking |\n| List / feed items appearing | `stagger-cascade` | choreograph order, gently |\n| Feature / marketing card hover | `tilt-3d` | depth/flair OK on content-light marketing |\n| Dashboard / data card hover | `snap · hover` | a subtle lift only — keep dense UI calm |\n| Like / favorite / reaction | `like-burst` | a celebratory one-shot; reward the tap |\n| Live / online / recording dot | `pulse-beat` | looping heartbeat = \"alive\" |\n| Loading / skeleton | `shimmer` | calm directional progress |\n| Success / confirmation | `pop-in` | positive little \"done\" |\n| Toggle / tab / segment switch | `toggle-flip` | distinctive, recognizable switch |\n| Page / route transition | `silk · entrance` | smooth, minimal, get out of the way |\n| Number / balance / KPI / price reveal | **none** | don't animate the payload — it must read instantly |\n\n**Two anti-rules override the table** (state them if you deviate):\n1. **One seed per product.** If the project already uses a seed, match it — don't introduce a second personality.\n2. **Never delay the payload.** Don't animate a balance, price, or search result into view; motion is for affordance, not content.\n\n## Named motion keywords (distinctive moves)\n\nSeeds set a *personality* (how a fade/scale feels). The **motion library** in\n`engine/motion/library.ts` adds *distinctive moves* — a flip, a curtain wipe, a\nmorph — each behind a unique keyword. Prefer a keyword when the user wants a\nspecific, recognizable motion rather than a generic feel.\n\n`engine/motion/library.ts` (exported as `MOTION_LIBRARY` / `MOTION_BY_KEY` from\n`@engine/motion`) is the **single source of truth** — every keyword carries its\nown runnable `snippet`. Pull the snippet from there; never hand-write the params.\n\n| Keyword | Move | Say it when the user wants… |\n|---|---|---|\n| `toggle-flip` | 3D Y-axis card flip | a switch/toggle to flip between two faces |\n| `toggle-slide` | slide-stack swap | a value to slide out and the next to slide in |\n| `toggle-morph` | pill ⇄ circle morph | a control to change shape on toggle |\n| `toggle-curtain` | top→bottom clip-path wipe | a panel to reveal like a curtain |\n| `reveal-blur` | blur(12px)→0 focus-in | content to focus-pull into place |\n| `reveal-rise` | masked clip-path text rise | a headline/text to climb into view |\n| `reveal-unfold` | scaleY from top edge | an accordion/panel to unfold |\n| `pop-in` | spring overshoot from 0 | a badge/checkmark to pop in bouncily |\n| `press-squish` | scale-down + skew | a button to feel jelly/tactile on tap |\n| `tap-ripple` | radial ripple from tap | Material-style press feedback |\n| `pulse-beat` | looping scale pulse | a live/recording/heartbeat indicator |\n| `wiggle` | quick horizontal shake | error / invalid-input feedback |\n| `shimmer` | skeleton loading sweep | a loading placeholder |\n| `stagger-cascade` | children fade-up in sequence | a list to animate in one-by-one |\n\n**Applying a keyword:**\n\n1. Read the exact recipe from `engine/motion/library.ts` — find the entry whose\n   `key` matches, copy its `snippet` verbatim (it is calibrated and runnable).\n2. Adapt only the element/content to the user's JSX; keep the transition values.\n3. If the keyword is stateful (toggles, ripple), wire the `useState` shown in the\n   snippet. If it's a one-shot reveal, a `key` bump replays it.\n4. Tell the user the keyword you applied so they can reuse it elsewhere for\n   consistency, and point them at `/motion` to preview/Copy others.\n\nIf the user describes a move but no exact keyword fits, fall back to a seed +\ncontext. If they say a keyword that doesn't exist, suggest the closest real one\nfrom the table — never invent a keyword.\n\n## Context detection\n\nInfer one of the five contexts from the prompt:\n\n- \"on hover\" / \"when hovered\" → `hover`\n- \"on press\" / \"on tap\" / \"on click\" → `press`\n- \"when it appears\" / \"on mount\" / \"entering\" → `entrance`\n- \"when it leaves\" / \"on close\" / \"exiting\" → `exit` (requires `<AnimatePresence>`)\n- \"when layout changes\" / \"FLIP\" / \"rearranging\" → `layout`\n\nIf ambiguous, default to `entrance`. If multiple contexts are reasonable (e.g., a button needs both `hover` and `press`), apply both.\n\n## Application steps\n\nApply seed: **$0** · Context: **$1** · Target: **$ARGUMENTS**\n\n1. **Read the target file** at the path given (or, if no path was given, ask the user which file). Locate the JSX element the user is talking about — usually a `<button>`, `<div>`, `<Card>`, or similar.\n\n2. **Confirm the import paths**. The component file must be able to import:\n   - `motion` (and `AnimatePresence` for `exit`) from `\"framer-motion\"`\n   - the chosen seed from `\"@engine/motion\"` — in a project that doesn't use the `@engine/*` alias, use a relative path to `engine/motion`\n\n3. **Replace the target tag with a `<motion.X>` and spread the seed's recipe**:\n\n   ```tsx\n   // hover example\n   <motion.button {...spring.hover}>Save</motion.button>\n\n   // press + hover combined\n   <motion.button {...spring.press} {...spring.hover}>Save</motion.button>\n\n   // entrance (mount)\n   <motion.div {...silk.entrance}>...</motion.div>\n\n   // exit (requires AnimatePresence wrapper somewhere up the tree)\n   <AnimatePresence>\n     {open && <motion.div {...silk.entrance} {...silk.exit} />}\n   </AnimatePresence>\n\n   // layout (FLIP)\n   <motion.div {...snap.layout}>...</motion.div>\n   ```\n\n4. **Do NOT inline the params**. The whole point of the seed is that the values come from one source. Never expand `{ type: \"spring\", stiffness: 300, damping: 18 }` into the JSX — always spread the recipe.\n\n5. **Respect `prefers-reduced-motion`** in long-running surfaces. For one-off interactions (hover/press), framer-motion already throttles. For mount/exit/layout sequences in a long-lived page, import `usePrefersReducedMotion` and `REDUCED_TRANSITION` from `@engine/motion` and override the transition when reduced motion is on.\n\n6. **Validate** by re-reading the file and confirming the JSX still parses (matching brackets, motion tag closed, AnimatePresence in place if `exit` was used).\n\n7. **Tell the user which seed and context you applied**, and offer one related context they might want next (\"Want `press` too so it feels clickable?\").\n\n## Defaults if the user is vague\n\n- No file given → ask \"which file?\"\n- No vibe word → ask \"any vibe word, brand, or seed name?\"\n- Vibe is \"natural\" or \"feel like a real app\" → default to **Silk** (the safest of the five)\n- Element is a CTA button → also apply `press`\n\n## Forbidden\n\n- Do not invent new seed names. There are exactly five.\n- Do not edit `engine/motion/seeds/*.ts` from this skill — those are calibrated by hand. Add a new seed only via a separate, explicit ask.\n- Do not introduce a third-party animation lib (gsap, anime.js). StyleSeed targets framer-motion exclusively.\n- Do not add scroll-linked, parallax, or infinite animations *via this skill* — it does\n  per-component seeds/moves. (Scroll-linked/parallax/3D ARE allowed on a marketing/landing/brand\n  page per DESIGN-LANGUAGE §43 Cinematic tier — build those directly with a scroll lib; on\n  app/data surfaces they stay forbidden.) Infinite loops remain banned everywhere except skeleton pulse.","author":"@bitjaru","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/bitjaru/styleseed/tree/main/engine/.claude/skills/ss-motion","license":"MIT","category":"document","lang":"en","tokens":2513,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":["Read","Write","Edit","Grep","Glob","Bash"]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":[]}}