Vanilla Extract - Recipes

흑우·2023년 12월 17일

vanilla-extract

목록 보기
4/4

Recipes란?

recipes는 Stitches에서 영감을 받은 다양한 변형 css를 생성하는 type-safe한 runtime API입니다.

이렇게 설명하면 이게 무슨 소리인가..? 할지도 모르겠는데요. 사용하는 것을 보시면 금방 감이 오실겁니다.

recipe

// button.css.ts
import { recipe } from '@vanilla-extract/recipes';

export const button = recipe({
  base: {
    borderRadius: 6
  },

  variants: {
    color: {
      neutral: { background: 'whitesmoke' },
      brand: { background: 'blueviolet' },
      accent: { background: 'slateblue' }
    },
    size: {
      small: { padding: 12 },
      medium: { padding: 16 },
      large: { padding: 24 }
    },
    rounded: {
      true: { borderRadius: 999 }
    }
  },

  // Applied when multiple variants are set at once
  compoundVariants: [
    {
      variants: {
        color: 'neutral',
        size: 'large'
      },
      style: {
        background: 'ghostwhite'
      }
    }
  ],

  defaultVariants: {
    color: 'accent',
    size: 'medium'
  }
});

recipe는 다음과 같이 이루어져있는데요. base, variants, compoundVariants, defaultVariants라는 키 값을 받습니다.

base는 기본적으로 적용되는 css 속성값을 말합니다.

variants는 사용자가 직접 선택할 수 있는 다양한 스타일 값을 말합니다.

compoundVariants

compoundVariants는 두 개 이상의 변형 옵션을 결합하여 새로운 변형 옵션을 만드는 기능입니다.

export const button = recipe({
  base: {
    borderRadius: 6,
    outline: 'solid',
  },

  variants: {
    color: {
      orange: { color: 'orange', outlineColor: 'orange' },
      blue: { color: 'blue', outlineColor: 'blue' },
    },
    fill: {
      true: { color: 'white' },
    },
  },

  // Applied when multiple variants are set at once
  compoundVariants: [
    {
      // color 가 orange이고 fill이 true일 때 background는 orange임.
      variants: { color: 'orange', fill: true },
      style: { backgroundColor: 'orange' },
    },
    {
      variants: { color: 'blue', fill: true },
      style: { backgroundColor: 'blue' },
    },
  ],

  defaultVariants: {
    color: 'blue',
    fill: false,
  },
});

 <div className={button({ color: 'orange', fill:true })}>안녕하세요</div>

defaultVariants는 사용자가 해당 속성 값을 선택하지 않으면 자동으로 할당되는 스타일 값을 말합니다.

사용하기

import { button } from './button.css.ts';

document.write(`
  <button class="${button({
    color: 'accent',
    size: 'large',
    rounded: true
  })}">
    Hello world
  </button>
`);

다음과 같이 사용할 수 있습니다. button의 color는 accent로 지정했으니 background: 'slateblue' 속성이 적용되겠네요.

sprinkles 적용하기

import { recipe } from '@vanilla-extract/recipes';
import { reset } from './reset.css.ts';
import { sprinkles } from './sprinkles.css.ts';

export const button = recipe({
  base: [reset, sprinkles({ borderRadius: 'round' })],

  variants: {
    color: {
      neutral: sprinkles({ background: 'neutral' }),
      brand: sprinkles({ background: 'brand' }),
      accent: sprinkles({ background: 'accent' })
    },
    size: {
      small: sprinkles({ padding: 'small' }),
      medium: sprinkles({ padding: 'medium' }),
      large: sprinkles({ padding: 'large' })
    }
  },

  defaultVariants: {
    color: 'accent',
    size: 'medium'
  }
});

저번 글에서 다뤘던 sprinkles를 사용해서 recipe를 정의할 수도 있습니다.

RecipeVariants

recipe의 유형 인터페이스를 활용하는 유틸리티입니다. 이는 인터페이스의 일부로 레시피 값을 허용해야 하는 함수나 구성 요소 props을 입력할 때 유용합니다.

import {
  recipe,
  RecipeVariants
} from '@vanilla-extract/recipes';

export const button = recipe({
  variants: {
    color: {
      neutral: { background: 'whitesmoke' },
      brand: { background: 'blueviolet' },
      accent: { background: 'slateblue' }
    },
    size: {
      small: { padding: 12 },
      medium: { padding: 16 },
      large: { padding: 24 }
    }
  }
});

// Get the type
export type ButtonVariants = RecipeVariants<typeof button>;

// the above will result in a type equivalent to:
export type ButtonVariants = {
  color?: 'neutral' | 'brand' | 'accent';
  size?: 'small' | 'medium' | 'large';
};

정리

  • recipe를 사용해서 복잡한 스타일링 분기처리를 깔끔하게 처리할 수 있습니다.
    • base로 기본 스타일 값을 정의하고
    • variants로 스타일 변형 값을 정의하고
    • defaultVariants로 스타일 변형 값의 기본 값을 정의하고
    • compoundVariants로 2개 이상의 variants를 합쳐서 새로운 스타일 변형을 만들 수 있습니다.

Reference

profile
흑우 모르는 흑우 없제~

0개의 댓글