ChakraUI Buttonコンポーネントのレスポンシブ対応


ChakraUIのButtonコンポーネントについて

Buttonコンポーネントのsizepropsはオブジェクトの値を入れられず、単一のstring("lg" | "md" | "sm" | "xs")しか入れることができません。

レスポンシブ対応をするときには現在のブレークポイントを返すchakraUIのhook useBreakpointValueを使うことで実現できます。

レスポンシブ対応を含めたコンポーネントを作成します

button.tsx
import React, { forwardRef } from 'react'
import {
  Button as ChakraButton,
  ButtonProps as ChakraButtonProps,
  useBreakpointValue
} from '@chakra-ui/react'

export type ButtonProps = {
  children: string | React.ReactNode
  // この型指定は恐らくあまりうまくないです  
  sizes?: string | { base: string; md: string } | { base: string; xl: string }
}

export const Button = forwardRef<
  HTMLButtonElement,
  ButtonProps & ChakraButtonProps
>(({ children, sizes, ...props }, ref) => {
  // useBreakpointValueにはオブジェクトか配列を渡せるので、sizesがstringの場合はstring[]にする
  const adjustment = typeof sizes === 'object' ? sizes : [sizes]
  // 'md'はデフォルトブレークポイント
  const buttonSize = useBreakpointValue(adjustment, 'md')

  return (
    <ChakraButton size={buttonSize} ref={ref} {...props}>
      {children}
    </ChakraButton>
  )
})

使うとき

hoge.tsx
import { Button } from '@/components/button'
export const Hoge = () => {
  return (
    <Button sizes={{ base: 'lg', md: 'xl' }}>
    ボタン
    </Button>
)}

注意点

createBreakpointsで独自のブレークポイントを設定しているとき単位をpxにするとuseBreakpointValueの挙動がおかしくなることがあるので、createBreakpointsを使う際は気にする必要があります。

ChakraUIのデフォルトのブレークポイントはemで指定されているので不都合がなければそれを使うか、独自に指定する場合もemで指定してあげると良さそうです。