Tailwind Variant v3
The `tailwind-variant-v3` package is a runtime variant utility specifically designed for Tailwind CSS v3, offering a TypeScript-first approach for defining and managing UI component styles. It is part of the `weapp-tailwindcss` monorepo, which integrates Tailwind CSS into WeChat Mini Programs and similar environments. The current stable version is `0.2.1`. Key features include composable variants (supporting `base`, `slots`, `variants`, `compoundVariants`, `compoundSlots`), responsive variant definitions, and deep integration with `tailwind-merge` for robust class name collision resolution. It provides `cn` and `cnBase` utilities and allows for custom `twMergeConfig` and pluggable `twMergeAdapter` implementations for alternative merging libraries. Slot caching is also incorporated to optimize performance. Users must manually install `tailwind-merge@^2` as a peer dependency. For projects using Tailwind CSS v4, it is explicitly recommended to use a corresponding v4 runtime variant solution.
Common errors
-
Cannot find module 'tailwind-merge'
cause `tailwind-merge` is a peer dependency of `tailwind-variant-v3` and must be installed manually.fixRun `npm install tailwind-merge@^2` (or `pnpm add` / `yarn add`) in your project directory. -
TypeError: (0 , tailwind_variant_v3__WEBPACK_IMPORTED_MODULE_0__.tv) is not a function
cause This package is ESM-first. This error typically occurs when attempting to use CommonJS `require()` syntax or incorrect destructuring in an environment that expects ESM.fixEnsure your project's `tsconfig.json` and `package.json` are configured for ES Modules (e.g., `"type": "module"`, `"module": "ESNext"`) and use `import { tv, cn } from 'tailwind-variant-v3'`. -
Argument of type '{ twMergeAdapter: TailwindMergeAdapter; }' is not assignable to parameter of type '...'cause Type mismatch or incorrect implementation provided when attempting to inject a custom `TailwindMergeAdapter` for `tailwind-merge`.fixEnsure that the `TailwindMergeAdapter` type is correctly imported and that the `twMerge` and `extendTailwindMerge` functions from your chosen merge library (e.g., `@weapp-tailwindcss/merge-v3`) are correctly provided to the adapter object.
Warnings
- breaking This package (`tailwind-variant-v3`) is specifically designed for Tailwind CSS v3. If you are using Tailwind CSS v4, you must use the corresponding v4 runtime variant solution to avoid compatibility issues.
- gotcha The package has a peer dependency on `tailwind-merge` (specifically `^2`). This dependency is not automatically installed and must be added manually to your project.
- gotcha When using an alternative merge adapter, such as `@weapp-tailwindcss/merge-v3`, you must manually install it and then explicitly inject it into `tv` or `create` using the `twMergeAdapter` option.
Install
-
npm install tailwind-variant-v3 -
yarn add tailwind-variant-v3 -
pnpm add tailwind-variant-v3
Imports
- tv
const { tv } = require('tailwind-variant-v3')import { tv } from 'tailwind-variant-v3' - cn
const cn = require('tailwind-variant-v3').cnimport { cn } from 'tailwind-variant-v3' - create
import create from 'tailwind-variant-v3'
import { create } from 'tailwind-variant-v3' - TailwindMergeAdapter
import type { TailwindMergeAdapter } from 'tailwind-variant-v3'
Quickstart
import { cn, tv } from 'tailwind-variant-v3'
const button = tv({
base: 'inline-flex items-center gap-2 font-medium transition-colors',
slots: {
icon: 'size-4',
label: 'truncate'
},
variants: {
tone: {
primary: 'bg-blue-500 text-white hover:bg-blue-600',
secondary: 'bg-zinc-900 text-zinc-50 hover:bg-zinc-800',
ghost: 'bg-transparent text-zinc-900 hover:bg-zinc-100'
},
size: {
sm: { base: 'h-8 px-3 text-xs', icon: 'size-3' },
md: { base: 'h-10 px-4 text-sm', icon: 'size-4' },
lg: { base: 'h-12 px-6 text-base', icon: 'size-5' }
}
},
defaultVariants: {
tone: 'primary',
size: 'md'
}
})
// Generate slot classes for a ghost, large button
const slots = button({ tone: 'ghost', size: 'lg' })
// Access individual slot classes
const baseClasses = slots.base() // Example: 'inline-flex items-center gap-2 font-medium transition-colors h-12 px-6 text-base'
const iconClasses = slots.icon({ class: 'text-xl' }) // Example: 'size-5 text-xl'
// Use cn for general class merging
const combinedClasses = cn('flex', ['text-sm', 'md:text-lg'])({ twMerge: true })
console.log('Base Classes:', baseClasses)
console.log('Icon Classes:', iconClasses)
console.log('Combined Classes:', combinedClasses)