ss-motion について
ss-motion は、React JSX に framer-motion の動きを適用するスキルです。動きの種または名称付きモーションを選び、プロジェクトのライブラリにあるレシピを使い、モーション軽減などの制約に従います。
主な機能
- 01説明を五つのモーションシードに対応付け
- 02用途に応じたモーションの提案
- 03モーションライブラリの名称付き動作の利用
- 04ホバー、押下、表示時の状況に対応
- 05モーション軽減とアニメーション制約の遵守
活用シーン
- 01ボタンの押下フィードバック選定
- 02ダイアログやメニューの表示アニメーション設定
- 03リスト、ローディング状態、状態切り替えへの動き追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bitjaru/ styleseed --skill ss-motionインストール後、Claude Code で/ss-motionを入力して読み込まれたか確認します。
詳細
このワークフローの前に、セッションごとに1回だけ実行する更新の事前確認に従ってください。
モーションシードの適用
レジストリを優先するアーティファクト境界
.styleseed/project.json と .styleseed/artifacts/index.json が存在する場合は、まず要求されたアーティファクト ID を解決し、その後 .styleseed/bundles/<artifact-id>.md と .styleseed/manifests/<artifact-id>.json のみを読み取ってください。レジストリがあるプロジェクトでは、グローバルなレガシーバンドルにフォールバックしないでください。レガシープロジェクトでは、レジストリが存在しない場合に限り .styleseed/effective-rules.md を使用できます。
使用しない場合
- framer-motion の一般的なドキュメントや学習には → framer-motion のサイトを使用してください
- React 以外のモーション(CSS のみのトランジション、GSAP)には — このスキルの対象は
motion.XJSX のみです - スクロールに連動するタイムラインやパララックス全般には — このスキルの対象外です(コンポーネントごとの シード/動作を扱います)。ただし、これらはマーケティング/ランディング/ブランドページでは許可されます(DESIGN-LANGUAGE §43 シネマティック層)。その場合は、このスキルではなくスクロールライブラリを使って実装してください。アプリ/データ画面では 引き続き禁止です。
- 既存の FadeIn/FadeUp/Stagger ラッパーを調整するには —
engine/components/ui/motion.tsxを直接編集してください
雰囲気 → シードの対応
適用する前に、ユーザーのプロンプトを5つのシードのいずれかに変換してください。engine/motion/index.ts の次の対応表を使用します。
| ユーザーが使いそうな表現 | シード |
|---|---|
| 弾む、バネのような、遊び心のある、エネルギッシュな、生き生きとした | Spring |
| 滑らか、シルクのような、流れるような、エレガント、落ち着いた、連続的な | Silk |
| キビキビした、素早い、瞬時の、迷いのない、シャープ、正確 | Snap |
| ふわふわした、穏やかな、無重力のような、夢のような、周囲に溶け込む、漂うような | Float |
| リズミカル、力強い、脈打つ、鼓動、ビート | Pulse |
| 「Toss スタイル」、「Arc スタイル」 | Spring(ブランドのデフォルトに基づく) |
| 「Stripe スタイル」、「Notion スタイル」 | Silk |
| 「Linear スタイル」、「Raycast スタイル」、「Vercel スタイル」 | Snap |
ユーザーがブランド名だけを挙げた場合は、BRAND_DEFAULT_SEED にあるそのブランドのデフォルトシードを使用してください。ユーザーがシード名(spring、silk など)を明示した場合は、その指定をそのまま尊重してください。
推奨モード — ユースケース → モーション(ユーザーが雰囲気ではなく「場面」を説明する場合)
ユーザーが気分ではなく、対象が何であるか(「いいねボタン」、「モーダル」、「読み込み状態」、「フィード内の項目」など)を説明している場合は、ユースケースマップ(engine/motion/library.ts の MOTION_BY_USECASE、@engine/motion からエクスポート)から推奨してください。
| ユースケース | 選ぶもの | 理由 |
|---|---|---|
| 主要ボタン/CTA の押下 | spring · press | 触覚的で自信のある反応 — 押下時には「沈み込む」ような動きが必要です |
| モーダル/ダイアログ/シートの表示 | silk · entrance | 滑らかです。重要な内容や破壊的な操作の内容は、決してバウンドさせないでください |
| ドロップダウン/ポップオーバー/メニュー | snap · entrance | 即座で正確です。頻繁に使う UI は待たせないでください |
| トースト/インライン通知 | spring · entrance | 小さく親しみやすい登場で、操作を妨げません |
| リスト/フィード項目の表示 | stagger-cascade | 順序を穏やかに演出します |
| 特徴紹介/マーケティングカードのホバー | tilt-3d | コンテンツの少ないマーケティング画面では、奥行きや華やかさを加えても問題ありません |
| ダッシュボード/データカードのホバー | snap · hover | 控えめに持ち上げるだけにして、情報量の多い UI を落ち着かせます |
| いいね/お気に入り/リアクション | like-burst | タップに応える、お祝いのような単発アニメーションです |
| ライブ/オンライン/録画中のドット | pulse-beat | ループする鼓動で「稼働中」を表します |
| 読み込み/スケルトン | shimmer | 落ち着いた方向性のある進行表示です |
| 成功/確認 | pop-in | 「完了」を小さくポジティブに伝えます |
| トグル/タブ/セグメントの切り替え | toggle-flip | 個性があり、切り替えだと分かりやすい動きです |
| ページ/ルートのトランジション | silk · entrance | 滑らかで控えめ、邪魔になりません |
| 数字/残高/KPI/価格の表示 | なし | 表示内容はアニメーションさせないでください — すぐに読み取れる必要があります |
次の2つのアンチルールは表より優先されます(異なる選択をする場合は、その理由を明示してください)。
- 製品ごとにシードは1つだけです。 プロジェクトですでにシードが使われている場合は、それに合わせてください。2つ目の個性を持ち込まないでください。
- 表示内容を遅らせないでください。 残高、価格、検索結果をアニメーションで表示しないでください。モーションは操作の手がかりのためのものであり、コンテンツのためのものではありません。
名前付きモーションキーワード(特徴的な動き)
シードは、フェードやスケールの「個性」(動きの印象)を設定します。engine/motion/library.ts にあるモーションライブラリは、特徴的な動きを追加します。フリップ、カーテンワイプ、モーフなど、それぞれに固有のキーワードが付いています。ユーザーが汎用的な印象ではなく、具体的で認識しやすい動きを求めている場合は、キーワードを優先してください。
engine/motion/library.ts(@engine/motion から MOTION_LIBRARY/MOTION_BY_KEY としてエクスポート)は、唯一の信頼できる情報源です。各キーワードには、実行可能な独自の snippet が含まれています。スニペットはここから取得してください。パラメーターを手書きしてはいけません。
| キーワード | 動き | ユーザーが次のような動きを求めているときに使用 |
|---|---|---|
toggle-flip | 3D Y 軸カードフリップ | スイッチ/トグルで 2 つの面を切り替える |
toggle-slide | スライドスタックの切り替え | 現在の値がスライドアウトし、次の値がスライドインする |
toggle-morph | ピル ⇄ 円のモーフィング | トグル操作でコントロールの形状を変える |
toggle-curtain | 上から下への clip-path ワイプ | カーテンのようにパネルを表示する |
reveal-blur | blur(12px)→0 のフォーカスイン | コンテンツに焦点が合うように引き寄せる |
reveal-rise | マスクされた clip-path によるテキストの上昇 | 見出し/テキストをせり上がるように表示する |
reveal-unfold | 上端を起点にした scaleY | アコーディオン/パネルを展開する |
pop-in | 0 からのスプリングオーバーシュート | バッジ/チェックマークを弾むように表示する |
press-squish | 縮小+傾斜 | タップ時にボタンを弾力のある、触感的な印象にする |
tap-ripple | タップ位置から広がる放射状の波紋 | Material スタイルの押下フィードバック |
pulse-beat | スケールパルスのループ | ライブ/録画/心拍のインジケーター |
wiggle | 素早い水平方向の揺れ | エラー/無効な入力へのフィードバック |
shimmer | スケルトン読み込みのスイープ | 読み込み中のプレースホルダー |
stagger-cascade | 子要素が順番にフェードアップ | リストを 1 項目ずつアニメーション表示する |
キーワードの適用方法:
engine/motion/library.tsで正確なレシピを確認します。一致するkeyのエントリーを見つけ、そのsnippetをそのままコピーします(調整済みで、実行可能です)。- ユーザーの JSX に合わせて要素/コンテンツのみを調整し、トランジション値は維持します。
- キーワードが状態を持つもの(トグル、リップル)の場合は、スニペットに示されている
useStateを配線します。1 回だけのリビールの場合は、keyを更新すると再生されます。 - 一貫性を保ってほかの箇所でも再利用できるよう、適用したキーワードをユーザーに伝え、ほかのキーワードをプレビューしてコピーできる
/motionを案内します。
ユーザーが動きを説明していても、完全に一致するキーワードがない場合は、シードとコンテキストを組み合わせてください。存在しないキーワードをユーザーが指定した場合は、決してキーワードを捏造せず、表にある最も近い実在のキーワードを提案してください。
コンテキストの判定
プロンプトから、次の 5 つのコンテキストのいずれかを推測します。
- 「ホバー時」/「ホバーすると」→
hover - 「押下時」/「タップ時」/「クリック時」→
press - 「表示時」/「マウント時」/「入場時」→
entrance - 「離れるとき」/「閉じるとき」/「退出時」→
exit(<AnimatePresence>が必要です) - 「レイアウト変更時」/「FLIP」/「並べ替え時」→
layout
曖昧な場合は、entrance をデフォルトにします。複数のコンテキストが妥当な場合(例:ボタンで hover と press の両方が必要な場合)は、両方を適用してください。
アプリケーション手順
適用するシード:$0 · コンテキスト:$1 · 対象:$ARGUMENTS
-
対象ファイルを読みます。指定されたパスにあるファイルを読みます(パスが指定されていない場合は、ユーザーにどのファイルか尋ねます)。ユーザーが指している JSX 要素を特定します。通常は
<button>、<div>、<Card>などです。 -
インポートパスを確認します。コンポーネントファイルから次のものをインポートできる必要があります。
"framer-motion"からmotion(およびexitを使う場合はAnimatePresence)"@engine/motion"から選択したシード(@engine/*エイリアスを使用していないプロジェクトでは、engine/motionへの相対パスを使用します)
-
対象タグを
<motion.X>に置き換え、シードのレシピを展開します。// hover example <motion.button {...spring.hover}>Save</motion.button> // press + hover combined <motion.button {...spring.press} {...spring.hover}>Save</motion.button> // entrance (mount) <motion.div {...silk.entrance}>...</motion.div> // exit (requires AnimatePresence wrapper somewhere up the tree) <AnimatePresence> {open && <motion.div {...silk.entrance} {...silk.exit} />} </AnimatePresence> // layout (FLIP) <motion.div {...snap.layout}>...</motion.div> -
パラメーターを直接記述しないでください。シードの値を単一のソースから取得することが重要です。
{ type: "spring", stiffness: 300, damping: 18 }を JSX に直接展開してはいけません。必ずレシピをスプレッド構文で展開します。 -
長時間動作する画面では、
prefers-reduced-motionを尊重してください。単発のインタラクション(ホバー/押下)では、framer-motion がすでに制御します。長時間表示されるページでマウント/終了/レイアウトのシーケンスを使う場合は、@engine/motionからusePrefersReducedMotionとREDUCED_TRANSITIONをインポートし、モーション軽減が有効な場合はトランジションを上書きします。 -
検証します。ファイルを読み直し、JSX が引き続き解析できることを確認します(括弧が対応していること、motion タグが閉じられていること、
exitを使った場合はAnimatePresenceがあること)。 -
適用したシードとコンテキストをユーザーに伝え、次に試せる関連コンテキストを 1 つ提案します(「クリックできる感じにするために、
pressも適用しますか?」など)。
ユーザーの指定が曖昧な場合のデフォルト
- ファイルの指定がない → 「どのファイルですか?」と尋ねます
- 雰囲気を表す言葉がない → 「雰囲気を表す言葉、ブランド名、またはシード名はありますか?」と尋ねます
- 雰囲気が「自然」または「実際のアプリのような感じ」 → 最も安全な 5 種類のシードの 1 つである Silk をデフォルトにします
- 対象の要素が CTA ボタン →
pressも適用します
禁止事項
- 新しいシード名を作らないでください。シードは 5 種類だけです。
- このスキルから
engine/motion/seeds/*.tsを編集しないでください。これらは手作業で調整されています。新しいシードの追加は、別途明示的に依頼された場合に限ります。 - サードパーティ製のアニメーションライブラリ(gsap、anime.js)を導入しないでください。StyleSeed が対象とするのは framer-motion のみです。
- このスキルを使って、スクロール連動、パララックス、または無限アニメーションを追加しないでください。このスキルの対象は、コンポーネント単位のシード/動きです。(DESIGN-LANGUAGE §43 Cinematic tier に従い、マーケティング/ランディング/ブランドページではスクロール連動/パララックス/3D を使用できます。スクロールライブラリを使って直接構築してください。アプリ/データ画面では引き続き禁止です。)スケルトンのパルスを除き、無限ループはすべての画面で引き続き禁止です。