Skip to content

Commit 7f0d841

Browse files
committed
明暗模式设置为跟随系统时,支持动态切换
1 parent 2a3700f commit 7f0d841

File tree

5 files changed

+61
-23
lines changed

5 files changed

+61
-23
lines changed

src/layouts/components/AppSetting/index.vue

+9-10
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@ const menuStore = useMenuStore()
1717
1818
const isShow = ref(false)
1919
20-
const isDark = computed({
21-
get() {
22-
return settingsStore.settings.app.colorScheme === 'dark'
23-
},
24-
set(value) {
25-
settingsStore.settings.app.colorScheme = value ? 'dark' : 'light'
26-
},
27-
})
28-
2920
watch(() => settingsStore.settings.menu.menuMode, (value) => {
3021
if (value === 'single') {
3122
menuStore.setActived(0)
@@ -97,7 +88,15 @@ function handleCopy() {
9788
颜色主题风格
9889
</div>
9990
<div class="flex items-center justify-center pb-4">
100-
<HToggle v-model="isDark" on-icon="ri:sun-line" off-icon="ri:moon-line" />
91+
<HTabList
92+
v-model="settingsStore.settings.app.colorScheme"
93+
:options="[
94+
{ icon: 'i-ri:sun-line', label: '明亮', value: 'light' },
95+
{ icon: 'i-ri:moon-line', label: '暗黑', value: 'dark' },
96+
{ icon: 'i-ri:computer-line', label: '系统', value: '' },
97+
]"
98+
class="w-60"
99+
/>
101100
</div>
102101
<div v-if="settingsStore.mode === 'pc'" class="divider">
103102
导航栏模式

src/layouts/components/Topbar/Toolbar/ColorScheme/index.vue

+21-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const settingsStore = useSettingsStore()
99
1010
function toggleColorScheme(event: MouseEvent) {
1111
const { startViewTransition } = useViewTransition(() => {
12-
settingsStore.setColorScheme(settingsStore.settings.app.colorScheme === 'dark' ? 'light' : 'dark')
12+
settingsStore.currentColorScheme && settingsStore.setColorScheme(settingsStore.currentColorScheme === 'dark' ? 'light' : 'dark')
1313
})
1414
startViewTransition()?.ready.then(() => {
1515
const x = event.clientX
@@ -37,7 +37,24 @@ function toggleColorScheme(event: MouseEvent) {
3737
</script>
3838

3939
<template>
40-
<span class="flex-center cursor-pointer px-2 py-1" @click="toggleColorScheme">
41-
<SvgIcon :name="settingsStore.settings.app.colorScheme === 'light' ? 'i-ri:sun-line' : 'i-ri:moon-line'" />
42-
</span>
40+
<HDropdown class="flex-center cursor-pointer px-2 py-1">
41+
<SvgIcon
42+
:name="{
43+
'': 'i-ri:computer-line',
44+
'light': 'i-ri:sun-line',
45+
'dark': 'i-ri:moon-line',
46+
}[settingsStore.settings.app.colorScheme]" @click="toggleColorScheme"
47+
/>
48+
<template #dropdown>
49+
<HTabList
50+
v-model="settingsStore.settings.app.colorScheme"
51+
:options="[
52+
{ icon: 'i-ri:sun-line', label: '', value: 'light' },
53+
{ icon: 'i-ri:moon-line', label: '', value: 'dark' },
54+
{ icon: 'i-ri:computer-line', label: '', value: '' },
55+
]"
56+
class="m-3"
57+
/>
58+
</template>
59+
</HDropdown>
4360
</template>

src/layouts/ui-kit/HTabList.vue

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Tab, TabGroup, TabList } from '@headlessui/vue'
33
44
const props = defineProps<{
55
options: {
6+
icon?: string
67
label: any
78
value: T
89
}[]
@@ -37,11 +38,12 @@ function handleChange(index: number) {
3738
<TabList class="inline-flex select-none items-center justify-center rounded-md bg-stone-1 p-1 ring-1 ring-stone-2 dark:bg-stone-9 dark:ring-stone-8">
3839
<Tab v-for="(option, index) in options" :key="index" v-slot="{ selected }" as="template">
3940
<button
40-
class="w-full inline-flex items-center justify-center truncate border-size-0 rounded-md bg-inherit px-2 py-1.5 text-sm text-dark ring-stone-2 ring-inset dark:text-white focus:outline-none focus:ring-2 dark:ring-stone-8" :class="{
41+
class="w-full inline-flex items-center justify-center gap-1 break-keep border-size-0 rounded-md bg-inherit px-2 py-1.5 text-sm text-dark ring-stone-2 ring-inset dark:text-white focus:outline-none focus:ring-2 dark:ring-stone-8" :class="{
4142
'cursor-default bg-white dark:bg-dark-9': selected,
42-
'cursor-pointer opacity-50 transition hover:(opacity-100)': !selected,
43+
'cursor-pointer opacity-50 hover:(opacity-100)': !selected,
4344
}"
4445
>
46+
<SvgIcon v-if="option.icon" :name="option.icon" class="flex-shrink-0" />
4547
{{ option.label }}
4648
</button>
4749
</Tab>

src/layouts/ui-kit/HTooltip.vue

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
withDefaults(
33
defineProps<{
44
text: string
5-
enable: boolean
5+
enable?: boolean
66
}>(),
77
{
88
text: '',
@@ -20,5 +20,7 @@ withDefaults(
2020
</slot>
2121
</template>
2222
</VTooltip>
23-
<slot v-else />
23+
<div v-else>
24+
<slot />
25+
</div>
2426
</template>

src/store/modules/settings.ts

+23-5
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,28 @@ const useSettingsStore = defineStore(
88
'settings',
99
() => {
1010
const settings = ref(settingsDefault)
11-
watch(() => settings.value.app.colorScheme, (colorScheme) => {
11+
12+
const prefersColorScheme = window.matchMedia('(prefers-color-scheme: dark)')
13+
const currentColorScheme = ref<Exclude<Settings.app['colorScheme'], ''>>()
14+
watch(() => settings.value.app.colorScheme, (val) => {
15+
if (val === '') {
16+
prefersColorScheme.addEventListener('change', updateTheme)
17+
}
18+
else {
19+
prefersColorScheme.removeEventListener('change', updateTheme)
20+
}
21+
}, {
22+
immediate: true,
23+
})
24+
watch(() => settings.value.app.colorScheme, updateTheme, {
25+
immediate: true,
26+
})
27+
function updateTheme() {
28+
let colorScheme = settings.value.app.colorScheme
1229
if (colorScheme === '') {
13-
colorScheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
30+
colorScheme = prefersColorScheme.matches ? 'dark' : 'light'
1431
}
32+
currentColorScheme.value = colorScheme
1533
switch (colorScheme) {
1634
case 'light':
1735
document.documentElement.classList.remove('dark')
@@ -20,9 +38,8 @@ const useSettingsStore = defineStore(
2038
document.documentElement.classList.add('dark')
2139
break
2240
}
23-
}, {
24-
immediate: true,
25-
})
41+
}
42+
2643
watch(() => settings.value.menu.menuMode, (val) => {
2744
document.body.setAttribute('data-menu-mode', val)
2845
}, {
@@ -107,6 +124,7 @@ const useSettingsStore = defineStore(
107124

108125
return {
109126
settings,
127+
currentColorScheme,
110128
os,
111129
title,
112130
setTitle,

0 commit comments

Comments
 (0)