---
name: "naive-ui-dark-mode"
description: "Dark mode implementation and theme switching for Naive UI applications. Invoke when user needs to implement dark/light theme switching, follow system preferences, or customize dark theme variables."
metadata:
author: jiaiyan
version: "1.0.0"
---
# Naive UI Dark Mode
Naive UI provides built-in support for dark mode through the `n-config-provider` component. This skill covers implementing dark mode, following system preferences, and customizing dark theme variables.
## When to Use
Use this skill when:
- **Theme switching**: Implementing dark/light mode toggle
- **System preference**: Following OS dark mode settings
- **Dark theme customization**: Customizing dark theme variables
- **Global dark styles**: Applying dark mode to the entire page
- **Persistent dark mode**: Saving user theme preference
## When to Invoke
Invoke this skill when:
- User asks how to implement dark mode in Naive UI
- User wants to toggle between light and dark themes
- User needs to follow system dark mode preference
- User wants to customize dark theme colors
- User asks about applying dark mode globally
- User encounters issues with dark mode styling
## Prerequisites
- Naive UI installed (`npm install naive-ui`)
- Vue 3 application setup
- Basic understanding of `n-config-provider`
## API Reference
### Theme Objects
| Theme | Import | Description |
|-------|--------|-------------|
| Light Theme | `import { lightTheme } from 'naive-ui'` | Default light theme (used when theme is `null`) |
| Dark Theme | `import { darkTheme } from 'naive-ui'` | Built-in dark theme |
### Theme Prop Values
| Value | Behavior |
|-------|----------|
| `undefined` | Inherits from parent `n-config-provider` |
| `null` | Uses default light theme |
| `darkTheme` | Applies dark theme |
### useOsTheme Hook
```ts
import { useOsTheme } from 'naive-ui'
const osTheme = useOsTheme()
// Returns: Ref<'dark' | 'light' | 'no-preference' | 'unknown'>
```
### useThemeVars Hook
```ts
import { useThemeVars } from 'naive-ui'
const themeVars = useThemeVars()
// Returns: Reactive theme variables object
```
## Basic Usage
### Simple Dark Mode Toggle
```vue
Dark ModeLight ModePrimary Button
```
### Follow System Theme Preference
```vue
Current system theme: {{ osTheme }}
Button adapts to system theme
```
### Dark Mode with Global Styles
```vue
Dark
Light
Body background also changes!
```
## Common Patterns
### Persistent Dark Mode with localStorage
```vue
Dark
Light
```
### Dark Mode with Custom Theme Overrides
```vue
Custom Primary Color
```
### System Preference with Manual Override
```vue
LightDarkSystemTheme Button
```
### Using Theme Variables
```vue
Current primary color: {{ themeVars.primaryColor }}
Primary
```
### Nested Theme Configuration
```vue
Light Button
```
## Best Practices
1. **Use n-global-style**: Always include `` to apply theme to body
```vue
```
2. **Persist user preference**: Save theme choice to localStorage
```js
watch(isDark, (value) => {
localStorage.setItem('theme', value ? 'dark' : 'light')
})
```
3. **Provide system option**: Allow users to follow OS preference
```js
import { useOsTheme } from 'naive-ui'
const osTheme = useOsTheme()
```
4. **Customize dark theme separately**: Use different overrides for light and dark
```js
const themeOverrides = computed(() =>
isDark.value ? darkOverrides : lightOverrides
)
```
5. **Use computed for reactivity**: Make theme reactive with computed properties
```js
const theme = computed(() => isDark.value ? darkTheme : null)
```
6. **Avoid flash of wrong theme**: Set theme before app mounts
```js
const savedTheme = localStorage.getItem('theme')
const isDark = ref(savedTheme === 'dark')
```
7. **Test both themes**: Verify all components look correct in both modes
8. **Consider SSR**: Handle dark mode properly in server-side rendering
```vue
```
## Common Dark Theme Variables
```ts
const darkThemeOverrides = {
common: {
bodyColor: '#1c1c1e',
cardColor: '#2c2c2e',
modalColor: '#2c2c2e',
popoverColor: '#2c2c2e',
tableColor: '#2c2c2e',
textColorBase: '#ffffff',
textColor1: '#ffffff',
textColor2: 'rgba(255, 255, 255, 0.82)',
textColor3: 'rgba(255, 255, 255, 0.56)',
primaryColor: '#63E2B7',
primaryColorHover: '#7FE7C5',
primaryColorPressed: '#5acea7',
infoColor: '#70C0E8',
successColor: '#63E2B7',
warningColor: '#F2C97D',
errorColor: '#E88080',
borderColor: 'rgba(255, 255, 255, 0.12)',
dividerColor: 'rgba(255, 255, 255, 0.12)'
}
}
```
## Troubleshooting
### Body Background Not Changing
**Problem**: Dark mode applies to components but body remains light
**Solution**: Add `` inside `n-config-provider`
```vue
```
### Flash of Light Theme on Load
**Problem**: Page briefly shows light theme before switching to dark
**Solution**: Load theme preference before app renders
```js
const savedTheme = localStorage.getItem('theme')
const isDark = ref(savedTheme === 'dark')
```
### Theme Not Persisting
**Problem**: Theme resets on page reload
**Solution**: Watch and save theme changes
```js
watch(isDark, (value) => {
localStorage.setItem('theme', value ? 'dark' : 'light')
}, { immediate: true })
```
## Related Skills
- [n-config-provider](../components/n-config-provider/SKILL.md): Global configuration component
- [n-global-style](../components/n-global-style/SKILL.md): Global style synchronization
- [naive-ui-theming](../naive-ui-theming/SKILL.md): Theme customization guide
- [naive-ui-ssr](../naive-ui-ssr/SKILL.md): SSR considerations for dark mode