Files

5.1 KiB

Vibn AI Templates

A small, themable starter kit for building modern SaaS UIs. Pure React + CSS variables — no build step, no dependencies. Designed to be copy-pasted into any project.

What's in it

  • tokens.css — Every color, radius, shadow, and type token, exposed as CSS custom properties. Four themes ship out of the box:
    • .theme-minimal — soft warm light (Linear / Notion school)
    • .theme-dark — black-and-white surface (Vercel / Stripe school)
    • .theme-glass — aurora gradient + frosted glass
    • .theme-editorial — paper, serif display, hairline rules
  • icons.jsx — A small Tabler-style stroke icon set (<Icon name="search"/>) plus a <VibnMark/> brand glyph.
  • components.jsx — Atoms + composites. Every visual property reads from a CSS variable:
    • Forms · Button, IconButton, Field, Input, Textarea, Select, Checkbox, Radio, Switch, FieldGroup
    • Containers · Card, CardHeader, Divider, Modal, Banner
    • Display · Badge (tones: neutral / accent / success / warn / danger / info), Avatar, AvatarStack, Tabs, Table, Spinner, KBD
  • shells.jsx — Page-level layouts:
    • In-product · SidebarShell, TopbarShell, RailShell
    • Auth · AuthCenteredShell, AuthSplitShell, AuthGlassShell

How theming works

Tokens are CSS custom properties on :root (the default minimal theme). Each .theme-* class overrides a subset. Apply a theme by adding the class anywhere — usually on <html> or a top-level wrapper.

<html class="theme-glass">
  <!-- the whole page uses the glass theme -->
</html>
<!-- or scope a theme to one region -->
<div class="theme-editorial">
  <Card>… this card is editorial …</Card>
</div>

Themes can nest. Setting theme-* on a child element overrides only the tokens that theme defines; the rest inherit from the parent.

Adding a fifth theme

Add a new class to tokens.css that overrides whichever tokens differ from :root:

.theme-sunset {
  --bg: #2b0d0e;
  --surface: #3a1316;
  --accent: #ff8a3a;
  --accent-2: #f43f5e;
  --text: #fef7ee;
  --text-2: #f0c8b0;
  --border: #4a1f23;
  --button-bg: #ff8a3a;
  --button-fg: #2b0d0e;
}

You don't need to redefine the whole token set — just the differences. Components don't change.

Usage in plain HTML (no bundler)

<link rel="stylesheet" href="vibn-ai-templates/tokens.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=DM+Serif+Display:ital@0;1&display=swap" rel="stylesheet">

<script src="https://unpkg.com/react@18.3.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js"></script>

<script type="text/babel" src="vibn-ai-templates/icons.jsx"></script>
<script type="text/babel" src="vibn-ai-templates/components.jsx"></script>
<script type="text/babel" src="vibn-ai-templates/shells.jsx"></script>

<div id="root" class="theme-dark"></div>

<script type="text/babel">
  function App() {
    return (
      <AuthCenteredShell brand={{ name: "Acme" }}>
        <h1 style={{ margin: 0, fontSize: 22, fontWeight: 600 }}>Welcome back</h1>
        <p style={{ color: "var(--text-2)", marginTop: 6 }}>Sign in to continue.</p>
        <Field label="Email"><Input value="mira@acme.io"/></Field>
        <Field label="Password"><Input type="password" value="••••••••••"/></Field>
        <Button full>Sign in</Button>
      </AuthCenteredShell>
    );
  }
  ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>

Usage in a React codebase

Convert the three .jsx files from Object.assign(window, …) to named export statements. The components have no runtime dependencies beyond React.

// In your app
import "vibn-ai-templates/tokens.css";
import { Button, Card, Input, Field, Tabs } from "vibn-ai-templates/components";
import { SidebarShell } from "vibn-ai-templates/shells";

// Pick a theme on your root
<html className="theme-dark">

Conventions

  • Inline styles read from CSS varsstyle={{ background: "var(--surface)" }}. This is intentional: it lets the entire library reskin with one class swap, and avoids a CSS-in-JS dependency.
  • Components are presentational. State (open/closed modals, active tabs, form values) lives in your app. Pass active + onChange to controlled components.
  • No external icon dependency. icons.jsx ships a curated set. Add to it freely.
  • Avatars hash a color from the name unless you pass color="#…".
  • Tables and tabs are uncontrolled-friendly — pass rows/items, omit selection props if you don't need them.

Showcase

Vibn UI Showcase.html at the project root renders every component across every theme. Use it as the visual reference and as a starting point for new screens.

Versioning

This is a starter — fork it. There's no semver, no changelog. Edit tokens.css to match your brand, prune what you don't use, extend what you do.