tailwind-variants

Typed Tailwind CSS variant API with slots, compound variants, and built-in class-conflict resolution

Library
npm
v3.3.1
3,308 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
65 /100 Good
Development Activity 56
Maintenance 60
Community 52
Maturity 52
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
85 /100 Excellent
Architecture 88
Code Quality 86
Innovation 87
Learning Curve 78

Tailwind Variants is a TypeScript-first variant API for Tailwind CSS that lets you define base styles, variants, compound variants, default variants, and component slots as a single typed configuration object. It layers built-in Tailwind class-conflict resolution on top of the variant system, so composing and overriding classes never produces duplicate or conflicting utility classes.

Framework-agnostic and dependency-light, it is used to build variant-driven design systems and component libraries — including HeroUI’s own component set — where a consistent, type-safe styling API matters across React, Vue, Svelte, or plain JS projects.

What You Get

  • A typed tv() API for defining base styles, variants, compound variants, default variants, and multi-slot components in one config object
  • Built-in Tailwind class-conflict resolution (via an internal tailwind-merge-compatible engine) on tv, createTV, cn, and cnMerge
  • A /lite entry point that drops conflict resolution for a smaller bundle when merging isn’t needed
  • cx, cn, and cnMerge utility functions for concatenating and optionally merging class names outside of tv()
  • Full TypeScript inference for variant props, slot names, and compound-variant conditions

Common Use Cases

  • Building a variant-driven design system where each component (button, card, input) exposes typed size/color/state props that map to Tailwind classes
  • Building multi-part components with slots (e.g. a card with header/body/footer slots) that share variant state across all slots
  • Replacing ad hoc clsx/template-literal class concatenation with a typed, cacheable resolver that also resolves Tailwind class conflicts
  • Powering component libraries (like HeroUI) that need a consistent styling API across many components and consumers using different bundlers or frameworks

Under The Hood

Architecture The package is layered: index.ts is a thin public API that wraps internal/tv.ts’s getTailwindVariants factory, which returns the tv/createTV functions. class-resolver.ts’s createClassResolver branches on a resolved.mode of "plain" | "variant" | "slots" into three specialized resolver closures (createPlainResolver, createVariantResolver, createSlotsResolver) that are built lazily on first invocation so constructing a tv() component stays cheap. resolve-options.ts eagerly parses the raw config into a ResolvedOptions descriptor and lazily compiles variants, compound variants, and compound slots on first call via compileResolvedOptions. cache.ts implements a bounded result cache (256-entry limit) keyed by a props fingerprint plus a compound-variants signature, with the very first invocation always skipping the cache to avoid caching cold-start artifacts. tw-merge.ts implements its own tailwind-merge-compatible engine (parse-class-name, class-group-utils, sort-modifiers) rather than depending on the tailwind-merge package at runtime for the default entry point.

Tech Stack TypeScript 5.6 in strict mode with exactOptionalPropertyTypes enabled. Built via tsup (esbuild-backed) into dual ESM (dist/index.js) and CJS (dist/index.cjs) bundles with generated .d.ts/.d.cts type files, plus separate lite and utils entry points declared through package.json exports. tailwind-merge and tailwindcss are optional peer dependencies (peerDependenciesMeta.optional: true), so the package still works when Tailwind isn’t present at runtime. The repo uses a pnpm workspace with .nvmrc/packageManager pinning, Biome 2.5 for linting instead of ESLint/Prettier, commitlint plus husky to enforce Conventional Commits, and bumpp + conventional-changelog to automate releases.

Code Quality 15 Vitest test files (cn.test.ts, create-tv.test.ts, merge-engine.test.ts, merge-parity.test.ts, tv-compound-slots.test.ts, tv-extend*.test.ts, tv-slots.test.ts, tv-tailwind-merge.test.ts, and more) cover the resolver modes, extension and composition behavior, and merge parity against upstream tailwind-merge semantics. A separate __types__ directory holds compile-time type tests (tsc -p .config/tsconfig.type-tests.json) that assert the public API’s inferred types for the core, slot, variant, and metadata APIs. strict: true plus exactOptionalPropertyTypes catch a class of undefined-vs-missing bugs at compile time. CI (ci.yml) runs alongside a dedicated benchmark.yml workflow that tracks performance regressions via tinybench.

API Design The public surface is deliberately small — tv, createTV, cn, cx, cnMerge, and defaultConfig — with tv() itself handling plain, variant, and slot-based components based on the shape of the config object passed in, so there’s no separate API to learn per mode. Slots and compound variants are expressed declaratively in the same config rather than requiring separate composition calls, and createTV mirrors tv exactly but pre-bound to custom config, keeping the mental model consistent. The project is documented at tailwind-variants.org with a runnable quick-start in the README and versioned migration guides (v1→v2, v2→v3) for breaking changes.

Used by 18 apps in this directory

TypeScript
80%
GPL 3.0

Bramble

Authentication · Password Manager · Security

399

Local-first, end-to-end encrypted password manager that syncs your vault directly between your own devices over a private peer-to-peer mesh — no server, no account, no cloud in the middle.

View details
75
Repo Health
84
Technical
68
Dependency
Built with
TypeScript 80%
Updated 5 days ago
Rust
67%
MIT

Bun

Developer Tools

96,068

An all-in-one JavaScript and TypeScript toolkit — one Rust-and-JavaScriptCore binary that replaces Node.js, npm, a bundler, and a test runner with faster equivalents.

View details
92
Repo Health
91
Technical
64
Dependency
Built with
Rust 67%
C++ 19%
TypeScript 10%
Updated 5 days ago
JavaScript
99%
Other

ChartBrew

Analytics · Databases

4,063

Open-source reporting platform to build live dashboards from SQL, NoSQL, APIs, and SaaS tools with an AI assistant that creates charts from natural language.

View details
90
Repo Health
83
Technical
64
Dependency
Built with
JavaScript 99%
Updated 1 weeks ago
TypeScript
45%
Other

Convex Backend

Databases · Developer Tools

12,617

Open-source reactive database that lets developers build live-updating apps with pure TypeScript, strong consistency, and real-time subscriptions—no separate API layer required.

View details
87
Repo Health
82
Technical
68
Dependency
Built with
TypeScript 45%
Rust 43%
Updated 6 days ago
Java
34%
Apache 2.0

Enso

Analytics · Data Engineering · Low Code Platforms

7,441

A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.

View details
59
Repo Health
90
Technical
61
Dependency
Built with
Java 34%
TypeScript 27%
Scala 26%
Updated 1 months ago
TypeScript
64%
Other

Epicenter

Developer Tools · Knowledge Management · Note Taking

4,808

A local-first monorepo led by Whispering, an open-source speech-to-text app, built on an MIT toolkit that turns your data into plain Markdown and SQLite files you own instead of a database you rent.

View details
88
Repo Health
90
Technical
64
Dependency
Built with
TypeScript 64%
HTML 13%
Svelte 13%
Updated 5 days ago
TypeScript
82%
MIT

evidence

Analytics · Data Engineering

6,962

Turn SQL queries and markdown files into polished, interactive data apps and business intelligence reports — no drag-and-drop, no GUI, just code.

View details
90
Repo Health
79
Technical
64
Dependency
Built with
TypeScript 82%
Svelte 17%
Updated 1 weeks ago
Python
64%
Other

Keep

Automation · Devops · Monitoring

12,359

The open-source AIOps and alert management platform that unifies 130+ monitoring tools into a single pane of glass with AI-powered correlation, deduplication, and workflow automation.

View details
89
Repo Health
79
Technical
66
Dependency
Built with
Python 64%
TypeScript 36%
Updated 1 weeks ago
TypeScript
50%

Kener

Devops · Monitoring

5,181

Stunning, self-hosted status pages with real-time uptime monitoring, incident management, and multi-channel notifications in a single Docker container.

View details
86
Repo Health
76
Technical
67
Dependency
Built with
TypeScript 50%
Svelte 47%
Updated 2 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers