Chakra Factory

Chakra Factory

Chakra Factory는 어떤 HTML 요소든 JSX style prop을 받을 수 있는 슈퍼차지 컴포넌트로 만들어 주는 도구예요. 스타일 prop을 쉽게 활용하고 싶다면 꼭 알아두면 좋아요.

출처: 문서

본문

개요

Chakra factory는 어떤 HTML 요소로부터든 JSX style prop을 받을 수 있는 슈퍼차지 JSX 컴포넌트를 만드는 방법이에요.

import { chakra } from "@chakra-ui/react"

chakra factory는 JSX 요소로 쓰거나 factory 함수로 쓰는 두 가지 방법으로 사용할 수 있어요.

JSX 요소

Style prop은 컴포넌트에 prop으로 전달할 수 있는 CSS 속성이에요. JSX factory를 쓰면 chakra.<element> 문법으로 style prop을 지원하는 JSX 요소를 만들 수 있어요.

import { chakra } from "@chakra-ui/react"

const Button = ({ children }) => (
  <chakra.button bg="blue.500" color="white" py="2" px="4" rounded="md">
    {children}
  </chakra.button>
)

Factory 함수

chakra 함수를 사용해서 네이티브 요소나 커스텀 컴포넌트를 변환할 수 있어요. 핵심 요건은 컴포넌트가 prop으로 className을 반드시 받아야 한다는 점이에요.

const Link = chakra("a")

function Example() {
  return <Link bg="red.200" href="https://chakra-ui.com" />
}

커스텀 컴포넌트를 쓴 또 다른 예시예요.

import * as RadixScrollArea from "@radix-ui/react-scroll-area"

const ScrollArea = chakra(RadixScrollArea.Root)

function Example() {
  return (
    <ScrollArea>
      <RadixScrollArea.Viewport>
        <div>Hello</div>
      </RadixScrollArea.Viewport>
    </ScrollArea>
  )
}

스타일 붙이기

chakra 함수를 사용해서 컴포넌트에 스타일이나 recipe를 붙일 수 있어요.

const Link = chakra("a", {
  base: {
    bg: "papayawhip",
    color: "red.500",
  },
})

// usage: <Link href="https://chakra-ui.com" />

Recipe 붙이기

컴포넌트에 recipe를 붙이는 예시예요.

const Card = chakra("div", {
  base: {
    shadow: "lg",
    rounded: "lg",
    bg: "white",
  },
  variants: {
    variant: {
      outline: {
        border: "1px solid",
        borderColor: "red.500",
      },
      solid: {
        bg: "red.500",
        color: "white",
      },
    },
  },
})

// usage: <Card variant="outline" />

Prop 전달 (Forwarding props)

기본적으로 chakra factory는 chakra 관련 style prop만 DOM으로 전달되지 않도록 걸러내요. prop 전달을 더 세밀하게 제어하고 싶다면 shouldForwardProp 옵션을 전달하면 돼요.

$로 시작하지 않는 모든 prop을 전달하는 예시예요.

function shouldForwardProp(prop: string) {
  return !prop.startsWith("$")
}

const Component = chakra("div", {}, { shouldForwardProp })

커스텀 prop 전달 로직을 만들려면 @emotion/is-prop-valid 패키지와 Chakra UI의 isValidProperty를 함께 쓰세요.

import { chakra, defaultSystem } from "@chakra-ui/react"
import shouldForwardProp from "@emotion/is-prop-valid"

const { isValidProperty } = defaultSystem

function shouldForwardProp(prop: string, variantKeys: string[]) {
  const chakraSfp = !variantKeys?.includes(prop) && !isValidProperty(prop)
  return shouldForwardProp(prop) || chakraSfp
}

const Component = chakra("div", {}, { shouldForwardProp })

기본 Props

defaultProps 옵션을 사용해서 컴포넌트에 기본 prop을 전달할 수 있어요.

const Button = chakra(
  "button",
  {
    base: {
      bg: "blue.500",
      color: "white",
    },
  },
  { defaultProps: { type: "button" } },
)

다형성 (Polymorphism)

chakra factory로 만든 모든 컴포넌트는 as와 asChild prop을 받아서 실제 DOM 요소를 바꿀 수 있어요.

<Button as="a" href="https://chakra-ui.com">
  Chakra UI
</Button>

또는

<Button asChild>
  <a href="https://chakra-ui.com">Chakra UI</a>
</Button>

Chakra UI에서의 컴포지션에 대해 더 알아보려면 여기를 참고하세요.

더 알아보기 (Learn more)