Getting Started

Prerequisites

SVDM is a TypeScript-first library for managing styling variance in design systems and component-based UI projects.

Before you start:

  • Make sure your project is using TypeScript.
  • Install and configure your CSS solution (for example, Tailwind or a utility classes setup).

Once the basics are in place, you can install SVDM:

Bash

pnpm add svdm

If you prefer another package manager, adapt the command to match your environment.

SVDM works best when you:

  • Import the main svd function from the SVDM package.
  • Define a schema describing your variants and their possible values.
  • Use the generated function to produce styles inside your components.

First schema

SVDM revolves around a single function, svd. It takes a configuration object and returns a function that generates styles.

A minimal example:

ts

import { svd } from "svdm";

const buttonVariants = svd({
  variants: {
    variant: {
      primary: "bg-blue-600 text-white",
      secondary: "bg-surface-3 text-foreground",
    },
    size: {
      sm: "px-3 py-1.5 text-sm",
      md: "px-4 py-2 text-base",
    },
  },
  defaultVariants: {
    variant: "primary",
    size: "md",
  },
});

const styles = buttonVariants({
  variant: "secondary",
  size: "sm",
});

TypeScript infers that variant can only be "primary" or "secondary" and that size can only be "sm" or "md". Passing anything else produces a type error.

Using SVDM in a component

In the @workspace/ui library, we use SVDM to drive button variants:

TSX

import { svd, SVDProps } from "svdm";

const buttonVariants = svd({
  variants: {
    variant: {
      primary: {
        className: "bg-brand-10 border-brand-a8",
        textColor: "text-brand-1",
      },
      secondary: {
        className: "bg-primary-2 border-border",
        textColor: "text-primary",
      },
    },
    size: {
      "7": {
        container: "h-7 px-2.5 text-sm font-normal rounded-field",
      },
      "8": {
        container: "h-8 px-3 text-sm font-normal rounded-field",
      },
    },
  },
  defaultVariants: {
    variant: "primary",
    size: "7",
  },
});

type ButtonProps = SVDProps<typeof buttonVariants> &
  React.ButtonHTMLAttributes<HTMLButtonElement>;

export function Button({ variant, size, className, ...props }: ButtonProps) {
  const styling = buttonVariants({ variant, size });
  return (
    <button
      className={cn(
        styling.variant.className,
        styling.variant.textColor,
        styling.size.container,
        className,
      )}
      {...props}
    />
  );
}

This pattern keeps the styling logic in one place and lets TypeScript keep your component props in sync with the SVDM schema.

© 2025 Lingxi Li.

SF