45fda56fb8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
1.3 KiB
Vue
49 lines
1.3 KiB
Vue
<script setup lang="ts">
|
|
import { Icon } from '@iconify/vue'
|
|
|
|
const colorMode = useColorMode()
|
|
type Mode = 'system' | 'dark' | 'light'
|
|
|
|
const iconMap: Record<Mode, string> = {
|
|
system: 'mdi:monitor',
|
|
dark: 'mdi:weather-night',
|
|
light: 'mdi:weather-sunny',
|
|
}
|
|
|
|
const labelMap: Record<Mode, string> = {
|
|
system: '跟随系统',
|
|
dark: '深色模式',
|
|
light: '浅色模式',
|
|
}
|
|
|
|
const cycleOrder = computed<Mode[]>(() => {
|
|
const isDark = colorMode.value === 'dark'
|
|
return isDark ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']
|
|
})
|
|
|
|
const currentMode = computed(() => colorMode.preference as Mode)
|
|
const currentIcon = computed(() => iconMap[currentMode.value] || iconMap.system)
|
|
const currentLabel = computed(() => labelMap[currentMode.value] || labelMap.system)
|
|
|
|
function cycle() {
|
|
const order = cycleOrder.value
|
|
const idx = order.indexOf(currentMode.value)
|
|
colorMode.preference = order[(idx + 1) % order.length]
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<button
|
|
@click="cycle"
|
|
class="inline-flex items-center justify-center rounded-md w-8 h-8 transition-colors"
|
|
style="color: var(--color-text-secondary)"
|
|
:class="[
|
|
'hover:bg-[var(--color-bg-hover)] hover:text-[var(--color-text)]',
|
|
]"
|
|
:aria-label="currentLabel"
|
|
:title="currentLabel"
|
|
>
|
|
<Icon :icon="currentIcon" class="w-5 h-5" />
|
|
</button>
|
|
</template>
|