Recipes는 컴포넌트의 다양한 상태와 변형을 체계적으로 관리하기 위한 스타일링 API 패턴이다.

  1. base

    • 컴포넌트의 기본 스타일을 정의하는 속성
    • 모든 변형에 공통적으로 적용되는 스타일을 정의
    • CSS 변수를 활용하면 JavaScript를 통한 테마 변경이 용이
  2. variants

    • 컴포넌트의 다양한 변형을 정의하는 속성
    • 크기(size), 색상(color), 상태(state) 등 독립적인 스타일 변형을 그룹화
    • 각 변형은 서로 조합 가능
  3. compoundVariants

    • 여러 variant가 동시에 적용될 때의 특별한 스타일을 정의
    • 복잡한 조건부 스타일링을 선언적으로 처리
    • 조건문 없이도 세밀한 스타일 제어가 가능
  4. defaultVariants

    • 컴포넌트의 기본 variant 값을 지정
    • 명시적 지정이 없을 때 적용될 기본값 설정

예제: 버튼 컴포넌트

import { cva } from '../styled-system/css'
 
const button = cva({
  // 기본 스타일
  base: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    borderRadius: '4px',
    transition: 'all 0.2s'
  },
  
  // 변형 스타일
  variants: {
    visual: {
      solid: { bg: 'blue.500', color: 'white' },
      outline: { borderWidth: '1px', borderColor: 'blue.500', color: 'blue.500' }
    },
    size: {
      sm: { padding: '0.5rem 1rem', fontSize: '14px' },
      md: { padding: '0.75rem 1.5rem', fontSize: '16px' },
      lg: { padding: '1rem 2rem', fontSize: '18px' }
    },
    isDisabled: {
      true: { opacity: 0.5, cursor: 'not-allowed' }
    }
  },
  
  // 복합 변형 스타일
  compoundVariants: [
    {
      visual: 'outline',
      isDisabled: true,
      css: {
        borderStyle: 'dashed'
      }
    }
  ],
  
  // 기본 변형 설정
  defaultVariants: {
    visual: 'solid',
    size: 'md'
  }
})
 
// 사용 예시
const Button = () => (
  <button className={button({ visual: 'outline', size: 'lg', isDisabled: true })}>
    Click me
  </button>
)

이 패턴은 Stitches에서 처음 대중화되었으며, 이후 vanilla-extract, Panda CSS, Chakra UI 등 다양한 스타일링 라이브러리에서 채택되었다. cva(Class Variance Authority)와 tailwind-variants를 통해 Utility-first 접근에도 유용하게 사용되고 있다.

초기 Recipes는 단일 컴포넌트(single slot)에 대한 스타일 변형만을 다루었으나, 복잡한 컴포넌트 구조를 효과적으로 관리하기 위해 여러 하위 요소(multi slot)의 스타일을 동시에 제어할 수 있는 형태로 발전했다.

참고