A typesafe, class-variance-authority-based, styled-components-like library for authoring React components with Tailwind CSS.
⚠️ styled-cva 0.5.x only supports React ≥19.x. If you're on React 18, use the latest 0.3.x⚠️
npm
npm i --save @styled-cva/reactpnpm
pnpm add @styled-cva/reactbun
bun add @styled-cva/reactimport tw from "@styled-cva/react";
const Button = tw.button`bg-blue-500 text-white font-bold py-2 px-4 rounded`;
<Button>Click me</Button>;@styled-cva/react runs on Preact via the standard preact/compat bundler alias — no styled-cva code changes required. See Getting Started → Preact for Vite, Webpack, and Next.js snippets.
A consumer-facing skill ships with the repo at .claude/skills/styled-cva/. It loads automatically when working inside this repo, and is published as a .skill artifact attached to each GitHub release.
Install for an end user:
- Grab
styled-cva.skillfrom the latest GitHub release. - Drop it into either
~/.agents/skills/(multi-agent registry) or~/.claude/skills/(Claude Code only) — the file is a standard zip with.skillextension and most installers extract it in place.
Build locally:
bun run skill:build # writes dist/skill/styled-cva.skillThe same script is used by the release flow to produce the artifact attached to each tag.
| Package | Description |
|---|---|
| packages/core | @styled-cva/core – shared cva, cn, helpers (published) |
| packages/react | @styled-cva/react – React adapter (published) |
| packages/solid | @styled-cva/solid – Solid adapter (published) |
| packages/vue | @styled-cva/vue – Vue adapter (published) |
| packages/eslint-plugin | @styled-cva/eslint-plugin – ESLint rule to extract classes to styled components (published) |
| packages/prettier-plugin | @styled-cva/prettier-plugin – Prettier plugin to normalize and multi-line tw templates (published) |
| packages/biome-plugin | @styled-cva/biome-plugin – Biome GritQL diagnostics for tw templates (published) |
| docs | @styled-cva/docs – documentation site (private) |
Requirements: Bun (or Node ≥20), recommended via packageManager in root package.json.
bun install
bun run build
bun run test
bun run lint
bun run dev| Script | Description |
|---|---|
bun run build |
Build all packages (core, react, solid, vue, eslint-plugin, prettier-plugin, biome-plugin) and docs |
bun run dev |
Start docs site (Next.js) |
bun run test |
Run tests in packages that have a test script |
bun run lint |
Lint packages |
bun run format |
Format with Prettier |
bun run clean |
Remove build output for all packages |
bun run bump:patch |
Bump patch version(s) for package(s) (supports glob filter) |
bun run changeset |
Add a changeset (describe a release) |
bun run version |
Bump versions and update CHANGELOGs from changesets |
bun run release |
Build and publish all versioned packages |
bun run release:react |
Build and publish @styled-cva/react |
bun run release:solid |
Build and publish @styled-cva/solid |
bun run release:vue |
Build and publish @styled-cva/vue |
bun run release:eslint-plugin |
Build and publish @styled-cva/eslint-plugin |
bun run release:prettier-plugin |
Build and publish @styled-cva/prettier-plugin |
bun run release:biome-plugin |
Publish @styled-cva/biome-plugin (no build — ships .grit files) |
Versioning uses Changesets. See RELEASING.md for the full workflow.
The Unlicense — public domain. See the LICENSE file at the repository root.