What is a theme
How ViraUI theme CSS, tokens, and data-mode turn one stylesheet into your app’s look.
A theme is one stylesheet of --* design tokens. Swap the import and the same @viraui/react components pick up a different brand — a built-in preset from @viraui/foundation, or a custom sheet. How that sheet lands in the app (import order, fonts, preflight) is covered in Setup; what the tokens mean by name is in Foundation.
Light and dark
Light and dark are not separate themes, they are two modes of the same theme. Built-in presets pair both modes in one sheet with CSS light-dark() — for example --global-background: light-dark(…light…, …dark…). Preflight maps data-mode on the document root to color-scheme, so flipping the attribute resolves every paired token without swapping stylesheets.
<html lang="en" data-mode="light">data-mode accepts light, dark, or inverted. Use light or dark on the root for the active scheme; use inverted on a nested island when that subtree should flip against its parent. Preflight ignores system and auto, so the app (or a theme library) must always write light or dark into the attribute. Brand is which theme stylesheet you imported; mode is which side of that sheet’s light-dark() pairs resolves.
Wire mode in your app
Point any theme manager at data-mode with theme names light / dark. Paste the prompt for your stack:
Wire light/dark mode for ViraUI in this Next.js App Router app with next-themes.
Install next-themes. Add a client ThemeProvider with attribute="data-mode", defaultTheme="system", enableSystem, and disableTransitionOnChange. Wrap the root layout children with it. Put suppressHydrationWarning on <html>. Theme names must resolve to data-mode="light" or data-mode="dark" on the document (system preference is fine as input, but never leave data-mode as system/auto — preflight only understands light|dark|inverted). Do not swap theme CSS for mode changes. Add a simple light/dark/system toggle using useTheme().setTheme. Report what you changed.For a custom theme, keep the same light-dark() pairs on tokens that change with scheme (--global-*, --highlight-*, --base-*). Mode-invariant tokens can stay plain. Other pairing strategies work if every semantic token still resolves — just do not treat a second dark stylesheet as the brand swap.
Last updated on