#chakra-ui タグの付いた Snippet

ボタンを押すと滑らかにスクロールしてコンテンツを表示

2021/01/08

export const SomePage = () => {
  const refContents = useRef<HTMLDivElement>();

  const scrollToContents = useCallback(() => {
    refContents.current.scrollIntoView({
      behavior: 'smooth',
      block: 'start',
    });
  }, [refContents]);

  return (
    <VStack w="100%" minH="calc(100vh - 64px)">
      <Center h={16} pb={16}>
        <IconButton
          aria-label="Scroll to Contents section"
          icon={<FaArrowDown />}
          fontSize="2em"
          onClick={scrollToContents}
        />
      </Center>

      {/* 他の内容省略 */}

      <Box backgroundColor="gray.50" minH="16em" px={[0, 8, 16, 24]} ref={refContents}>
        {/* コンテンツ */}
      </Box>
    </VStack>
  );
};

scrollIntoView を使うと、対象の DOM へスクロールできる。

  • behavior: 'smooth' とすると、スムーススクロールでジャンプしてくれる
  • block で要素の先頭・中央・末尾のいずれへジャンプするかを指定できる
  • DOM 要素の参照は ref で取得し useRef を通して保存する。取得した参照は ref.current からアクセスできる
  • IconButton を利用すると、アイコンをボタン要素として利用できる。SVG アイコンであれば fontSize で大きさを指定できる
  • アイコンを利用したリンク要素やボタン要素には、aria-label をつけること。アイコン単独だと可読な文字列がなく、スクリーンリーダーなどに対応できないため。これに限らず a11y は意識していきたい

references

カルーセルでカードを表示する

2021/01/07

import React from 'react';
import { Box } from '@chakra-ui/react';
import Slick, { Settings } from 'react-slick';

import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';

const settings: Settings = {
  dots: true,
  infinite: true,
  centerMode: true,
  slidesToShow: 3,
  autoplay: true,
  speed: 500,
  cssEase: 'ease-out',
  responsive: [
    {
      breakpoint: 992,
      settings: {
        slidesToShow: 2,
      },
    },
    {
      breakpoint: 640,
      settings: {
        slidesToShow: 1,
      },
    },
  ],
};

export const SlickArticles: React.FC = ({ articles }) => (
  <Slick {...settings}>
    {articles.map((a) => (
      <Box key={a.slug} p={[2, 4]}>
        <ArticleCard article={a} />
      </Box>
    ))}
  </Slick>
);

react-slick ライブラリを使えば達成できる。

  • responsive オプションで、タブレットビューやスマホビューにも対応できる。max-width タイプの指定になるので、Chakra で慣れている場合は逆指定になることに注意
  • autoplayinfinite で自動スクロール
  • centerMode を指定すると、左右にカードの一部が表示されるため、無限にあるように見えやすくなる。カードの枚数は slidesToShow で指定
  • エレメントに padding はつかないため、自分でつけてから渡す(ここでは Box でラップしている)
  • エレメントの高さにあった height に自動的になるが、dots ぶんの高さは確保されないので、margin-bottom などで調整する

references

SNSシェアボタンを上スクロール時のみフェードインさせる

2021/01/06

import React, { useState } from 'react';
import { VStack, SlideFade, Box, Icon, Placement, Tooltip } from '@chakra-ui/react';
import { useScrollPosition } from '@n8tb1t/use-scroll-position';
import { TwitterShareButton } from 'react-share';
import { FaTwitter } from 'react-icons/fa';

import { SITE_URL, TWITTER_ID } from '../../../utils/env';

type ShareButtonsLeftFixedProps = {
  urlBlog: string;
  title: string;
};

export const ShareButtonsLeftFixed: React.FC<ShareButtonsLeftFixedProps> = ({ title, urlBlog }) => {
  const [showShareButtons, setShowShareButtons] = useState(true);

  useScrollPosition(({ prevPos, currPos }) => {
    const visible = currPos.y > prevPos.y;
    setShowShareButtons(visible);
  }, []);

  const url = new URL(urlBlog, SITE_URL).toString();

  return (
    <Box
      position="fixed"
      left="calc(50vw - 28em)"
      top="7em"
      visibility={['hidden', 'hidden', 'hidden', 'visible']}
    >
      <SlideFade in={showShareButtons} offsetX="-1em" offsetY={0}>
        <VStack spacing={4} p={4} backgroundColor="gray.50" borderRadius={8}>
          <TwitterShareButton url={url} title={title} via={TWITTER_ID}>
            <Tooltip
              label="Twitterでシェア"
              shouldWrapChildren
              hasArrow
              placement={tooltipPlacement}
            >
              <Icon as={FaTwitter} boxSize={6} fill="gray.400" _hover={{ fill: 'teal.500' }} />
            </Tooltip>
          </TwitterShareButton>

          {/* 以下のボタンは省略 */}
        </VStack>
      </SlideFade>
    </Box>
  );
};
  • 上スクロールを検知するには use-scroll-position を利用する
  • スライドアニメーションのために Chakra-UI の SlideFade を利用する
  • タップすると何が起こるのかを提示するために Chakra-UI の Tooltip を利用する

references

SNSシェアボタンの作成

2021/01/05

import React from 'react';
import { Icon, Placement, Tooltip } from '@chakra-ui/react';
import {
  FacebookShareButton,
  HatenaShareButton,
  LineShareButton,
  PocketShareButton,
  TwitterShareButton,
} from 'react-share';
import { FaFacebook, FaGetPocket, FaLine, FaTwitter } from 'react-icons/fa';
import { SiHatenabookmark } from 'react-icons/si';

import { SITE_URL, TWITTER_ID } from '../../../utils/env';

type ShareButtonsProps = {
  urlBlog: string;
  title: string;
  tooltipPlacement: Placement;
};

export const ShareButtons: React.FC<ShareButtonsProps> = ({ urlBlog, title, tooltipPlacement }) => {
  const url = new URL(urlBlog, SITE_URL).toString();

  return (
    <>
      <TwitterShareButton url={url} title={title} via={TWITTER_ID}>
        <Icon as={FaTwitter} boxSize={6} fill="gray.400" _hover={{ fill: 'teal.500' }} />
      </TwitterShareButton>
      <FacebookShareButton url={url}>
        <Icon as={FaFacebook} boxSize={6} fill="gray.400" _hover={{ fill: 'teal.500' }} />
      </FacebookShareButton>
      <LineShareButton title={title} url={url}>
        <Icon as={FaLine} boxSize={6} fill="gray.400" _hover={{ fill: 'teal.500' }} />
      </LineShareButton>
      <PocketShareButton title={title} url={url}>
        <Icon as={FaGetPocket} boxSize={6} fill="gray.400" _hover={{ fill: 'teal.500' }} />
      </PocketShareButton>
      <HatenaShareButton title={title} url={url}>
        <Icon as={SiHatenabookmark} boxSize={6} fill="gray.400" _hover={{ fill: 'teal.500' }} />
      </HatenaShareButton>
    </>
  );
};

react-share ライブラリを使用する。外部スクリプトの読み込みや、テンプレート文字列の流し込みなど、必要な操作はすべて対応してくれる。

各業者のアイコンについては、今回はトーンを揃えたかったので react-icons の FontAwesome や Simple を利用した。react-share 自身にも各種アイコンは入っているので、それを利用しても OK。

import { FacebookIcon } from 'react-share'; // react-share の組み込み
import { FaFacebook } from 'react-icons/fa'; // react-icons を使う場合

<Icon as={FaTwitter} boxSize={6} fill="gray.400" _hover={{ fill: 'teal.500' }} />;

references

Writings

blogsnippetcourse

Contact

Home©︎ suzukalight