👪
【Yamada UI】Motionを使って親コンポーネントアクション時に子コンポーネントをアニメーションさせる
概要
YamadaUIのMotionタグを使用した時に、親コンポーネントのホバーやクリック時に子コンポーネントのみの要素をアニメーションさせたい事があったので、やり方をまとめます。
遭遇したこと
ヘッダーのナビゲーションで、ホバーすると以下のように下線をアニメーションしながら出現させたい。
以下のようなコードを書くと、子コンポーネントのMotionをホバーしたときに発火しますが、width
が0なので、ホバーできません。
import { Box, Motion } from "@yamada-ui/react";
const Component = () => {
return (
<Box>
<Button>ナビゲーション</Button>
<Motion background="black" h="1px" w="0" whileHover={{ width: "100%" }} />
</Box>
);
};
親コンポーネントのwhileHover
時に子コンポーネントのスタイルを変更できると上手く行きそうな気がします。
解決法
variants
を使用して、以下のようなコードにすると動きます。
import { Box, Motion } from "@yamada-ui/react";
const Component = () => {
const underlineAnimation = {
initial: { width: "0%" },
animate: { width: "100%" },
};
return (
<Motion initial="initial" whileHover="animate">
<Button>ナビゲーション</Button>
<Motion background="black" h="1px" variants={underlineAnimation} />
</Motion>
);
};
初期状態(initial
)の時は、variants
をpropsで持つコンポーネントに対して、指定されたオブジェクト(ここではunderlineAnimation
)のinitial
を適用させます。
whileHover
などのアクションが起こった場合は、指定されたオブジェクトのanimate
を適用させるといった動きをします。
補足
もし、2つ以上のMotion
があり、別々のアニメーションを行わせたい場合はvariants
で渡すオブジェクトを変えればよいです。
<Motion initial="initial" whileHover="animate">
<Motion variants={animation1} />
<Motion variants={animation2} />
</Motion>
ちなみに、以下のようにpropsで渡す値を変えることで、オブジェクトのプロパティ名を変更することも可能です。
const animation = {
start: { css },
end: { css },
};
...
<Motion initial="start" whileHover="end">
<Motion variants={animation} />
</Motion>
最後に
YamadaUIはframer-motionを使用しているらしいので、アニメーション関係で分からないことがあった場合は、framer-motionのリファレンスを見に行くのも大事だと思いました。
バニラのCSSを書くよりも断然楽にアニメーションを実装できるので、皆さんも使いましょう!
参考
Discussion