In a shared UI component library, SVDM can power most of the component variants. For example, a button component can use a nested object structure to keep layout and behavior together:
ts
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", }, clear: { className: "bg-clear border-none hover:bg-primary-a3 shadow-none before:bg-clear", 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>;
By returning small configuration objects instead of plain strings, the component can read layout, icon sizing, and loading state styles from a single SVDM schema.
SVDM integrates cleanly with React by separating styling logic from component markup. You define the schema once and reuse it across components:
TSX
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", }, }); type ButtonVariantProps = Parameters<typeof buttonVariants>[0]; type ButtonProps = ButtonVariantProps & 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 your React components lightweight while SVDM manages the styling configuration.
A typography component can use SVDM together with the singleton helper to map
high-level variants onto semantic HTML tags and classes:
ts
import type { ClassValue } from "clsx"; import { svd, singleton, SVDProps } from "svdm"; const AVAILABLE_TAGS = { h1: "h1", h2: "h2", p: "p", } as const; type TypographyVariantDefinition = { tag: keyof typeof AVAILABLE_TAGS; className: ClassValue; }; const typographyVariants = svd({ variants: { variant: singleton<TypographyVariantDefinition>().use({ body: { tag: "p", className: "text-base font-normal text-primary", }, title: { tag: "h1", className: "text-2xl font-normal tracking-tight text-primary", }, note: { tag: "p", className: "text-sm font-normal text-primary-9", }, }), }, defaultVariants: { variant: "body", }, }); type TypographyProps = SVDProps<typeof typographyVariants> & { children: React.ReactNode; };
This pattern keeps the mapping between content roles and typography styles in one place while keeping the component API simple.
In a documentation site that renders MDX, SVDM can be used to theme Markdown
content through a textColorVariants schema:
ts
import { svd } from "svdm"; export const textColorVariants = svd({ variants: { variant: { default: { root: "[&>p]:mb-5 [--md-text-primary:var(--color-primary)]", link: "hover:text-primary-a11 focus-visible:text-primary-a11", listGeneral: "space-y-1", }, description: { root: "[&>p]:mb-1 [--md-text-primary:var(--color-primary-9)]", link: "hover:text-primary focus-visible:text-primary", listGeneral: "space-y-0.5", }, }, size: { base: { paragraph: "text-base", h1: "text-xl", h2: "text-lg", }, sm: { paragraph: "text-sm", h1: "text-lg", h2: "text-base", }, }, }, defaultVariants: { variant: "default", size: "base", }, });
The Markdown renderer calls textColorVariants to compute classes for headings,
paragraphs, and lists, giving consistent styling for all MDX content with a
single configuration.
© 2025 Lingxi Li.
San FranciscoSF