キカガク プラットフォームブログ

株式会社キカガクのプラットフォームブログです。エンジニアやデザイナー、プロダクトマネージャーなどが記事を書いています。

Chakra UI 小技集

ChakraUI小技集

はじめに

こんにちは、開発事業部ソフトウェアエンジニアの柳澤です。
今年の春からキカガクにジョインしました。

前職ではWebエンジニアとしてプレーンな CSS を書いていましたが、キカガクではスタイリングのために Chakra UI(ReactのUIコンポーネントフレームワーク)を採用しています。
プレーン CSS ユーザーが、 Chakra UI を使う上で躓いたポイントがいくつかあったので、今回小技集としてまとめました。同じ境遇の方の助けになりますと幸いです。

Chakra UI を学ぶ際に、下記の本が大変参考になりました。

zenn.dev

今回はこちらを読んだ上で、特に難しかった項目をピックアップして書いていきたいと思います。

疑似要素・疑似クラス同士を組み合わせる

まず最初に、疑似要素・疑似クラスを組み合わせる書き方です。

Chakra UI では &:hover_hover&:first-of-type_first など、それぞれの疑似要素・クラスの書き方が用意されています。詳細はこちらの公式ページの下の方をご確認下さい。

疑似要素・クラスを扱う際は、このようにオブジェクトとして記載します。

<Button
  backgroundColor="orange"
  _hover={{
    backgroundColor: "yellow",
  }}
/>

しかし、疑似要素・クラス同士を組み合わせて使う時は、入れ子構造にしてあげる必要があります。

<Button
  _before={{
    right: "100%"
  }}
  _hover={{
    _before: { right: "0" } 
  }}
/>

また、疑似要素・クラス内でのレスポンシブ設定は、以下のような書き方になります。

_before={{
  width: { base: '14px', md: '20px', xl: '30px' }
}}

ChakraUI でのホバーアニメーション

以上の疑似要素・クラスの組み合わせを利用すると、このようなホバーアニメーションが自由に作れます。
今回はホバーすると、疑似要素が左から出現するボタンを作成しました。

Sandbox

ソースコード

import { Button, VStack, Text } from "@chakra-ui/react";

export default function App() {
  return (
    <div className="App">
      <VStack padding={"10"} spacing={"10"}>
        <Button
          position="relative"
          backgroundColor="red.200"
          boxShadow="xl"
          overflow="hidden"
          padding="8"
          _before={{
            content: `""`,
            display: "inline-block",
            position: "absolute",
            top: "0",
            width: "100%",
            height: "100%",
            backgroundColor: "red.300",
            transition: "0.5s",
            right: "100%" //最初は隠しておく
          }}
          _hover={{
            _before: { right: "0" } //ホバーしたら出てくる
          }}
        >
          <Text zIndex="1">ホバーアニメーション付きボタン</Text> 
        </Button>
      </VStack>
    </div>
  );
}

ChakraUI での条件分岐:アコーディオン

Chakra UI 内で条件によってスタイルを変えたい時は、以下のように三項演算子を使うと簡単です。

<Box
    background={isRed ? "red" : "blue"}
/>

useStateと組み合わせることで、自在にスタイルを変えることができます。
今回は質問をクリックすると、答えが現れる Q&A アコーディオンを実装しました。

Sandbox

ソースコード

import { Box, Heading, Text, VStack } from "@chakra-ui/react";
import React, { useState } from "react";

type AcoProps = {
  question: string;
  children: React.ReactNode;
};

const Aco = ({ question, children }: AcoProps) => {
  const [isOpen, setIsOpen] = useState<boolean>(false);
  return (
    <Box w={"400px"}>
      <Heading
        bg="cyan.500"
        color="white"
        padding="4"
        cursor="pointer"
        onClick={() => setIsOpen(!isOpen)}
        transition="0.5s"
        _hover={{
          opacity: "0.5"
        }}
      >
        {question}
      </Heading>
      <Box
        maxHeight={isOpen ? "100px" : "0"}
        overflow="hidden"
        transition="0.5s"
      >
        <Text padding="10" bg="cyan.100">
          {children}
        </Text>
      </Box>
    </Box>
  );
};

export default function App() {
  return (
    <div className="App">
      <VStack spacing="6" padding={"10"}>
        <Aco question={"質問1"}>答え1</Aco>
        <Aco question={"質問2"}>答え2</Aco>
        <Aco question={"質問3"}>答え3</Aco>
      </VStack>
    </div>
  );
}

ChakraUI と別ライブラリの併用:スライドショー

別ライブラリとChakraUIを併用するときには、sxという特殊なプロパティが役立ちます。 以下のようにsxプロパティの中に子要素のクラスを書き、スタイルを指定することが出来ます。

<Box sx={{
  ".child_class": {
    color: "red",
    width: "30px",
  }
}}>
  <div className="child_class">子要素</div>
</Box>

今回は使用例として、スライドショーライブラリの react-slick と組み合わせてスライドショーを作りました。 sxプロパティ内に react-slick 特有のクラスを記載することで、ドットや矢印のデザインをカスタマイズすることができます。

Sandbox

ソースコード

import { Box, VStack, HStack, Text } from "@chakra-ui/react";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import dynamic from "next/dynamic";

const Slider = dynamic(() => import("react-slick").then((m) => m.default), {
  ssr: false
});

type SlideProps = {
  title: string;
};

const Slide = ({ title }: SlideProps) => {
  return (
    <HStack
      w="100%"
      h="200px"
      bg="cyan.400"
      border="cyan.700"
      alignContent="center"
      justifyContent="center"
      mx="4"
    >
      <Text color="white" fontWeight="bold">
        {title}
      </Text>
    </HStack>
  );
};

export default function App() {
  const slickSettings = {
    dots: true,
    infinite: true,
    speed: 1000,
    autoplay: true,
    slidesToShow: 3
  };
  return (
    <div className="App">
      <Box m="20">
        <Box
          sx={{
            ".slick-dots": {
              transform: "translateY(1em)"
            },
            ".slick-dots li button": {
              _before: {
                transition: "0.2s",
                content: "''",
                borderRadius: "100%",
                background: "cyan.500"
              }
            },
            ".slick-arrow": {
              backgroundColor: "cyan.500",
              color: "white",
              w: "30px",
              h: "50px",
              transition: "0.2s",
              _hover: {
                backgroundColor: "cyan.500",
                color: "white"
              },
              _focus: {
                backgroundColor: "cyan.500",
                color: "white"
              },
              _before: {
                transition: "0.2s"
              }
            },
            ".slick-prev": {
              left: "-40px",
              _before: {
                content: '"◀"'
              }
            },
            ".slick-next": {
              right: "-40px",
              _before: {
                content: '"▶"'
              }
            }
          }}
        >
          <Slider {...slickSettings}>
            <Slide title={"スライド1"} />
            <Slide title={"スライド2"} />
            <Slide title={"スライド3"} />
            <Slide title={"スライド4"} />
            <Slide title={"スライド5"} />
          </Slider>
        </Box>
      </Box>
    </div>
  );
}

おわりに

以上、小技集でした。Chakra UI 自体コンポーネントが豊富なので、あまり手をかけずにかっこいいデザインを作ることができます。
それでも、もう少しカスタマイズしたい…という時に、お役立て頂けますと幸いです。

Chakra UI の基本的な使い方については、fwywd (フュード) の記事でも取り上げています。ぜひこちらもご覧ください!

fwywd.com

また、キカガク開発事業部では一緒に働いてくださる方を募集しています。
もうすぐ入社して4ヶ月が過ぎますが、毎日楽しく働いております。
もしご興味があれば、採用情報の「話しを聞きに行きたい」ボタンから、カジュアル面談のお申込みをお願いします!

www.wantedly.com www.wantedly.com www.wantedly.com