diff --git a/src/core/components/VTSwitchAppearance.vue b/src/core/components/VTSwitchAppearance.vue
index 820f58a..67f7977 100644
--- a/src/core/components/VTSwitchAppearance.vue
+++ b/src/core/components/VTSwitchAppearance.vue
@@ -1,48 +1,13 @@
diff --git a/src/core/composables/SwitchAppearance.ts b/src/core/composables/SwitchAppearance.ts
new file mode 100644
index 0000000..8cb2aaf
--- /dev/null
+++ b/src/core/composables/SwitchAppearance.ts
@@ -0,0 +1,43 @@
+import { ref } from 'vue'
+
+export function useSwitchAppearance() {
+ return { isDark, toggle }
+}
+
+const storageKey = 'vitepress-theme-appearance'
+const { isDark, toggle } =
+ typeof localStorage !== 'undefined'
+ ? useAppearance()
+ : { isDark: false, toggle: () => {} }
+
+function useAppearance() {
+ let userPreference = localStorage.getItem(storageKey) || 'auto'
+ const query = window.matchMedia(`(prefers-color-scheme: dark)`)
+ const classList = document.documentElement.classList
+ const isDark = ref(
+ userPreference === 'auto' ? query.matches : userPreference === 'dark'
+ )
+ const setClass = (dark: boolean) => classList[dark ? 'add' : 'remove']('dark')
+
+ query.onchange = (e) => {
+ if (userPreference === 'auto') {
+ setClass((isDark.value = e.matches))
+ }
+ }
+
+ const toggle = () => {
+ setClass((isDark.value = !isDark.value))
+ localStorage.setItem(
+ storageKey,
+ (userPreference = isDark.value
+ ? query.matches
+ ? 'auto'
+ : 'dark'
+ : query.matches
+ ? 'light'
+ : 'auto')
+ )
+ }
+
+ return { isDark, toggle }
+}