👪

【Yamada UI】Motionを使って親コンポーネントアクション時に子コンポーネントをアニメーションさせる

2023/12/28に公開

概要

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を書くよりも断然楽にアニメーションを実装できるので、皆さんも使いましょう!

参考

https://yamada-ui.com/ja/components/other/motion
https://www.framer.com/motion/animation/#variants

Discussion