Grow with precision.
Calm, fresh, green-accented React 19 components with soft motion.
Original code, shadcn-compatible copy-paste delivery — zero runtime lock-in.
| 🌱 Original | Every component is written from scratch. Patterns are studied; code and visuals are never copied. |
| ♿ Accessible | WCAG AA contrast (756 audited colour pairs), keyboard & screen-reader support, prefers-reduced-motion respected, usable at 320 px, SSR-safe. |
| 🎨 Themeable | Flat design tokens in the package, semantic data-theme / data-tone on the consumer side. Five ready-made presets — Slate · Sand · Midnight · Rose · Ocean — plus light and dark as first-class citizens. |
| 📋 Copy-paste ready | shadcn-compatible registry items install straight into your codebase. You own the source, no wrapper dependency. |
28 components, 30 registry items:
| Category | Components |
|---|---|
| Inputs | Button · Input · Textarea · Checkbox · Radio Group · Select · Switch |
| Layout | Card · Separator · Skeleton · Table · Field · Field Group |
| Feedback | Alert · Badge · Progress · Toast |
| Overlay | Dialog · Dropdown Menu · Popover · Tooltip · Hover Card · Command |
| Disclosure | Accordion · Collapsible · Tabs |
| Data display | Avatar · Carousel · Label |
- React 19 project
- Tailwind CSS v4 (CSS-first —
@import "tailwindcss") - shadcn CLI initialised (
npx shadcn@latest init) @/*path alias intsconfig.json
npx shadcn add @vert/vertThis emits:
styles/vert.css— tokens, utilities, base stylesstyles/themes.css— theme bridges- Five presets —
styles/themes/slate.css,sand.css,midnight.css,rose.css,ocean.css
Tailwind must come first:
@import "tailwindcss";
@import "./styles/vert.css";# one at a time
npx shadcn add @vert/button
# batch
npx shadcn add @vert/button @vert/input @vert/card
# or via direct URL (no registry config needed)
npx shadcn add https://vert-ui.dev/r/field.jsonThe CLI copies component source into components/vert-ui/<name>.tsx, installs the
cn() helper (lib/vert-ui/cn.ts) on first need, rewrites imports, and pulls in required
dependencies automatically.
Copy files from packages/ui/src/components and
packages/ui/src/lib/cn.ts directly into your project.
vert-ui ships two parallel token vocabularies that coexist:
| Layer | Entry | Tokens | Controlled by |
|---|---|---|---|
| Flat (library internals / docs) | packages/ui/src/styles/index.css |
--color-primary, --color-muted, --color-ring, … |
.dark class or prefers-color-scheme |
| Semantic (consumer-facing engine) | styles/vert.css (registry item) |
--brand, --surface, --accent, --muted, … |
data-theme="slate|sand|…" + data-tone="light|dark" on <html> |
vert.css aliases semantic vars to the flat set, so the same Tailwind utilities resolve in
both entries. Switch themes at runtime by toggling the data-theme and data-tone attributes.
| Preset | Tone |
|---|---|
| Slate | Cool neutral with emerald accent |
| Sand | Warm earth tones |
| Midnight | Deep dark with vivid highlights |
| Rose | Soft pink undertones |
| Ocean | Blue-teal palette |
- Contrast — 756 colour pairs (384 semantic + 372 flat) audited against WCAG AA. Run the
audit yourself:
pnpm exec tsx scripts/check-contrast.ts - Keyboard — every interactive component is fully keyboard-navigable.
- Screen readers — semantic HTML, ARIA attributes, and Radix primitives provide a solid accessible tree.
- Reduced motion — all animation respects
prefers-reduced-motion: reduce. - Responsive — components are tested down to 320 px viewport width.
- SSR-safe — no
window/documentaccess at module scope; compatible with server rendering.
The docs app is the full reference — live preview, usage examples, props table and accessibility notes for every component.
pnpm install
pnpm --filter @vert-ui/docs dev # → http://localhost:3000apps/docs TanStack Start docs site (catalog + per-component pages)
packages/ui Component library (consumed as raw TS, no build step)
packages/registry shadcn-compatible registry generator
packages/cli vert-ui CLI — init, add, diff (in progress)
scripts/ check-contrast.ts — WCAG AA audit over the theme tokens
styles/ Consumer-facing theme files (vert.css, themes/, presets)
# Install
pnpm install
# Docs dev server
pnpm --filter @vert-ui/docs dev
# Unit tests (vitest + jsdom, 28 components)
pnpm --filter @vert-ui/ui exec vitest run
# Single test file
pnpm --filter @vert-ui/ui exec vitest run src/components/button.test.tsx
# Typecheck
pnpm exec tsc -p packages/ui/tsconfig.json --noEmit
pnpm exec tsc -p apps/docs/tsconfig.json --noEmit
# Contrast audit (must stay 756 passed / 0 failed)
pnpm exec tsx scripts/check-contrast.ts
# Regenerate registry JSON (run after any component / theme edit)
pnpm exec tsx packages/registry/src/build.ts
# Production docs build
pnpm --filter @vert-ui/docs buildCI runs the same six checks — both typechecks, unit tests, contrast audit, registry build, and docs build — on every push and pull request.
Versions and changelogs are managed with Changesets:
pnpm exec changeset # record a change
pnpm exec changeset version # bump versions + write CHANGELOGs
pnpm exec changeset publish # publish to npmCurrent version: 0.1.0 — see
packages/ui/CHANGELOG.md for the full history.
- Fork the repo and create a feature branch.
pnpm installat the root.- Make your changes — follow the existing component conventions (
cvavariants,cn(),data-slot,asChildvia Radix Slot, ref forwarding,displayName). - Add / update tests (
src/components/<name>.test.tsx). - Run the full verification suite:
pnpm --filter @vert-ui/ui exec vitest run pnpm exec tsc -p packages/ui/tsconfig.json --noEmit pnpm exec tsx scripts/check-contrast.ts pnpm exec tsx packages/registry/src/build.ts pnpm --filter @vert-ui/docs build
- Open a PR against
main.
MIT © vert-ui