useDark
Reactive dark mode with auto data persistence.
Demo
Basic Usage
import { useDark, useToggle } from '@vueuse/core'
const isDark = useDark()
const toggleDark = useToggle(isDark)
import { useDark, useToggle } from '@vueuse/core'
const isDark = useDark()
const toggleDark = useToggle(isDark)
Behavior
useDark
combines with usePreferredDark
and useStorage
On start up, it reads the value from localStorage/sessionStorage(the key is configurable) to see if there is a user configured color scheme, if not, it will use users' system preferences. When you change the isDark
ref, it will update the corresponding element's attribute and then store the preference to storage for persistence.
Please note
useDark
only handles the DOM attribute changes for you to apply proper selector in your CSS. It does NOT handle the actual style, theme or CSS for you.
Configuration
By default, it uses Tailwind CSS favored dark mode, which enables dark mode when class dark
is applied to the html
tag, for example:
<!--light-->
<html> ... </html>
<!--dark-->
<html class="dark"> ... </html>
<!--light-->
<html> ... </html>
<!--dark-->
<html class="dark"> ... </html>
While you can customize it and make it work for most of the CSS frameworks.
For example:
const isDark = useDark({
selector: 'body',
attribute: 'color-scheme',
valueDark: 'dark',
valueLight: 'light',
})
const isDark = useDark({
selector: 'body',
attribute: 'color-scheme',
valueDark: 'dark',
valueLight: 'light',
})
will work like
<!--light-->
<html>
<body color-scheme="light"> ... </body>
</html>
<!--dark-->
<html>
<body color-scheme="dark"> ... </body>
</html>
<!--light-->
<html>
<body color-scheme="light"> ... </body>
</html>
<!--dark-->
<html>
<body color-scheme="dark"> ... </body>
</html>
If the configuration above still not fitting to your needs, you can use onChanged
options to take full controls over how you handle the updates
const isDark = useDark({
onChanged(dark: boolean) {
// update the dom, call the API or something
},
})
const isDark = useDark({
onChanged(dark: boolean) {
// update the dom, call the API or something
},
})
Component Usage
This function also provides a renderless component version via the
@vueuse/components
package. Learn more about the usage.
<UseDark v-slot="{ isDark, toggleDark }">
<button @click="toggleDark()">
Is Dark: {{ isDark }}
</button>
</UseDark>
<UseDark v-slot="{ isDark, toggleDark }">
<button @click="toggleDark()">
Is Dark: {{ isDark }}
</button>
</UseDark>
Type Declarations
export interface UseDarkOptions
extends Omit<UseColorModeOptions<BasicColorSchema>, "modes" | "onChanged"> {
/**
* Value applying to the target element when isDark=true
*
* @default 'dark'
*/
valueDark?: string
/**
* Value applying to the target element when isDark=false
*
* @default ''
*/
valueLight?: string
/**
* A custom handler for handle the updates.
* When specified, the default behavior will be overridded.
*
* @default undefined
*/
onChanged?: (isDark: boolean) => void
}
/**
* Reactive dark mode with auto data persistence.
*
* @see https://vueuse.org/useDark
* @param options
*/
export declare function useDark(
options?: UseDarkOptions
): WritableComputedRef<boolean>
export interface UseDarkOptions
extends Omit<UseColorModeOptions<BasicColorSchema>, "modes" | "onChanged"> {
/**
* Value applying to the target element when isDark=true
*
* @default 'dark'
*/
valueDark?: string
/**
* Value applying to the target element when isDark=false
*
* @default ''
*/
valueLight?: string
/**
* A custom handler for handle the updates.
* When specified, the default behavior will be overridded.
*
* @default undefined
*/
onChanged?: (isDark: boolean) => void
}
/**
* Reactive dark mode with auto data persistence.
*
* @see https://vueuse.org/useDark
* @param options
*/
export declare function useDark(
options?: UseDarkOptions
): WritableComputedRef<boolean>
Source
Contributors
Anthony Fu
wheat
云游君
Mehran Mirshekaran
Máximo Mussini
Pig Fang
Alex Kozack
ordago
Le Minh Tri