Themes
Zen supports light and dark themes out of the box. Themes are applied using CSS custom properties that automatically adjust colors, backgrounds, and borders based on the active theme.
Setup
Wrap your application with ZenProvider to enable theme support.
import { ZenProvider } from '@umami/react-zen';
function App() {
return (
<ZenProvider>
<YourApp />
</ZenProvider>
);
}Theme options
You can configure the initial theme using the theme or colorScheme props.
// Force a specific theme
<ZenProvider theme="dark">
// Use system preference
<ZenProvider colorScheme="system">
// Default to light, but respect system preference
<ZenProvider colorScheme="light">ThemeButton
Use the ThemeButton component to let users toggle between light and dark themes.
<ThemeButton variant="outline" />Local themes
You can scope theme changes to a specific container using the target prop. This allows parts of your UI to have a different theme than the rest of the page.
function LocalThemeExample() {
const containerRef = useRef(null);
return (
<Box ref={containerRef} padding="6" backgroundColor="surface-base">
<Row alignItems="center" justifyContent="space-between">
<Text>This container has its own theme</Text>
<ThemeButton target={containerRef} />
</Row>
</Box>
);
}useTheme hook
Access and control the current theme programmatically with the useTheme hook.
import { useTheme } from '@umami/react-zen';
function MyComponent() {
const { theme, setTheme } = useTheme();
return (
<Button onPress={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</Button>
);
}CSS variables
Themes work by redefining CSS custom properties. The following variables change based on the active theme:
| Variable | Description |
|---|---|
| --surface-base | Primary background color |
| --surface-raised | Elevated surface background |
| --surface-sunken | Recessed surface background |
| --surface-overlay | Overlay/modal background |
| --text-primary | Primary text color |
| --text-muted | Muted/subtle text color |
| --border-default | Default border color |
| --border-strong | Emphasized border color |
| --interactive-bg | Interactive element background |
| --primary | Primary/accent color |
Theme persistence
Theme preference is automatically saved to localStorage under the key theme. When the page loads, the stored preference is restored.
Dark mode classes
Zen applies both data-theme="dark" attribute and the .dark class to the root element for maximum compatibility with Tailwind CSS and other frameworks.
Color palettes
Zen supports multiple gray-scale palettes inspired by Tailwind CSS. Each palette has a different color temperature and character.
Available palettes
| Palette | Description |
|---|---|
| neutral | Pure gray with no color tint (default) |
| slate | Cool blue-gray tones |
| gray | Slight blue tint |
| zinc | Subtle blue undertones |
| stone | Warm tan/brown tones |
Setting the palette
You can set the palette via ZenProvider or programmatically with useTheme.
// Via provider
<ZenProvider palette="slate">
<YourApp />
</ZenProvider>
// Programmatically
const { palette, setPalette } = useTheme();
setPalette('zinc');PaletteSwitcher
Use the PaletteSwitcher component to let users switch between palettes.
<PaletteSwitcher />Palette persistence
Palette preference is automatically saved to localStorage under the key zen.palette. The data-palette attribute is applied to the root element.