vert-ui
Browse docs
All guides

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

  1. Install the theme

    npx shadcn add @vert/vert

    Import 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";
  2. Add a component

    npx shadcn add @vert/button

    The source lands in your repo and its npm dependencies are installed. Import it from there — never from a library package.

  3. Render it

    import { Button } from "@/components/vert-ui/button"
    
    <Button>Save changes</Button>
    <Button variant="outline">Cancel</Button>
    <Button variant="glow">Deploy</Button>
  4. 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">
  5. 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.css

Three 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-describedby wiring are built in.
  • prefers-reduced-motion respected; 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: