Vanilla Extract - Sprinkles

흑우·2023년 12월 17일

vanilla-extract

목록 보기
3/4

Sprinkles란?

스타일 선언을 축약해주는 기능을 지원하는 vanilla-extract 패키지입니다.
Sprinkles는 런타임/컴파일 타임 상관 없이 모두 사용 가능합니다.
.css.ts에서 작성하는 모든 스타일 코드들은 컴파일 타임에서 빌드되는데요. 아래 작성한 sprinkles도 컴파일 타임에 css로 변환됩니다.

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

export const container = sprinkles({
  display: 'flex',
  paddingX: 'small',
  flexDirection: {
    mobile: 'column',
    desktop: 'row'
  },
  background: {
    lightMode: 'blue-50',
    darkMode: 'gray-700'
  }
});

내부족으로 style api를 사용하고 클래스 리스트를 반환하기 때문에 selector로도 사용할 수 있습니다.

export const container = sprinkles({
  padding: 'small'
});

globalStyle(`${container} *`, {
  boxSizing: 'border-box'
});

.css.ts에서 작성하지 않은 스타일은 런타임에 빌드됩니다.

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

const flexDirection =
  Math.random() > 0.5 ? 'column' : 'row';

document.write(`
  <section class="${sprinkles({
    display: 'flex',
    flexDirection
  })}">
    ...
  </section>
`);

defineProperties

defineProperties는 properties, conditions, shorhands라는 키 값을 받습니다.

const space = {
  none: 0,
  small: '4px',
  medium: '8px',
  large: '16px'
  // etc.
};

const colors = {
  blue50: '#eff6ff',
  blue100: '#dbeafe',
  blue200: '#bfdbfe'
  // etc.
};

디자인 시스템에서 정의했거나 미리 적어놓고 사용하고 싶은 스타일을 object literal 형식으로 만들어 놓습니다.

const responsiveProperties = defineProperties({
  conditions: {
    mobile: {},
    tablet: { '@media': 'screen and (min-width: 768px)' },
    desktop: { '@media': 'screen and (min-width: 1024px)' }
  },
  defaultCondition: 'mobile',
  properties: {
    display: ['none', 'block', 'flex'],
    flexDirection: ['row', 'column'],
    padding: space
    // etc.
  }
});

반응형 페이지를 위해 responsiveProperties를 선언하겠습니다.
properties에 padding에는 space를 넣었는데요. 이 것은 sprinkles를 사용할 때 사용할 수 있는 padding의 값으로 0, 4, 8, 16px만 가능하게 한다는 말입니다.
즉, sprinkles에서 사용할 수 있는 display, flexDirection, padding의 값을 일부 값으로 제한한것입니다.

properties

사용할 수 있는 css 속성 값을 정의합니다.

import { defineProperties } from '@vanilla-extract/sprinkles';

const responsiveProperties = defineProperties({
  properties: {
    display: ['none', 'block', 'flex'],
    flexDirection: ['row', 'column'],
    alignItems: [
      'stretch',
      'flex-start',
      'center',
      'flex-end'
    ],
    justifyContent: [
      'stretch',
      'flex-start',
      'center',
      'flex-end'
    ]
    // etc.
  }
});

간단한 매핑은 배열을 사용할 수 있습니다.

import { defineProperties } from '@vanilla-extract/sprinkles';

const responsiveProperties = defineProperties({
  properties: {
    gap: {
      none: 0,
      small: 4,
      medium: 8,
      large: 16
    }
    // etc.
  }
});

의미론적 매핑은 객체를 사용할 수 있습니다.

import { defineProperties } from '@vanilla-extract/sprinkles';
import { vars } from './vars.css.ts';

const responsiveProperties = defineProperties({
  properties: {
    gap: vars.space
    // etc.
  }
});

vanilla-extract에서 제공하는 themes를 사용할 수도 있습니다.

shorthands

shorthands는 축약어를 선언하는 것입니다. paddingX, paddingY 등을 선언하는 데 유용합니다.

import { defineProperties } from '@vanilla-extract/sprinkles';
import { vars } from './vars.css.ts';

const responsiveProperties = defineProperties({
  properties: {
    paddingTop: vars.space,
    paddingBottom: vars.space,
    paddingLeft: vars.space,
    paddingRight: vars.space
  },
  shorthands: {
    padding: [
      'paddingTop',
      'paddingBottom',
      'paddingLeft',
      'paddingRight'
    ],
    paddingX: ['paddingLeft', 'paddingRight'],
    paddingY: ['paddingTop', 'paddingBottom']
  }
});

conditions

conditions 제공된 속성에 대한 미디어/기능/컨테이너 쿼리 집합을 정의합니다.

import { defineProperties } from '@vanilla-extract/sprinkles';

const responsiveProperties = defineProperties({
  conditions: {
    mobile: {},
    tablet: { '@media': 'screen and (min-width: 768px)' },
    desktop: { '@media': 'screen and (min-width: 1024px)' }
  },
  defaultCondition: 'mobile'
  // etc.
});

selectors로 지정할 수도 있습니다.

import { defineProperties } from '@vanilla-extract/sprinkles';

const properties = defineProperties({
  conditions: {
    default: {},
    hover: { selector: '&:hover' },
    focus: { selector: '&:focus' }
  },
  defaultCondition: 'default'
  // etc.
});

defaultCondition

말 그대로 기본 조건을 설정합니다.

import { defineProperties } from '@vanilla-extract/sprinkles';

const responsiveProperties = defineProperties({
  conditions: {
    mobile: {},
    tablet: { '@media': 'screen and (min-width: 768px)' },
    desktop: { '@media': 'screen and (min-width: 1024px)' }
  },
  defaultCondition: 'mobile'
  // etc.
});

만약 조건이 상호 배타적인 경우 배열로 설정할 수 있습니다.

import { defineProperties } from '@vanilla-extract/sprinkles';

const responsiveProperties = defineProperties({
  conditions: {
    lightMode: {
      '@media': '(prefers-color-scheme: light)'
    },
    darkMode: { '@media': '(prefers-color-scheme: dark)' }
  },
  defaultCondition: ['lightMode', 'darkMode']
  // etc.
});

createSprinkles

정의된 속성에 접근하기 위한 함수를 만듭니다.

import {
  defineProperties,
  createSprinkles
} from '@vanilla-extract/sprinkles';

const responsiveProperties = defineProperties({
  /* ... */
});
const unconditionalProperties = defineProperties({
  /* ... */
});
const colorProperties = defineProperties({
  /* ... */
});

export const sprinkles = createSprinkles(
  responsiveProperties,
  unconditionalProperties,
  colorProperties
);

정리

  • sprinkles는 스타일 선언을 축약해주는 기능을 지원합니다.
  • defineProperties를 통해 sprinkles에서 사용할 속성을 정의합니다.
    • properties는 sprinkles에서 사용할 css 속성을 정의합니다.
    • shorthands는 sprinkles에서 사용할 축약어를 정의합니다.
    • conditions는 sprinkles에서 사용할 조건을 정의합니다. (모바일, 테블릿, 데스크탑)
  • createSprinkles를 통해 정의한 속성에 접근할 수 있는 함수를 생성합니다.

Reference

profile
흑우 모르는 흑우 없제~

0개의 댓글