Installation & Theming

How to install StyleLab UI and switch between its 8 themes in your React app.

Prerequisites

  • React 18+ — The library uses hooks and modern React patterns.
  • Tailwind CSS v4 — StyleLab themes are built on Tailwind v4’s @theme and utilities. v3 is not supported.
  • A build setup that supports CSS @import (Vite, Next.js, Parcel, etc.).

1. Installation

In a Next.js or existing React app you already have React; just install the package. In a new project without React, add the peer dependencies too.

# Next.js or existing React app
npm install @raxrai/stylelab-ui

# New project without React
npm install @raxrai/stylelab-ui react react-dom

With Yarn or pnpm:

yarn add @raxrai/stylelab-ui
# or (new project without React: add react react-dom)
pnpm add @raxrai/stylelab-ui

Peer dependencies: react and react-dom (≥18). The library bundles class-variance-authority, clsx, tailwind-merge, lucide-react, and framer-motion; you do not need to install them separately.

2. Add the styles

Your app must use Tailwind CSS v4. Import StyleLab’s design tokens in your global CSS after Tailwind so custom shadows and theme utilities are available.

@import "tailwindcss";
@import "@raxrai/stylelab-ui/styles";

The StyleLab stylesheet provides:

  • Custom shadows — e.g. --shadow-neubrutal, --shadow-clay-outer, --shadow-glass-edge, --shadow-neon-glow for Cyberpunk.
  • Keyframes — e.g. skeleton shimmer, glitch (Cyberpunk).
  • Theme-specific utilities used by the components.

If your setup uses a different Tailwind entry (e.g. a preset or @tailwind base/components/utilities), ensure the StyleLab import runs after Tailwind so @theme inline tokens are applied. In Next.js, this usually means adding both imports at the top of your app/globals.css (or styles/globals.css).

3. Wrap your app with ThemeProvider

All StyleLab components read the active theme from React context. Wrap your app (or the subtree that uses the library) with ThemeProvider and set a defaultTheme. Optional persistTheme (default true) controls whether the theme is restored from and saved to localStorage; use persistTheme= for fixed-theme pages. The provider must be a client component ("use client") because it uses state and useEffect.

import { ThemeProvider } from "@raxrai/stylelab-ui";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ThemeProvider defaultTheme="minimal">
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

With the default persistTheme=, the provider restores the theme from localStorage on mount and saves when you call setTheme. If you need a custom storage key or to control the initial theme yourself (e.g. after async load), use the pattern below: read from storage and pass as defaultTheme.

"use client";

import { useEffect, useState } from "react";
import { ThemeProvider, THEMES } from "@raxrai/stylelab-ui";

const STORAGE_KEY = "stylelab-theme";
const FALLBACK = "minimal";

function getStoredTheme(): string {
  if (typeof window === "undefined") return FALLBACK;
  try {
    const stored = localStorage.getItem(STORAGE_KEY);
    return stored && THEMES.includes(stored) ? stored : FALLBACK;
  } catch {
    return FALLBACK;
  }
}

export function Providers({ children }: { children: React.ReactNode }) {
  const [initialTheme, setInitialTheme] = useState(FALLBACK);
  useEffect(() => {
    setInitialTheme(getStoredTheme());
  }, []);
  return (
    <ThemeProvider defaultTheme={initialTheme}>
      {children}
    </ThemeProvider>
  );
}

4. Use components and switch the theme

Import components and the useTheme hook. The hook returns theme (current theme) and setTheme (update and persist). Use the hook only inside a subtree wrapped by ThemeProvider; otherwise you get a safe fallback (minimal, no-op setTheme).

import { Button, Card, useTheme } from "@raxrai/stylelab-ui";

export function MyPage() {
  const { theme, setTheme } = useTheme();

  return (
    <div>
      <Button variant="primary">Click me</Button>
      <Card>Content</Card>
      <select
        value={theme}
        onChange={(e) => setTheme(e.target.value)}
      >
        <option value="minimal">Minimal</option>
        <option value="night">Night</option>
        <option value="glass">Glass</option>
        {/* ... other themes */}
      </select>
    </div>
  );
}

For TypeScript, use the StyleLabTheme type when typing theme state or props.

4b. Per-component theme override

Many components accept an optional theme prop. When set, that instance uses the given theme instead of the context theme. Useful for one-off cards, modals, or sections that should look different from the rest of the app.

import { Card, Badge, Modal } from "@raxrai/stylelab-ui";

// One card in Cyberpunk while the app is in Minimal
<Card theme="cyberpunk">Neon card</Card>
<Badge theme="night">Dark badge</Badge>
<Modal open={open} onClose={() => setOpen(false)} theme="glass">
  Glass-style modal
</Modal>

Components that support the theme prop include Button, Badge, Card, Input, Alert, Modal, Tabs, Tooltip, Accordion, Avatar, Breadcrumbs, Calendar, CommandPalette, and others. Check each component’s props in the Gallery.

5. Available themes

Pass any of these values to defaultTheme or setTheme(theme). TypeScript type: StyleLabTheme.

  • MinimalminimalClean surfaces, neutral palette, focused typography.
  • NightnightDark-first with subtle borders and inset shadows.
  • GlassglassGlassmorphism: blur, depth, soft shadows.
  • NeubrutalneubrutalBold borders, flat shadows, high contrast.
  • ClayclaySoft 3D feel with rounded shapes and clay shadows.
  • CyberpunkcyberpunkNeon accents, glitch, terminal-ready.
  • Retroretro8-bit inspired: blocky, lime accent, monospace.
  • MotionmotionHeavily animated: transitions and hover feedback.
import type { StyleLabTheme } from "@raxrai/stylelab-ui";
import { THEMES } from "@raxrai/stylelab-ui";

// THEMES is: ["minimal", "night", "glass", "neubrutal", "clay", "cyberpunk", "retro", "motion"]

6. Persistence and DOM attribute

When you call setTheme(theme), the provider updates React state and sets document.documentElement.dataset.stylelabTheme. When persistTheme is true (default), it also writes the theme to localStorage under storageKey (default "stylelab-theme") and restores from it on mount. When persistTheme=, no localStorage read or write occurs.

The initial theme is controlled by defaultTheme. With persistTheme=, the provider restores from localStorage on mount; you can also restore manually by reading storage and passing it as defaultTheme (see the example in section 3).

Using the data attribute in your CSS

The root element gets data-stylelab-theme="minimal" (or the current theme). You can use this to style your own layout or non–StyleLab elements to match the active theme.

/* e.g. in your global CSS or a CSS module */
[data-stylelab-theme="night"] .my-sidebar {
  background: rgb(24 24 27);
  border-color: rgba(255 255 255 / 0.1);
}
[data-stylelab-theme="cyberpunk"] .my-heading {
  color: #22d3ee;
}

7. Nesting and per-section themes

You can nest ThemeProvider. Inner providers override the theme for their subtree. Use this when part of your UI should use a different theme (e.g. a dark sidebar, a marketing block in Glass, or a modal in Cyberpunk).

<ThemeProvider defaultTheme="minimal">
  <main>App in Minimal</main>
  <ThemeProvider defaultTheme="cyberpunk">
    <aside>This sidebar uses Cyberpunk theme.</aside>
  </ThemeProvider>
</ThemeProvider>

8. Troubleshooting

  • Components look unstyled or wrong. Ensure @import "@raxrai/stylelab-ui/styles" runs after Tailwind in your global CSS. If StyleLab is imported first, Tailwind’s layers can override the theme tokens.
  • I’m on Tailwind v3. StyleLab is built for Tailwind v4 (with @theme inline). It is not compatible with v3. Upgrade to Tailwind v4 or use the library’s prebuilt CSS if a v4-compat build is provided.
  • Theme doesn’t persist after refresh. The provider only writes to localStorage when setTheme is called. To restore on load, use the “Restore theme from localStorage” pattern in section 3.
  • useTheme() returns minimal and setTheme does nothing. The component is not inside a ThemeProvider. Wrap the tree (e.g. in your root layout) with ThemeProvider.

Quick reference

  • Prerequisites: React 18+, Tailwind CSS v4.
  • Install: npm install @raxrai/stylelab-ui (Next.js/React apps already have React; add react react-dom only if the project doesn’t).
  • Styles: @import "@raxrai/stylelab-ui/styles" after Tailwind.
  • Provider: <ThemeProvider defaultTheme="minimal"> around your app (client component).
  • Theme hook: const { theme, setTheme } = useTheme().
  • Override: Many components accept a theme prop for that instance only.
  • Theme values: minimal, night, glass, neubrutal, clay, cyberpunk, retro, motion.
  • Persistence: When persistTheme is true (default), setTheme writes to localStorage and the provider restores on mount. Use persistTheme= to disable. data-stylelab-theme is always set on document.documentElement.