Theming
Learn how the color system works and how to customize the look and feel of Flux Dashboard.
OKLCh Color Tokens
All colors are defined as CSS custom properties using the OKLCh color space. OKLCh provides perceptually uniform lightness, making it easier to create consistent color palettes. The tokens are defined in src/app/globals.css.
:root {
--primary: oklch(0.55 0.25 285); /* Vivid violet */
--accent: oklch(0.60 0.20 230); /* Electric blue */
--primary-foreground: oklch(0.985 0.002 285);
--background: oklch(0.985 0.002 285);
--foreground: oklch(0.145 0.02 285);
--card: oklch(1 0 0);
--muted: oklch(0.96 0.005 285);
--muted-foreground: oklch(0.556 0.015 285);
--border: oklch(0.922 0.005 285);
/* ... more tokens */
}The OKLCh format is oklch(lightness chroma hue) where lightness is 0–1, chroma is 0–0.4, and hue is 0–360 degrees. Tailwind CSS v4 maps these tokens through the @theme inline block at the top of globals.css.
Changing the Primary Color
To change the primary color, update the --primary token in both the :root (light) and .dark blocks. For example, to switch from violet to magenta:
/* Light mode */
:root {
--primary: oklch(0.55 0.25 310); /* hue 285 → 310 (magenta) */
--primary-foreground: oklch(0.985 0.002 310);
--ring: oklch(0.55 0.25 310);
}
/* Dark mode */
.dark {
--primary: oklch(0.65 0.22 310);
--primary-foreground: oklch(0.09 0.015 285);
--ring: oklch(0.65 0.22 310);
}The change propagates everywhere bg-primary, text-primary, or ring-primary is used — buttons, links, active states, charts, and sidebar accents all update automatically.
Semantic Color Tokens
The design system uses semantic names rather than raw color values. Each token has a foreground counterpart for text that sits on top of it:
| Token | Purpose |
|---|---|
| --primary | Brand color, buttons, active states |
| --secondary | Secondary actions, subtle backgrounds |
| --muted | Muted backgrounds, code blocks |
| --accent | Hover states, highlights |
| --destructive | Error states, delete actions |
| --success | Success indicators, positive trends |
| --warning | Warning badges, caution states |
| --chart-1 to --chart-5 | Chart color palette (5 colors) |
| --sidebar-* | Sidebar-specific tokens (dark sidebar in light mode) |
Flux Signature CSS Classes
Flux Dashboard ships with a set of utility CSS classes that capture the template's signature visual language. These are defined in globals.css and can be applied to any element:
| Class | Effect |
|---|---|
| flux-shadow | Colored layered box-shadow with primary/accent tint |
| flux-glow | Gradient glow effect on hover (for buttons) |
| flux-frosted | Frosted glass effect with backdrop-blur |
| flux-gradient-text | Gradient-clipped text (primary to accent) |
| flux-dot-grid | Radial-gradient dot pattern background |
{/* Frosted glass card with colored shadow */}
<div className="flux-frosted flux-shadow rounded-xl p-6">
<h3 className="flux-gradient-text text-xl font-bold">Revenue</h3>
<p className="text-muted-foreground">+12.5% this month</p>
</div>
{/* Glowing call-to-action button */}
<button className="flux-glow rounded-lg bg-primary px-4 py-2 text-primary-foreground">
Upgrade Plan
</button>
{/* Dot grid decorative background */}
<section className="flux-dot-grid relative min-h-[200px] rounded-xl">
<div className="relative z-10 p-8">Content on top of dot grid</div>
</section>Dark Mode
Dark mode is implemented by toggling a .dark class on the <html> element. The ThemeProvider component from @dashboardpack/core/providers/theme-provider manages the state and persists the preference to localStorage. The Tailwind dark variant is configured in globals.css:
@custom-variant dark (&:is(.dark *));This allows you to use dark:bg-slate-900 classes in your components, and the .dark block in globals.css overrides all semantic tokens for dark mode.
Using the Theme Provider
The useTheme hook provides access to the current theme and a setter:
"use client";
import { useTheme } from "@dashboardpack/core/providers/theme-provider";
export function MyComponent() {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
Current theme: {theme}
</button>
);
}Supported values are "light", "dark", and "system". The system option follows the user's OS preference and reacts to changes in real time.
Theme Customizer
Flux Dashboard includes a live Theme Customizer accessible via the palette icon in the header. It opens as a slide-out drawer panel where you can preview every change in real time without refreshing the page. The Customizer controls the following settings:
- Color Presets — 6 built-in palettes: Default (Violet), Neon, Midnight, Aurora, Ember, and Graphite. Each preset swaps the full set of OKLCh tokens at runtime, instantly recoloring every component, chart, and sidebar accent across the entire dashboard.
- Density — Three levels: Compact, Default, and Comfortable. Adjusts spacing, padding, and font sizes globally via CSS custom properties, letting you fit more data on screen or give content room to breathe.
- Layout — Choose between the default Sidebar layout (fixed left navigation) or a Horizontal Top-Nav layout where the main navigation runs across the top of the page.
- Container — Fluid (full-width, edge-to-edge content) or Boxed (max-width centered container with side margins for a more traditional feel).
- Direction — Toggle between LTR (left-to-right) and RTL (right-to-left) text direction for multilingual support.
- Reset — A single button that restores all settings to their defaults (Default Violet preset, Default density, Sidebar layout, Fluid container, LTR direction).
All preferences are persisted to localStorage, so they survive page refreshes and browser restarts. The next time the user visits the dashboard, their chosen color preset, density, layout, container, and direction settings are restored automatically.
RTL Support
The entire dashboard supports right-to-left text direction for languages such as Arabic, Hebrew, Persian, and Urdu. The toggle is available in the Theme Customizer under the Direction setting. When RTL is enabled, the sidebar moves to the right, text aligns to the right, and all directional spacing flips accordingly.
The implementation relies on the following techniques:
- CSS Logical Properties — Instead of physical
ml-*/mr-*andpl-*/pr-*, all spacing uses logical equivalents:ms-*/me-*,ps-*/pe-*,text-start/text-end,border-s/border-e, androunded-s/rounded-e. These automatically flip based on the document direction. - Tailwind CSS v4 ltr:/rtl: Variants — For cases where logical properties alone are not sufficient (e.g., icon rotation, absolute positioning, transform origins), Tailwind's
ltr:andrtl:variants apply direction-specific styles conditionally. - dir attribute on HTML element — The Theme Customizer sets
dir="rtl"on the<html>element, which browsers use natively to reverse text flow, scroll direction, and table column order. - Inline Script Prevents Flash — A small inline script in the
<head>reads the saved direction preference from localStorage and applies thedirattribute before the page renders. This prevents a flash of incorrect direction (FOID) on page load, similar to how the theme script prevents a flash of incorrect theme.
<!-- Example: classes that work in both LTR and RTL -->
<div className="ms-4 me-2 ps-3 pe-3 text-start border-s-2">
Content flows correctly in both directions
</div>
<!-- Example: direction-specific overrides -->
<ChevronRight className="size-4 ltr:rotate-0 rtl:rotate-180" />Next Steps
See Components for a full list of available UI primitives, or learn how to add new pages to the dashboard.