Light/dark mode, 8 accent colors, system preference detection. Zero configuration, automatic persistence.
Simple, intuitive theme control
import { theme } from '@noundryfx/nounjs'
// Set theme mode
theme.set('dark') // Force dark mode
theme.set('light') // Force light mode
theme.set('system') // Follow OS preference
// Toggle between light and dark
theme.toggle()
// Set accent color
theme.accent('emerald') // Green
theme.accent('rose') // Pink
theme.accent('indigo') // Purple
// Get current theme
const { mode, accent } = theme.current()
// Subscribe to changes
theme.onChange(({ mode, accent }) => {
console.log('Theme changed:', mode, accent)
})
Seamlessly switch between light and dark themes. All components automatically adapt.
Choose from blue, indigo, violet, emerald, teal, rose, amber, or orange. Instantly applied across all components.
Works out of the box. Automatically persists to localStorage. No setup required.
Automatically detect and follow the user's OS color scheme preference.
Nounjs includes 8 carefully crafted accent color palettes. Each provides a full range from light to dark for consistent theming.
// Set accent color
theme.accent('emerald')
// Get available colors
const colors = theme.accents()
// ['blue', 'indigo', 'violet', 'emerald', 'teal', 'rose', 'amber', 'orange']
The theme system provides semantic CSS variables that automatically adapt to light/dark mode and the selected accent color. Use these in your own components for consistent theming.
/* Backgrounds */
var(--noun-bg) /* Main background */
var(--noun-bg-secondary) /* Secondary bg */
var(--noun-bg-tertiary) /* Tertiary bg */
var(--noun-bg-elevated) /* Cards, modals */
/* Text */
var(--noun-text) /* Primary text */
var(--noun-text-secondary) /* Secondary text */
var(--noun-text-muted) /* Muted text */
var(--noun-text-inverse) /* On dark bg */
/* Primary (uses accent) */
var(--noun-primary) /* Main color */
var(--noun-primary-hover) /* Hover state */
var(--noun-primary-text) /* Text on light */
/* Status */
var(--noun-success) /* Green */
var(--noun-danger) /* Red */
var(--noun-warning) /* Amber */
/* Each has -light and -text */
var(--noun-success-light)
var(--noun-success-text)
.my-card {
background: var(--noun-bg-elevated);
color: var(--noun-text);
border: 1px solid var(--noun-border);
border-radius: var(--noun-radius-lg);
box-shadow: var(--noun-shadow);
}
.my-button {
background: var(--noun-primary);
color: var(--noun-text-inverse);
border-radius: var(--noun-radius);
transition: all var(--noun-transition);
}
.my-button:hover {
background: var(--noun-primary-hover);
}
The Nounjs Starter includes a ready-to-use ThemeSwitcher component with dropdown for mode selection and accent color picker.
import { theme } from '@noundryfx/nounjs'
export default {
currentMode: 'light',
currentColor: 'blue',
mounted() {
// Get initial state
const { mode, accent } = theme.current()
this.currentMode = mode
this.currentColor = accent
// Subscribe to changes
this._unsubscribe = theme.onChange(({ mode, accent }) => {
this.currentMode = mode
this.currentColor = accent
})
},
unmounted() {
this._unsubscribe?.()
},
setMode(mode) {
theme.set(mode)
},
setColor(color) {
theme.accent(color)
}
}
Nounjs Starter
Clone the Nounjs Starter to see the complete ThemeSwitcher implementation with UI.
| Method | Description |
|---|---|
theme.set(mode) |
Set theme mode: 'light', 'dark', or 'system' |
theme.toggle() |
Toggle between light and dark mode |
theme.accent(color) |
Set accent color from available presets |
theme.current() |
Returns { mode, accent } with current theme state |
theme.accents() |
Returns array of available accent color names |
theme.onChange(fn) |
Subscribe to theme changes. Returns unsubscribe function. |
theme.useSystem() |
Shorthand for theme.set('system') |
For advanced use cases, you can also control the theme via HTML attributes:
<!-- Force dark mode -->
<html class="dark">
<!-- Set accent color -->
<html data-accent="emerald">
<!-- Both -->
<html class="dark" data-accent="rose">