Theming

Learn how to customize uiblox to match your brand. Our theming system uses CSS variables and Tailwind CSS for maximum flexibility.

Overview

uiblox uses a layered theming approach:

  1. CSS Variables - Define your color palette and design tokens
  2. Tailwind Config - Map CSS variables to Tailwind utilities
  3. Component Styles - Components reference these tokens

Customizing Colors

Override the default colors by modifying your CSS variables:

globals.css
ReactTailwind
TSX
:root {
  /* Primary - Change to your brand color */
  --color-primary-50: #fef2f2;
  --color-primary-100: #fee2e2;
  --color-primary-200: #fecaca;
  --color-primary-300: #fca5a5;
  --color-primary-400: #f87171;
  --color-primary-500: #ef4444;  /* Main primary color */
  --color-primary-600: #dc2626;
  --color-primary-700: #b91c1c;
  --color-primary-800: #991b1b;
  --color-primary-900: #7f1d1d;
  --color-primary-950: #450a0a;

  /* You can also change semantic colors */
  --color-background: #ffffff;
  --color-foreground: #0f172a;
  --color-muted: #f1f5f9;
  --color-border: #e2e8f0;
}

/* Dark mode overrides */
@media(prefers-color-scheme: dark) {
  :root {
    --color-background: #0f172a;
    --color-foreground: #f8fafc;
    --color-muted: #1e293b;
    --color-border: #334155;
  }
}

Generating Color Palettes

Use these tools to generate a complete color palette from a single color:

Dark Mode

uiblox supports dark mode out of the box using prefers-color-scheme. For manual dark mode toggling, add a class-based approach:

tailwind.config.ts
ReactTailwind
TSX
import type { Config } from "tailwindcss";

const config: Config = {
  darkMode: "class", // Enable class-based dark mode
  // ...rest of config
};

export default config;

Then toggle the dark class on your HTML element:

// Toggle dark mode
document.documentElement.classList.toggle("dark");

// Or set explicitly
document.documentElement.classList.add("dark");    // Enable
document.documentElement.classList.remove("dark"); // Disable

Custom Fonts

Change the default fonts by updating your CSS variables and layout:

globals.css
ReactTailwind
TSX
:root {
  --font-sans: "Your Font", system-ui, sans-serif;
  --font-mono: "Your Mono Font", monospace;
}

If using Next.js, load custom fonts in your layout:

layout.tsx
ReactTailwind
TSX
import { Inter, JetBrains_Mono } from "next/font/google";

const inter = Inter({
  subsets: ["latin"],
  variable: "--font-sans",
});

const jetbrainsMono = JetBrains_Mono({
  subsets: ["latin"],
  variable: "--font-mono",
});

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${inter.variable} ${jetbrainsMono.variable}`}>
      <body>{children}</body>
    </html>
  );
}

Spacing & Border Radius

Customize the spacing scale and border radius:

tokens.css
ReactTailwind
TSX
:root {
  /* Tighter spacing scale */
  --spacing-1: 0.125rem;
  --spacing-2: 0.25rem;
  --spacing-3: 0.5rem;
  --spacing-4: 0.75rem;

  /* More rounded corners */
  --radius-sm: 0.375rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;
}

Component-Level Customization

Since you own the component code, you can customize individual components directly. Here are some approaches:

1. Modify the CVA variants

// In button.tsx, add or modify variants
const buttonVariants = cva("...", {
  variants: {
    variant: {
      // Add your custom variant
      brand: "bg-brand-500 text-white hover:bg-brand-600",
    },
  },
});

2. Override with className

// Override styles at usage time
<Button className="bg-purple-500 hover:bg-purple-600">
  Custom Button
</Button>

3. Create component wrappers

// Create a pre-styled version
import { Button, ButtonProps } from "@/components/ui";

export function BrandButton(props: ButtonProps) {
  return (
    <Button
      {...props}
      className={cn(
        "bg-brand-500 hover:bg-brand-600",
        props.className
      )}
    />
  );
}

Next Steps