Overview
Lambda UI Components features a powerful theming system built on CSS variables, providing flexible and customizable styling for all components. The library includes eight built-in themes (six light themes and two dark themes) with automatic dark/light mode support.
Available Themes
The library includes eight pre-configured themes:
Light Themes
- light - Clean, modern light theme with cyan accents
- retro - Warm, vintage-inspired theme with orange accents
- lavender - Soft & elegant theme with violet and pink accents
- mint - Fresh & natural theme with emerald and blue accents
- sunset - Energetic & vibrant theme with rose and yellow accents
- ocean - Corporate & trustworthy theme with blue and emerald accents
Dark Themes
- dark - Sleek dark theme with teal accents
- slate - Cool, sophisticated dark theme with cyan accents
- graphite - Neutral charcoal dark theme with minimal color saturation
- deep-cosmic-night - Deep purple-tinted dark theme with cosmic violet accents
- soft-obsidian - Soft blue-black dark theme with muted blue undertones
- midnight - Ultra-dark purple theme with deep violet accents
Setup
To enable theming in your application, wrap your app with the ThemeProvider component at the root level:
import { ThemeProvider } from "lambda-ui-components";
export default function App({ children }) {
return (
<ThemeProvider
defaultTheme="dark"
enableSystem={true}
disableTransitionOnChange={false}
lightTheme="light"
darkTheme="dark"
>
{children}
</ThemeProvider>
);
}View all properties of the ThemeProvider component in the table below: Props
ButtonTheme Component
The ButtonTheme component provides a pre-built toggle button for switching between light and dark themes:
import { ButtonTheme } from "lambda-ui-components";
function Header() {
return (
<header>
<h1>My App</h1>
<ButtonTheme
animation="scale"
color="neutral"
size="medium"
/>
</header>
);
}CSS Variables
All themes are built using CSS variables, making them highly customizable. Each theme defines variables for:
- Colors - Background, foreground, surfaces, borders, shadows
- Accent Colors - Primary, secondary, neutral, success, danger, warning, info
- Typography - Font sizes, weights, families
- Spacing - Padding, gaps, margins
- Borders - Radius, widths
- Component Sizes - Buttons, inputs, icons, badges, etc.
Example of accessing theme variables in your custom CSS:
.my-custom-component {
background-color: var(--background-color);
color: var(--foreground-color);
border: 1px solid var(--border-color);
padding: var(--spacing-md);
border-radius: var(--radius-md);
}
.my-accent-button {
background-color: var(--primary-base-color);
color: var(--foreground-invert-color);
}
.my-accent-button:hover {
background-color: var(--primary-hover-color);
}Theme Persistence
The theme preference is automatically saved to localStorage and persists across sessions. The theme is also synchronized across browser tabs.
The ThemeProvider includes a script that runs before the page renders to prevent flash of unstyled content (FOUC) when loading the saved theme.
System Theme Detection
When enableSystem is true and the theme is set to "system", the library automatically detects and applies the user's system color scheme preference using the prefers-color-scheme media query.
The theme automatically updates when the user changes their system preference, without requiring a page reload.
Next.js Integration
For Next.js applications, wrap your app with ThemeProvider in a client component:
// app/providers.tsx
"use client";
import { ThemeProvider } from "lambda-ui-components";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
);
}
// app/layout.tsx
import { Providers } from "./providers";
export default function RootLayout({ children }) {
return (
<html suppressHydrationWarning>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}Note: Add suppressHydrationWarning to the <html> tag to prevent hydration warnings caused by the theme script.
Theme-Specific Styling
You can apply styles conditionally based on the active theme using the data-theme attribute selector:
/* Styles for all themes */
.my-component {
padding: 1rem;
}
/* Styles only for light theme */
[data-theme="light"] .my-component {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Styles only for dark themes */
[data-theme="dark"] .my-component,
[data-theme="slate"] .my-component {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}
/* Styles only for retro theme */
[data-theme="retro"] .my-component {
border: 2px solid var(--border-color);
}ThemeProvider API
Props
Prop | Default | Type |
|---|---|---|
defaultTheme | "system" (if enableSystem is true) or "dark" | "light" | "dark" | "retro" | "slate" | "lavender" | "mint" | "sunset" | "ocean" | "graphite" | "deep-cosmic-night" | "soft-obsidian" | "midnight" | "system" |
lightTheme | "light" | "light" | "retro" | "lavender" | "mint" | "sunset" | "ocean" |
darkTheme | "dark" | "dark" | "slate" | "graphite" | "deep-cosmic-night" | "soft-obsidian" | "midnight" |
enableSystem | true | boolean |
disableTransitionOnChange | false | boolean |
enableColorScheme | false | boolean |
storageKey | "theme" | string |
attribute | "data-theme" | "class" | "data-*" | string[] |
themes | ["light", "dark", "retro", "slate"] | AllThemes[] |
forcedTheme | undefined | "light" | "dark" | "retro" | "slate" | "system" |
nonce | undefined | string |
ButtonTheme API
Props
Prop | Default | Type |
|---|---|---|
animation | "scale" | "fade" | "rotate" | "scale" | "flip" | "slide" | "none" |
color | "neutral" | LambdaColor |
{...ButtonProps} | undefined | ButtonProps |