Getting Started
From an installed theme to a themed, accessible screen — five steps, each one a single command or a short snippet.
Walkthrough
Your first five minutes
Install the theme
npx shadcn add @vert/vertImport it after Tailwind in your CSS entry. Everything else — tokens, focus rings, reduced-motion handling — comes from this file.
@import "tailwindcss"; @import "./styles/vert.css";Add a component
npx shadcn add @vert/buttonThe source lands in your repo and its npm dependencies are installed. Import it from there — never from a library package.
Render it
import { Button } from "@/components/vert-ui/button" <Button>Save changes</Button> <Button variant="outline">Cancel</Button> <Button variant="glow">Deploy</Button>Pick a tone and a theme
Tone is light or dark. A theme is a full token preset — import the ones you use from
styles/themes/, then switch with attributes on<html>:<!-- light (default) --> <html data-tone="light"> <!-- dark tone: dark: variants now resolve to [data-tone='dark'] --> <html data-tone="dark"> <!-- full preset: import styles/themes/slate.css first --> <html data-theme="slate" data-tone="dark">Compose a small screen
Shown to everyone on your team.
Already taken.
<Field label="Workspace name" description="Shown to everyone on your team."> {(field) => <Input {...field} defaultValue="Acme Inc." />} </Field> <Field label="Slug" error="Already taken."> {(field) => <Input {...field} defaultValue="acme" />} </Field> <Button>Save changes</Button>Field wires label, description and error to the control with stable ids — the accessible part is handled for you.
Layout
What your repo looks like now
src/
├── components/
│ └── vert-ui/
│ ├── button.tsx
│ └── field.tsx
├── lib/
│ └── vert-ui/
│ └── cn.ts
└── styles/
└── vert.cssThree directories, all plain source. Nothing is generated, nothing is minified — this is the code you maintain from now on.
Theming
Switching themes at runtime
Both attributes are plain CSS hooks, so switching is instant and works without a re-render — persist the choice in localStorage and set it in your document head to avoid a flash on load:
// presets: slate, sand, midnight, rose, ocean
document.documentElement.setAttribute("data-theme", "slate")
// tone: "light" | "dark"
document.documentElement.setAttribute("data-tone", "dark")The dark: variant follows data-tone
The theme remaps Tailwind's dark: variant to [data-tone='dark'], so dark:bg-surface responds to your tone attribute, not the OS setting. An explicit tone always wins.
Ownership
Make it yours
Re-skin by editing the CSS variables at the top of styles/vert.css — brand, muted, accent, border, status colors, radii and shadows all live there. Change --brand and the whole interface follows.
Components are edited the same way: they are your files now. The cn() helper merges Tailwind classes, so pass className overrides freely — every component accepts one.
Accessibility
What you get for free
- WCAG AA contrast across 756 audited colour pairs, light and dark.
- Full keyboard support — focus order, arrow-key navigation, focus traps in overlays, visible focus rings.
- Screen-reader semantics: roles, labels and
aria-describedbywiring are built in. prefers-reduced-motionrespected; all animation is transform/opacity only.- SSR-safe and usable at 320px with no layout shift.
Next
Where to go from here
Each component page in the catalog has a live preview, usage examples, a full props table and accessibility notes: