Files
skills/docs/ui/react/react-ui/src/variants/variants.md
2026-05-29 08:20:56 +01:00

2.8 KiB

variants — chassis cva variants entry point

(no submodules)

Purpose

Single canonical entry point for class-variance-authority (cva) used by every chassis component. The chassis re-exports the bare cva / VariantProps here (one of the rare exceptions to "never re-export external deps for convenience" per CLAUDE.md §4 — justified by the typing trade-off, see useThemedVariants). The defineVariants helper wraps cva with a debug-friendly component-name tag so chassis DevTools surfaces and the registry generator can attribute resolver output to its source component.

Features

  • Re-exports cva and VariantProps from class-variance-authority
  • defineVariants(name, base, config) returns the same cva resolver with a non-enumerable componentName property attached
  • name arg accepts either a registered ThemableVariantNames key (with autocomplete) or an arbitrary string literal so component packs can declare new component names without first updating the chassis ThemableVariants interface

Usage: Basic example

import { defineVariants } from "@suaveplan/react-ui/variants";

export const buttonVariants = defineVariants("Button", "inline-flex h-9", {
    variants: {
        variant: { default: "bg-primary", ghost: "bg-transparent" },
        size: { sm: "px-3", md: "px-4", lg: "px-6" },
    },
    defaultVariants: { variant: "default", size: "md" },
});

Usage: Advanced example

import { defineVariants, type VariantProps } from "@suaveplan/react-ui/variants";

export const cardVariants = defineVariants("Card", "rounded border", {
    variants: {
        padding: { none: "", sm: "p-2", md: "p-4", lg: "p-6" },
    },
    defaultVariants: { padding: "md" },
});

export type CardVariants = VariantProps<typeof cardVariants>;

declare module "@suaveplan/react-ui/theme" {
    interface ThemableVariants {
        readonly Card: typeof cardVariants;
    }
}

API Reference

  • cva — re-exported from class-variance-authority
  • VariantProps — re-exported VariantProps
  • defineVariants(name, base, config) — wraps cva and tags the resolver with componentName

Implementation notes

The componentName property is non-enumerable so it does NOT appear in JSON serialisation, Object.keys, or for...in iteration — keeping the cva resolver's surface area unchanged for consumers that pass the function around. The tag is used by the registry generator (scripts/build-registry.ts in Wave 3) to map ejected component source to its resolver's named identity. The chassis's useThemedVariants hook does NOT consult the tag — it keys cache entries on the (themeName, componentName) tuple supplied by the call site, which keeps the cache lookup O(1) and dependency-free.