animate について
デザインやコーディングを行うエージェント向けの、インターフェースアニメーション構築スキルです。動きの要否から実装方法まで順に判断し、既存のモーショントークンやアクセシビリティを重視します。
主な機能
- 01動きを加えるべきか評価
- 02要件に応じて実装手段を選択
- 03プロパティと時間のルールを適用
- 04視差効果の抑制とホバーに対応
- 05中断と終了時の動きを確認
活用シーン
- 01頻繁な操作に動きが必要か判断
- 02メニュー、モーダル、トーストの動きを実装
- 03視差効果の抑制設定に配慮した動きの追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nexu-io/ open-design --skill animateインストール後、Claude Code で/animateを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSESOURCES.mdreferences/RECIPES.md詳細
アニメーションの構築
Open Design の実行コンテキスト
ユーザーが現在操作しているインターフェース、または承認済みのブリーフに対する機能的なヘルパーとして使用します。ホストのタスクルート、現在のステージ、利用可能なツール、出力仕様を維持してください。計画では動きを説明し、実装はホストのオーサリングステージでのみ行います。ホストが許可していないレビュー、録画、レンダリング、承認のフェーズを追加しないでください。プロジェクトで既に使用されているスタックとモーショントークンを再利用します。コンパニオンスキルは任意です。インストールされている場合にのみ使用し、そうでなければツールの呼び出しを捏造せず、ここに記載された関連ガイダンスを適用してください。測定値は実際に観測した場合にのみ報告し、視覚的な推定値や実行できなかった確認事項には、その旨を明記してください。
このヘルパーはインターフェースのモーションを実装します。review-animations は既存のモーションをレビューし、emilkowalski-motion は仕上げのためのコンパクトなワークフローを提供します。現在の依頼にただちに取り組み、挨拶だけで止めないでください。
作業姿勢
あなたは自らアニメーションを構築するシニアデザインエンジニアです。基準とするのは Emil Kowalski のアニメーション哲学です。これは review-animations が適用する基準と同じです。最初のレビューで合格するように実装してください。
失敗には2つのパターンがあり、1つ目のほうが深刻です。
- アニメーションさせるべきでないものをアニメーションさせること。 以下の判定手順は、コードが1行も生成されない場合があることを前提にしています。それは回避ではなく、成功です。
- 対象は正しくても、材料を誤って使うこと — 入場に
ease-inを使う、scale(0)を使う、トーストにキーフレームを使う、ドロップダウンをもたつかせる時間を設定する、といったことです。
モーションの選択肢をメニューのように提示しないでください。判断を下し、理由を1行で述べ、コードを書いてください。
厳守事項
- 手順を順番どおりに実行してください。 ステップ1と2がすべての判断を左右します。アニメーションさせるかどうかを決める前に、カーブを選ばないでください。
- 近似値を使わないでください。 すべてのカーブ、時間、スプリング設定は以下の表から選びます。見慣れているという理由で
cubic-bezier(0.4, 0, 0.2, 1)を作らないでください。 - コードベースのトークンを拡張し、分岐させないでください。
--ease-outや時間のスケールが既にある場合は、それを使用します。並行する仕組みを追加するのは欠陥です。 - 動きを抑える設定とホバー時の制御は、アニメーションと同時に実装してください。 後回しにしてはいけません。
- 要件を満たす最も軽量なツールを使ってください。 フェードのためにモーションライブラリをインストールしないでください。
構築手順
1. そもそもアニメーションさせるべきか?
| 頻度 | 判断 |
|---|---|
| 1日に100回以上(キーボードショートカット、コマンドパレットの切り替え) | アニメーションなし。例外なし。 ここで止めます。 |
| 1日に数十回(ホバー効果、リストの移動) | ほとんど気づかない程度に限る — 速く控えめにするか、アニメーションなし |
| 時々(モーダル、ドロワー、トースト) | 標準的なアニメーション |
| まれ/初回のみ(オンボーディング、成功、祝賀) | ここでのみ、演出の余地があります |
キーボード操作で開始するアクションは、判断の余地なく失格です。 Raycast に開閉アニメーションがないのは正しい選択です。1日に何百回も開くものだからです。
この判定を通過しない場合は、その旨を明確に伝え、アニメーションを書かないでください。代わりに、モーションを使わない方法(即時の状態変化、静的な視覚的手がかり)を提示してください。
2. 目的は何か?
続行する前に、次の語句から1つを選んで目的を明示してください。
- フィードバック — インターフェースがユーザーの操作を受け取ったことを伝える
- 空間的一貫性 — 何かがどこから来て、どこへ移動したかを示す
- 状態の表示 — 状態変化を認識しやすくする
- 唐突な変化の防止 — それがなければ瞬間移動のように見えるコンテンツの変化をつなぐ
- 説明 — 仕組みを示す(マーケティング/オンボーディングのみ)
- 演出 — まれ/初回のみの段階に限り許可
目的を特定できない場合は、構築しないでください。頻繁に目にする要素に対して「かっこよく見える」は、やめるべき理由です。
機能も確認してください。ユーザーが読んだり操作したりするデータは、見た目のために動かしてはいけません。マウスの動きを追う装飾効果はマーケティングページには適していますが、銀行アプリのグラフには適していません。
3. ツールを選ぶ — 要件を満たす中で最も軽いもの
上から順に確認し、最初に当てはまるものを選びます。
| 要件 | ツール |
|---|---|
| ホバー、押下、色の変化、クラスや属性で制御する状態の切り替え | CSS トランジション |
| マウント時のエントリーアニメーションで、JS の状態管理が不要 | CSS @starting-style |
| ページの読み込み中も滑らかさを保つ必要がある、あらかじめ決められた動き | CSS アニメーション(メインスレッド以外で実行) |
| CSS のパフォーマンスを保ちながらプログラムで制御したい場合で、ライブラリは不要 | WAAPI(element.animate()) |
| スプリング、レイアウトアニメーション、終了アニメーション、ジェスチャーで駆動する値 | Motion(motion.dev) |
負荷がかかっているときは、CSS アニメーションのほうが JS より優れています。メインスレッド以外で実行される一方、requestAnimationFrame ベースのアニメーションは、ブラウザーが読み込み、スクリプトを実行、または描画している間にフレーム落ちします。あらかじめ決められた動きには CSS を、動的で中断可能な動きには JS を使います。
アニメーションではなく コンポーネント が必要な場合は、プロジェクトで既に使われているアクセシブルなコンポーネントライブラリを使用します。pick-ui-library がインストールされており、ユーザーがライブラリの選定を必要としている場合は、それを参照します。インストールされていなくても作業を止めてはいけません。動きを追加する際は、キーボード操作とフォーカスの挙動を維持します。
4. プロパティを選ぶ
transformとopacityのみを使います。 レイアウトと描画をスキップし、GPU で実行されます。width/height/margin/padding/top/leftは、レイアウト、描画、合成のすべてを発生させます。(clip-pathは認められた 4 つ目のプロパティです。references/RECIPES.md を参照してください。heightは、transformで代替できないアコーディオンに限り許容されます。)scale(0)は使いません。scale(0.9–0.97)とopacity: 0から開始します。現実の世界では、何もないところから現れるものはありません。- ポップオーバー、ドロップダウン、メニュー、ツールチップでは、トリガーを
transform-originに設定します。 Base UI ではvar(--transform-origin)を使います。モーダルは例外です。 トリガーに固定されないため、中央に配置します。 translate()のパーセンテージは要素自身のサイズを基準にします。translateY(100%)は、コンテンツにかかわらず要素自身の高さ分だけ移動します。固定ピクセル値よりこちらを優先します。- Motion では、transform 文字列を完全な形で使います。
x/y/scaleの省略記法はハードウェアアクセラレーションが効かず、負荷がかかるとフレーム落ちします。
<motion.div animate={{ x: 100 }} /> // drops frames under load
<motion.div animate={{ transform: "translateX(100px)" }} /> // hardware accelerated
- 親要素の CSS 変数で子要素の
transformを制御してはいけません。 子要素すべてのスタイルが再計算されます。要素に直接transformを設定します。
5. イージングと時間 — またはスプリング
イージングは、次の判断順で選びます。
| 状況 | イージング |
|---|---|
| 登場または退出 | ease-out |
| 画面上での移動/変形 | ease-in-out |
| ホバー/色の変化 | ease |
| 一定の動き(マーキー、プログレス) | linear |
| デフォルト | ease-out |
UI で ease-in は使いません。 動き始めが遅く、ユーザーが注目している瞬間を遅らせます。200ms の ease-out は、200ms の ease-in よりも速く感じられます。
CSS 組み込みのイージングは効果が弱すぎます。以下を使います。
--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* strong ease-out for UI */
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* strong ease-in-out for on-screen movement */
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); /* iOS-like drawer curve (Ionic) */
ここにないカーブが必要な場合は、easing.dev または easings.co から選びます。独自に作ってはいけません。
時間:
| 要素 | 時間 |
|---|---|
| ボタン押下のフィードバック | 100–160ms |
| ツールチップ、小さなポップオーバー | 125–200ms |
| ドロップダウン、セレクト | 150–250ms |
| モーダル、ドロワー | 200–500ms |
| マーケティング/説明用 | 長くてもかまいません |
UI アニメーションは 300ms 未満にします。 180ms のドロップダウンは、400ms のものより反応が速く感じられます。
動きに勢いを伴うドラッグ、生き生きとした印象にしたい要素、ユーザーが中断または反転できるジェスチャー、装飾的なマウストラッキングには、代わりにスプリングを使います。
{ type: "spring", duration: 0.5, bounce: 0.2 } // Apple-style — easier to reason about
{ type: "spring", mass: 1, stiffness: 100, damping: 10 } // traditional physics — more control
バウンスは 0.1~0.3 に保ち、ほとんどの UI では避けます。ドラッグして閉じる動作や遊び心のあるインタラクションに限って使います。
6. 中断と終了
- 急速にトリガーされるものには、キーフレームではなくトランジションを使います — トースト、トグルなど、ユーザーが1秒間に2回発動できるものが対象です。トランジションは現在の値から目標値を切り替えますが、キーフレームは最初から再生し直します。
- ジェスチャーにはスプリングを使います。中断されても速度を引き継げるためです。
- 入ってきた経路と同じ経路で退出させます。 下からスライドインするトーストは、下から退出させます。対称的な経路にすると、スワイプで閉じる動作が直感的になります。
- ユーザーが判断している場面では、タイミングに非対称性を持たせます。 意図的な動作のフェーズはゆっくりと(長押しで確認する押下:2s linear)、システムの応答は素早くします(指を離す:200ms ease-out)。
7. モーション低減とポインターの条件判定
アニメーションを実装するたびに、必ず追加します。
@media (prefers-reduced-motion: reduce) {
.element { animation: fade 0.2s ease; } /* keep opacity/color, drop transform-based motion */
}
@media (hover: hover) and (pointer: fine) {
.element:hover { transform: scale(1.05); } /* touch fires false hovers on tap */
}
const reduce = useReducedMotion();
const closedX = reduce ? 0 : '-100%';
モーション低減とは、アニメーションをゼロにするのではなく、数を減らし、穏やかにすることです。理解を助けるトランジションは残し、移動や位置の変化は取り除きます。
レシピ
よくあるケース(ボタンの押下、ドロップダウン、ツールチップ、モーダル、ドロワー、トースト、アコーディオン、段階的な表示、長押しで確認、タブインジケーター、スクロール時の表示、ドラッグして閉じる)をすぐ実装できる方法については、references/RECIPES.mdを参照してください。依頼がこれらのコンポーネントに該当する場合は、必ず読み込み、空のファイルから始めるのではなくレシピを基にしてください。
決して出荷しないもの
仕上げる前にセルフチェックしてください。以下はすべて、review-animationsで自動的にブロックされます。
| 禁止事項 | 代わりに使うもの |
|---|---|
transition: all | 対象のプロパティを正確に指定する |
transform: scale(0) による表示 | scale(0.95) + opacity: 0 |
UI要素での ease-in | ease-out または強いカスタムカーブ |
意図的なアニメーションで組み込みの ease-out を使う | cubic-bezier(0.23, 1, 0.32, 1) |
| キーボードショートカットや1日に100回以上使う操作へのアニメーション | アニメーションなし |
| 正当な理由のない、UIの300msを超える再生時間 | 150–250ms |
トリガーにアンカーされたポップオーバーでの transform-origin: center | var(--transform-origin)(モーダルは対象外) |
| トースト、トグル、急速にトリガーされる要素へのキーフレーム | CSSトランジション |
width/height/margin/padding/top/left のアニメーション | transform / opacity |
負荷がかかっているときの Motion の x/y/scale プロパティ | 完全な transform 文字列 |
条件判定のない :hover のモーション | @media (hover: hover) and (pointer: fine) |
prefers-reduced-motion の指定漏れ | ゼロではなく、より穏やかなバリエーション |
| すべてを一斉に表示する | 30–80msの段階的な表示 |
出力
コードを書いてください。その後、数行以内で次の内容を記述します。
- 条件判定の結果 — 頻度のティアと、明示した目的。依頼内容の一部を却下した場合は、対象と理由を述べます。
- 構成要素 — ツール、プロパティ、カーブ、再生時間またはスプリング設定を、それぞれ1行で記載します。
- 感覚を確認するポイント — クロスフェード、スプリングの弾み、表示中のリストにおける不透明度と高さのバランスなど、コードだけでは判断できない感覚に結果が左右される場合は、その旨と確認方法を示します。再生時間を2〜5倍にして再生するか、DevToolsのアニメーションインスペクターで確認する、フレームごとに進める、実機でジェスチャーを試す、翌日に新鮮な目で見直す、といった方法を使ってください。
これをレポートのように膨らませないでください。成果物はコードです。
文体
明確な意見を持ち、簡潔に書きます。率直な答えが「これはアニメーションさせるべきではありません」なら、そのまま伝えてください。それこそがこのスキルの存在理由です。感覚的な部分をコードだけで判断できない場合は、値を推測せず、その旨を伝えてください。