Initial rearrangment of vuetom site source
This commit is contained in:
66
packages/vuetom/blog/components/switch/VPSwitch.vue
Normal file
66
packages/vuetom/blog/components/switch/VPSwitch.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<button class="VPSwitch" type="button" role="switch">
|
||||
<span class="check">
|
||||
<span class="icon" v-if="$slots.default">
|
||||
<slot />
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.VPSwitch {
|
||||
position: relative;
|
||||
border-radius: 11px;
|
||||
display: block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
flex-shrink: 0;
|
||||
/* border: 1px solid var(--vp-c-divider); */
|
||||
/* background-color: var(--vp-c-bg-mute); */
|
||||
transition: border-color 0.25s, background-color 0.25s;
|
||||
}
|
||||
|
||||
.VPSwitch:hover {
|
||||
/* border-color: var(--vp-c-gray); */
|
||||
}
|
||||
|
||||
.check {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
/* background-color: var(--vp-c-white);
|
||||
box-shadow: var(--vp-shadow-1); */
|
||||
transition: background-color 0.25s, transform 0.25s;
|
||||
}
|
||||
|
||||
.dark .check {
|
||||
/* background-color: var(--vp-c-black); */
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon :deep(svg) {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.dark .icon :deep(svg) {
|
||||
fill: var(--vp-c-text-1);
|
||||
transition: opacity 0.25s;
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,74 @@
|
||||
<script lang="ts" setup>
|
||||
import { APPEARANCE_KEY } from '../../shared.js'
|
||||
import VPSwitch from './VPSwitch.vue'
|
||||
import VPIconSun from '../icons/VPIconSun.vue'
|
||||
import VPIconMoon from '../icons/VPIconMoon.vue'
|
||||
|
||||
const toggle = typeof localStorage !== 'undefined' ? useAppearance() : () => {}
|
||||
|
||||
function useAppearance() {
|
||||
const query = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
const { classList } = document.documentElement
|
||||
|
||||
let userPreference = localStorage.getItem(APPEARANCE_KEY) || 'auto'
|
||||
|
||||
let isDark = userPreference === 'auto'
|
||||
? query.matches
|
||||
: userPreference === 'dark'
|
||||
|
||||
query.onchange = (e) => {
|
||||
if (userPreference === 'auto') {
|
||||
setClass((isDark = e.matches))
|
||||
}
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
setClass((isDark = !isDark))
|
||||
|
||||
userPreference = isDark
|
||||
? query.matches ? 'auto' : 'dark'
|
||||
: query.matches ? 'light' : 'auto'
|
||||
|
||||
localStorage.setItem(APPEARANCE_KEY, userPreference)
|
||||
}
|
||||
|
||||
function setClass(dark: boolean): void {
|
||||
classList[dark ? 'add' : 'remove']('dark')
|
||||
}
|
||||
|
||||
return toggle
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VPSwitch
|
||||
class="VPSwitchAppearance"
|
||||
aria-label="toggle dark mode"
|
||||
@click="toggle"
|
||||
>
|
||||
<VPIconSun class="sun" />
|
||||
<VPIconMoon class="moon" />
|
||||
</VPSwitch>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.sun {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.moon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.dark .sun {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.dark .moon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.dark .VPSwitchAppearance :deep(.check) {
|
||||
/* transform: translateX(18px); */
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user