Getting started
DAVE is a React component library built on Tailwind CSS. Components are unstyled at the Tailwind level — they use semantic CSS custom properties, so you can theme the entire system by overriding a handful of variables.
Fair warning — DAVE is a personal design system, built for my own projects first. It's MIT licensed and free to use, but there's no stability guarantee, no versioning promise, and no support line. Things change when I need them to. Use it, fork it, adapt it — just go in with eyes open.
Prerequisites
DAVE targets the Next.js App Router (tested with Next 15; Next 14 still works but isn't tested. Other React frameworks work but aren't tested either). Start from a fresh create-next-app scaffold with TypeScript and Tailwind enabled:
pnpm create next-app@15 my-app --typescript --tailwind --eslint --app --no-src-dir --import-alias "@/*" --turbopack
cd my-app--turbopack opts in to Next's default-recommended bundler and skips the interactive prompt the scaffold would otherwise show.
Installation
Install the component library, token package, and optionally the chart package:
pnpm add @haydywoo/dave-react @haydywoo/dave-tokens @haydywoo/dave-chartsConfigure styles
Replace app/globals.css with the DAVE setup. This file is doing three things at once: pulling in Tailwind 4, importing DAVE's token CSS variables, and aliasing those variables into Tailwind's theme so utilities like bg-card, text-foreground, bg-accent get generated.
/* app/globals.css */
@import "tailwindcss";
@import "@haydywoo/dave-tokens/dist/tokens.css";
@source "../node_modules/@haydywoo/dave-react/dist/**/*.js";
@source "../node_modules/@haydywoo/dave-charts/dist/**/*.js";
/* DAVE's dark mode is class-based (.dark on <html>) */
@custom-variant dark (&:where(.dark, .dark *));
@theme inline {
--color-background: var(--color-background);
--color-surface: var(--color-surface);
--color-surface-hovered: var(--color-surface-hovered);
--color-card: var(--color-card);
--color-raised: var(--color-raised);
--color-foreground: var(--color-foreground);
--color-fg-secondary: var(--color-foreground-secondary);
--color-fg-subdued: var(--color-foreground-subdued);
--color-fg-disabled: var(--color-foreground-disabled);
--color-border: var(--color-border);
--color-border-strong: var(--color-border-strong);
--color-accent: var(--color-accent);
--color-accent-hover: var(--color-accent-hover);
--color-accent-subtle: var(--color-accent-subtle);
--color-accent-subtle-border: var(--color-accent-subtle-border);
--color-accent-border: var(--color-accent-border);
--color-accent-foreground: var(--color-accent-foreground);
--color-accent-on: var(--color-on-accent);
--color-success: var(--color-success);
--color-success-subtle: var(--color-success-subtle);
--color-success-border: var(--color-success-border);
--color-success-foreground: var(--color-success-foreground);
--color-warning: var(--color-warning);
--color-warning-subtle: var(--color-warning-subtle);
--color-warning-border: var(--color-warning-border);
--color-warning-foreground: var(--color-warning-foreground);
--color-error: var(--color-error);
--color-error-hover: var(--color-error-hover);
--color-error-subtle: var(--color-error-subtle);
--color-error-border: var(--color-error-border);
--color-error-foreground: var(--color-error-foreground);
--color-chart-1: var(--color-chart-1);
--color-chart-2: var(--color-chart-2);
--color-chart-3: var(--color-chart-3);
--color-chart-4: var(--color-chart-4);
--color-chart-5: var(--color-chart-5);
--color-chart-6: var(--color-chart-6);
--color-chart-7: var(--color-chart-7);
--color-chart-8: var(--color-chart-8);
--shadow-card: var(--shadow-card);
--shadow-raised: var(--shadow-raised);
--shadow-control: var(--shadow-control);
--shadow-solid: var(--shadow-solid);
--default-transition-timing-function: var(--ease-standard);
--font-display: var(--font-display, ui-sans-serif), sans-serif;
--font-body: var(--font-body, ui-sans-serif), sans-serif;
--font-code: var(--font-code, ui-monospace), monospace;
}The @source directives tell Tailwind to scan DAVE's compiled JS for class names — without them, Tailwind won't know which utilities the library actually uses, and the resulting CSS will be missing classes the components reference.
The inline keyword on @theme is load-bearing: it tells Tailwind to keep the var() references at runtime instead of baking the values at build time. That's what lets DAVE's light/dark mode swap continue to work.
Configure Next.js
Add transpilePackages so Next transpiles DAVE's compiled output consistently:
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
transpilePackages: ['@haydywoo/dave-react', '@haydywoo/dave-charts', 'recharts'],
};
export default nextConfig;Use a component
import { Button, Card, CardHeader, CardTitle, CardContent } from '@haydywoo/dave-react';
export default function Page() {
return (
<Card>
<CardHeader>
<CardTitle>Hello</CardTitle>
</CardHeader>
<CardContent>
<Button variant="primary">Get started</Button>
</CardContent>
</Card>
);
}Use a chart
Charts use index (the key for the x-axis category) and categories (an array of keys to plot as series):
import { BarChart } from '@haydywoo/dave-charts';
const data = [
{ month: 'Jan', sales: 42, refunds: 6 },
{ month: 'Feb', sales: 51, refunds: 4 },
{ month: 'Mar', sales: 48, refunds: 9 },
];
<BarChart
data={data}
index="month"
categories={['sales', 'refunds']}
height={240}
/>TypeScript: CSS side-effect imports
If your pnpm build complains about a side-effect import for globals.css:
Type error: Cannot find module or type declarations for side-effect import of './globals.css'.
Add a global.d.ts at the project root (not next-env.d.ts — Next regenerates that file on every build and strips additions):
// global.d.ts
declare module '*.css';What's next
- Theming — swap the accent colour for your brand
- Colours — the full token scale
- Components — browse the component library