복합 Variants
복합 variant는 나열한 variant 값이 모두 맞아떨어질 때만 스타일을 적용해요. "variant: 'outlined' 이면서 color: 'danger'일 때만" 같은 요구사항에 대한 답이에요. 축을 하나만 적어도 괜찮아요. 그럴 때는 다른 모든 variant 뒤에 적용되는 스타일처럼 동작해요.
언제 쓰면 좋나요?
이런 상황에서 복합 variant를 쓰면 좋아요.
- 어떤 스타일이 두 개 이상의 축에 동시에 의존할 때.
- 단일 축 variant로 표현하려면 축을 새로 만들거나 값을 중복으로 정의해야 할 때.
- 컴포넌트 안에
size === 'lg' && color === 'primary' && ...같은 조건문이 늘어나기 시작할 때.
스타일이 단 한 축에만 의존한다면 그냥 variants에 바로 넣어 주세요. 복합 variant는 축의 교차(cross-product)를 위한 도구예요.
패턴: filled / outlined / text × color
디자인 시스템에서 흔히 보이는 패턴이에요. 같은 색상 세트를 세 가지 스타일로 표현해요.
ts
import { ev } from 'emotion-variants';
const button = ev({
base: {
padding: '8px 16px',
borderRadius: 8,
cursor: 'pointer',
border: 'none',
},
variants: {
variant: {
filled: {},
outlined: {
background: 'transparent',
border: '2px solid currentColor',
},
text: {
background: 'transparent',
},
},
color: {
primary: {},
danger: {},
},
},
compoundVariants: [
// Filled
{
variants: {
variant: 'filled',
color: 'primary',
},
style: {
background: '#d36ac2',
color: 'white',
},
},
{
variants: {
variant: 'filled',
color: 'danger',
},
style: {
background: '#dc3545',
color: 'white',
},
},
// Outlined
{
variants: {
variant: 'outlined',
color: 'primary',
},
style: {
color: '#d36ac2',
},
},
{
variants: {
variant: 'outlined',
color: 'danger',
},
style: {
color: '#dc3545',
},
},
// Text
{
variants: {
variant: 'text',
color: 'primary',
},
style: {
color: '#d36ac2',
},
},
{
variants: {
variant: 'text',
color: 'danger',
},
style: {
color: '#dc3545',
},
},
],
defaultVariants: {
variant: 'filled',
color: 'primary',
},
});color variant가 variants에서 빈 객체인 이유는, 스타일이 variant와의 조합에서만 의미를 갖기 때문이에요. 실제 값은 복합 variant 쪽에 들어 있어요.
패턴: size × density 오버라이드
복합 variant가 특정 교차점에서만 기본 속성을 살짝 조정하는 경우도 있어요.
ts
const card = ev({
base: {
padding: 16,
borderRadius: 12,
},
variants: {
size: {
sm: {
padding: 12,
},
md: {
padding: 16,
},
lg: {
padding: 24,
},
},
density: {
comfortable: {},
compact: {},
},
},
compoundVariants: [
{
variants: {
size: 'lg',
density: 'compact',
},
style: {
padding: 16,
},
},
],
});lg + compact 조합에서만 size가 정한 기본 padding을 덮어써요.
순서가 중요해요
각 호출에서 복합 variant는 단순 variant 뒤에, 배열에 적힌 순서대로 추가돼요. 두 복합 variant가 같은 속성을 설정하고 둘 다 일치하면, 뒤에 오는 게 이겨요.
ts
compoundVariants: [
{
variants: {
size: 'lg',
},
style: {
fontWeight: 600,
},
},
{
variants: {
size: 'lg',
color: 'primary',
},
style: {
fontWeight: 700, // 위 항목을 덮어써요
},
},
],TIP
단일 축만 일치시키는 복합 variant를 둘 수도 있어요. 일반 variant와 동작은 같지만, 모든 "조건부" 규칙을 한 곳에 모으고 싶을 때 유용해요.