본문 바로가기
개발개발/Date-project

[vanilla-extract] Sprinkles 로 스타일 토큰 만들기

by yelimu 2025. 3. 13.

그동안 tailwind CSS 로 4개 정도의 프로젝트를 했었다.

 

이번 프로젝트에서 바닐라 익스트랙트를 처음 사용하게 되었는데, 테일윈드에 절여질대로 절여진지라 유틸리티 형태로 스타일 코드를 작성하고 싶었다.

 

예를 들어 

marginLeft , marginRight => marginX 

marginTop, marginBottom => marginY

이렇게 한 개 이상의 프로퍼티를 하나의 프로퍼티로 설정할 수 있도록 말이다.

테일윈드에서는 mx-[ ], my-[ ] 식으로 제공하고 있다.

 

이럴때 사용할 수 있는것이 vanilla extract에서 제공하고 있는 sprinkles이다 

공식문서에서도 커스텀 유틸리티 클래스를 생성할 수 있다고 설명하고 있다. 

https://vanilla-extract.style/documentation/packages/sprinkles/#sprinkles

 

Sprinkles — vanilla-extract

Zero-runtime Stylesheets-in-TypeScript.

vanilla-extract.style

 


공식문서 예제를 일부 살펴보면 

space 객체에서 프로퍼티(변수)마다 특정 값을 할당하고 

이 변수 값을 defineProperties - properties 에서 css 프로퍼티에 지정한다.

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

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

const responsiveProperties = defineProperties({
	...
  properties: {
    display: ['none', 'flex', 'block', 'inline'],
    flexDirection: ['row', 'column'],
    paddingTop: space,
    paddingBottom: space,
    paddingLeft: space,
    paddingRight: space
    // etc.
  },
  shorthands: {
    padding: [
      'paddingTop',
      'paddingBottom',
      'paddingLeft',
      'paddingRight'
    ],
    paddingX: ['paddingLeft', 'paddingRight'],
    paddingY: ['paddingTop', 'paddingBottom'],
    placeItems: ['justifyContent', 'alignItems']
  }
});

export const sprinkles = createSprinkles(
  responsiveProperties,
);

 

.css.ts 파일에서 아래와 같이 style과 병합하여 사용할 수 있다. 

// styles.css.ts
import { style } from '@vanilla-extract/css';
import { sprinkles } from './sprinkles.css.ts';

export const container = style([
  sprinkles({
    display: 'flex',
    padding: 'small'
  }),
  {
    ':hover': {
      outline: '2px solid currentColor'
    }
  }
]);

그런데 나는 space 객체에서 정의된것처럼 4px, 8px 만 쓰고 싶은게 아니라 모든 숫자값과 "auto" 를 사용하고 싶었다.

그래서 그 방법을 찾아 헤맸는데 gpt는 자꾸 이상한 방법만 알려주는것이다! 

// ❌ 작동하지 않는 코드

const sprinkles = defineProperties({
  properties: {
    paddingTop: { type: "number", default: 0 }, 
    paddingBottom: { type: "number", default: 0 },
    paddingLeft: { type: "number", default: 0 },
    paddingRight: { type: "number", default: 0 },
    ...

 

스토리북에서만 안된걸까?? 페이지에서는 테스트해보지 않았기때문에 모르겠다.

코드에서 아래와 같이 적용했을때, 

const base = style([
  spacingSprinkles({
    paddingX: 12,
    paddingY: 8,
  }),
]);

 

스토리북에서는 아래와 같이 12 라는 값은 paddingLeft 이 쓸 수 없다고 에러를 뱉는다.

[plugin:vite-plugin-vanilla-extract] "paddingLeft" has no value 12. Possible values are "type"

 

그렇다고 모든 숫자값을 갖는 배열을 반복해서 정의하긴 싫었다 ㅠ

// ❌ 불필요한 하드코딩

{
    paddingTop:  [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, "auto"],
    paddingBottom:  [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, "auto"],
    paddingLeft:  [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, "auto"],
    paddingRight:  [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, "auto"],
    marginTop:  [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, "auto"],
    }

 

그런데 생각보다 허무하게 뜻밖의 답을 찾았다.

변수로 처리해주면 되는거였다 ^^ ㅎ 넘 당연한가?!@ 

나는 200까지 4 단위로 배열을 생성해주었다.

const spacingValues = [
  ...Array(51)
    .fill(0)
    .map((_, i) => 0 + i * 4),
  "auto",
];

const sprinkles = defineProperties({
  properties: {
    paddingTop: spacingValues,
    paddingBottom: spacingValues,
    paddingLeft: spacingValues,
    paddingRight: spacingValues,
    marginTop: spacingValues,
    marginBottom: spacingValues,
    marginLeft: spacingValues,
    marginRight: spacingValues,
    placeItems: {
      flexCenter: {
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
      },
    },
  },
  shorthands: {
    paddingX: ["paddingLeft", "paddingRight"],
    paddingY: ["paddingTop", "paddingBottom"],
    marginX: ["marginLeft", "marginRight"],
    marginY: ["marginTop", "marginBottom"],
  },
});

 

또한 placeItem 이라는 속성을 정의하고 요소를 flex + 가운데로 정렬하는 스타일을 flexCenter 라는 값으로 추가해주었다.

const base = style([
  spacingSprinkles({
    paddingX: 12,
    paddingY: 8,
    placeItems: "flexCenter",
  }),
  {
    height: 40,
    borderRadius: 8,
    gap: 4,
  },
]);

이런식으로 다른 스타일과 병합하여 쓰면 된다 👍

 

별거 아닐 수도 있지만 : > 🍀