Skip to content
Docs
dot

dotVariants

stable

CVA 스타일 타입 안전 컴포넌트 변형 빌더 — base, variants, defaultVariants, compoundVariants 지원

Import

import { dotVariants } from '@hua-labs/dot';
import type { VariantProps, DotVariantsConfig } from '@hua-labs/dot';

Functions

dotVariants

CVA(Class Variance Authority)를 대체하는 변형 스타일 팩토리입니다. 클래스 이름 대신 StyleObject를 반환하며, 타입 안전한 변형 시스템을 제공합니다.

Signature

function dotVariants<V extends VariantShape>(
  config: DotVariantsConfig<V>
): DotVariantsFn<V>

Parameters

파라미터타입설명
configDotVariantsConfig<V>변형 설정 오브젝트

DotVariantsConfig

필드타입설명
basestring모든 변형에 공통으로 적용되는 유틸리티 문자열
variantsV변형 축 정의. 각 키는 변형 이름, 값은 { 변형값: 유틸리티문자열 }
defaultVariantsPartial<VariantProps<V>>변형이 지정되지 않았을 때 사용할 기본값
compoundVariantsCompoundVariant<V>[]여러 변형 조건이 동시에 충족될 때 추가로 적용할 스타일

Returns

DotVariantsFn<V>(props?: VariantProps<V>) => StyleObject 형태의 호출 가능한 함수.

Usage

import { dotVariants } from '@hua-labs/dot';
import type { VariantProps } from '@hua-labs/dot';

// 버튼 변형 정의
const buttonStyles = dotVariants({
  base: 'inline-flex items-center justify-center rounded-md font-medium transition-colors',
  variants: {
    variant: {
      default: 'bg-primary-500 text-white hover:bg-primary-600',
      secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
      outline: 'border border-gray-300 bg-white hover:bg-gray-50',
      ghost: 'hover:bg-gray-100',
      destructive: 'bg-red-500 text-white hover:bg-red-600',
    },
    size: {
      sm: 'h-8 px-3 text-xs',
      md: 'h-10 px-4 text-sm',
      lg: 'h-12 px-6 text-base',
    },
  },
  defaultVariants: {
    variant: 'default',
    size: 'md',
  },
});

// 타입 추출
type ButtonVariants = VariantProps<typeof buttonStyles>;

// 사용
buttonStyles();
// base + variant:'default' + size:'md' 적용

buttonStyles({ variant: 'outline' });
// base + variant:'outline' + size:'md' 적용

buttonStyles({ variant: 'secondary', size: 'lg' });
// base + variant:'secondary' + size:'lg' 적용
// compoundVariants — 여러 조건이 동시 충족 시 추가 스타일
const badgeStyles = dotVariants({
  base: 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',
  variants: {
    variant: {
      default: 'bg-primary-500 text-white',
      secondary: 'bg-gray-100 text-gray-800',
      outline: 'border border-gray-300',
    },
    size: {
      sm: 'text-xs px-2 py-0.5',
      lg: 'text-sm px-3 py-1',
    },
  },
  defaultVariants: {
    variant: 'default',
    size: 'sm',
  },
  compoundVariants: [
    // variant가 'outline'이고 size가 'lg'일 때 추가 스타일
    {
      conditions: { variant: 'outline', size: 'lg' },
      dot: 'border-2',
    },
  ],
});

badgeStyles({ variant: 'outline', size: 'lg' });
// base + outline + lg + compoundVariant(border-2) 모두 적용
// React 컴포넌트에 통합
import React from 'react';
import { dotVariants } from '@hua-labs/dot';
import type { VariantProps } from '@hua-labs/dot';

const cardStyles = dotVariants({
  base: 'rounded-xl border bg-white shadow-sm',
  variants: {
    padding: {
      none: '',
      sm: 'p-4',
      md: 'p-6',
      lg: 'p-8',
    },
    elevated: {
      true: 'shadow-lg',
      false: 'shadow-sm',
    },
  },
  defaultVariants: {
    padding: 'md',
    elevated: 'false',
  },
});

type CardProps = VariantProps<typeof cardStyles> & {
  children: React.ReactNode;
};

function Card({ children, padding, elevated }: CardProps) {
  return (
    <div style={cardStyles({ padding, elevated })}>
      {children}
    </div>
  );
}

// 사용
<Card padding="lg" elevated="true">내용</Card>
// boolean 변형
const overlayStyles = dotVariants({
  base: 'fixed inset-0',
  variants: {
    visible: {
      true: 'opacity-100',
      false: 'opacity-0',
    },
    blurred: {
      true: 'backdrop-blur-sm',
      false: '',
    },
  },
  defaultVariants: {
    visible: 'false',
    blurred: 'false',
  },
});

overlayStyles({ visible: 'true', blurred: 'true' });
// { opacity: 1, backdropFilter: 'blur(4px)', ... }

타입 레퍼런스

VariantShape

type VariantShape = Record<string, Record<string, string>>;

DotVariantsConfig

interface DotVariantsConfig<V extends VariantShape> {
  base?: string;
  variants?: V;
  defaultVariants?: { [K in keyof V]?: StringToBoolean<keyof V[K]> };
  compoundVariants?: CompoundVariant<V>[];
}

CompoundVariant

interface CompoundVariant<V extends VariantShape> {
  conditions: { [K in keyof V]?: StringToBoolean<keyof V[K]> };
  dot: string;
}

VariantProps

type VariantProps<V extends VariantShape> = {
  [K in keyof V]?: StringToBoolean<keyof V[K]>;
};

Notes

  • dotVariants()는 클래스 이름이 아닌 StyleObject를 반환합니다. 클래스 이름이 필요한 경우 dotClass()를 사용하세요.
  • Flutter 대상(runtime: 'flutter')은 dotVariants()와 호환되지 않습니다. FlutterRecipe는 중첩 오브젝트 구조로 얕은 병합이 불가능합니다.
  • 변형 스타일은 내부적으로 캐시됩니다. 동일한 유틸리티 문자열을 여러 변형에서 재사용해도 성능 저하가 없습니다.
  • compoundVariants의 조건은 AND 연산입니다. 모든 조건이 충족될 때만 적용됩니다.