그동안 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,
},
]);
이런식으로 다른 스타일과 병합하여 쓰면 된다 👍
별거 아닐 수도 있지만 : > 🍀
'개발개발 > Date-project' 카테고리의 다른 글
svg 컴포넌트로 사용하기 (0) | 2025.03.31 |
---|---|
[스토리북] ColorPalette 컬러 팔레트 만들기 (0) | 2025.03.13 |
[스토리북] autodocs 개별 스토리에서 해제하기 (0) | 2025.03.13 |
[스토리북] 에러 TypeError: importers[path] is not a function occurred in monorepo after migrating to v7 (0) | 2025.03.13 |
[date] Storybook + vanilla extract 스타일 적용하기 (0) | 2025.03.11 |