How to Customize the Theme Using Celeris Web's Theme Setting System
Celeris Web centralizes all visual customization in a ThemeSetting object managed by the Pinia store useDesignStore, enabling reactive theme updates—including primary colors, dark mode toggles, and system preference tracking—through the useThemeSetting composable API.
The open-source celeris-web repository provides a robust theme setting system built on Pinia and Naive UI. This architecture allows developers to programmatically control every aspect of the application's appearance through a centralized, reactive configuration layer that updates the UI without page reloads.
Understanding the Theme Architecture
The theme setting system implements a five-layer architecture that separates default values, state management, public API abstractions, theme generation, and UI provider injection.
1. Default Configuration Layer
All theme defaults reside in DEFAULT_THEME_SETTING defined in apps/admin/src/setting/themeSetting.ts. This object initializes the default states for gray mode, dark mode, system-follow behavior, primary color, and auxiliary color tokens.
2. State Management with Pinia
The useDesignStore in apps/admin/src/store/modules/design/index.ts maintains the themeSetting state and exposes type-safe getters such as getDarkMode, getThemeColor, shouldEnableGrayMode, and shouldFollowSystemTheme. The store uses deepMerge to apply partial updates without destroying existing configuration objects.
3. Public API via Composables
The useThemeSetting composable in apps/admin/src/composables/setting/useThemeSetting.ts wraps the store with reactive toRef bindings. It exposes getter and setter pairs—including getDarkMode/setDarkMode, getThemeColor/setThemeColor, and setFollowSystemTheme—which serve as the primary interface for UI components.
4. Theme Generation Engine
When Naive UI requires concrete theme values, getNaiveUICustomTheme in apps/admin/src/store/modules/design/themeUtils.ts executes. This function builds color palettes via generateColorPalettes (which supports dark-mode awareness), merges them into Naive UI's common overrides, and applies component-specific fixes for button text, checkbox ticks, and other interactive elements.
5. Provider Injection
The useNaiveUIConfigProvider composable in apps/admin/src/composables/useNaiveUIConfigProvider.ts supplies the root n-config-provider with either lightTheme or darkTheme presets plus the custom overrides. This ensures all Naive UI components receive reactive theme updates prop-drilled from the application root.
Customizing Theme Settings
Developers modify specific visual aspects through targeted API calls. Each change propagates reactively through the store to the UI without requiring navigation or refresh.
Changing the Primary Color
Call setThemeColor() with a hex value, or modify DEFAULT_THEME_SETTING.themeColor directly. The themeUtils.ts palette generator creates new light and dark color shades automatically and merges them into Naive UI's common overrides.
Managing Dark Mode
Use setDarkMode(boolean) to toggle between themes. The getDarkMode getter determines which preset theme (darkTheme or lightTheme) the Config Provider passes to Naive UI components.
Following System Preferences
Enable setFollowSystemTheme(true) to synchronize with OS dark-mode settings. The store monitors usePreferredDark() and automatically switches presets when system appearance preferences change.
Configuring Auxiliary Colors
Extend otherColor tokens (info, success, warning, error) by calling setThemeSetting({ otherColor: {...} }) or editing the default configuration. These values inject component-level overrides via themeUtils.getOtherColor().
Accessibility Modes
Toggle shouldEnableGrayMode or shouldEnableColorWeak via their respective setters. These boolean flags apply CSS classes to layout wrappers, enabling grayscale or high-contrast rendering for accessibility compliance.
Implementation Examples
Runtime Primary Color Updates
import { useThemeSetting } from '~/composables/setting'
const { setThemeColor } = useThemeSetting()
function onColorPick(colorHex: string) {
// Color picker returns '#1890ff' or similar
setThemeColor(colorHex)
}
Dark Mode Toggle
import { useThemeSetting } from '~/composables/setting'
const { setDarkMode } = useThemeSetting()
// Handler for toggle switch
function toggleDark(checked: boolean) {
setDarkMode(checked)
}
System Theme Synchronization
import { useThemeSetting } from '~/composables/setting'
const { setFollowSystemTheme } = useThemeSetting()
// Application now mirrors OS appearance settings
setFollowSystemTheme(true)
Extending Color Palettes
import { useThemeSetting } from '~/composables/setting'
const { setThemeSetting } = useThemeSetting()
setThemeSetting({
otherColor: {
info: '#2db7f5',
success: '#52c41a',
warning: '#faad14',
error: '#f5222d',
},
})
App.vue Config Provider Setup
<script setup lang="ts">
import { useNaiveUIConfigProvider } from '~/composables/useNaiveUIConfigProvider'
const { configProviderProps } = useNaiveUIConfigProvider()
</script>
<template>
<n-config-provider v-bind="configProviderProps">
<router-view />
</n-config-provider>
</template>
Key Files in the Theme System
apps/admin/src/setting/themeSetting.ts– ContainsDEFAULT_THEME_SETTINGwith initial theme valuesapps/admin/src/store/modules/design/index.ts– Pinia store holdingthemeSettingstate anddeepMergeactionsapps/admin/src/composables/setting/useThemeSetting.ts– Public composable façade exposing reactive getters and settersapps/admin/src/store/modules/design/themeUtils.ts– Generates color palettes and Naive UI theme overridesapps/admin/src/composables/useNaiveUIConfigProvider.ts– Supplies the computed theme to Naive UI's providerpackages/web/types/src/config.ts– TypeScript interface definitions forThemeSetting
Summary
- Theme customization centers on the ThemeSetting object managed by useDesignStore.
- The useThemeSetting composable provides the public API for reactive theme control with
toRefbindings. - generateColorPalettes in
themeUtils.tscreates dark-aware color scales automatically. - All changes propagate immediately through Naive UI's ConfigProvider without page reloads.
- The system supports primary color customization, manual dark mode toggling, OS preference following, and auxiliary color token injection.
Frequently Asked Questions
Where are default theme values defined in Celeris Web?
Default theme values are defined in the DEFAULT_THEME_SETTING object located at apps/admin/src/setting/themeSetting.ts. This file initializes all default states including the primary color, gray mode settings, and auxiliary color tokens for info, success, warning, and error states.
How does the theme setting system handle dark mode switching?
The system uses the getDarkMode getter in useDesignStore to determine the active theme preset. When setDarkMode is called with a boolean value, the store updates its state, triggering useNaiveUIConfigProvider to switch between lightTheme and darkTheme presets and regenerate color palettes accordingly.
Can the application automatically follow the operating system's dark mode preference?
Yes. Call setFollowSystemTheme(true) from the useThemeSetting composable. This enables the store to monitor usePreferredDark() and automatically toggle between light and dark themes based on the user's OS appearance settings without manual intervention.
How do I add custom brand colors beyond the primary color?
Use the setThemeSetting method to update the otherColor property with custom hex values for info, success, warning, and error tokens. These values propagate through apps/admin/src/store/modules/design/themeUtils.ts to generate component-specific overrides that apply throughout the Naive UI component library.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →