Skip to content

Commit

Permalink
refactor: group dark mode logic to useDark (BewlyBewly#694)
Browse files Browse the repository at this point in the history
* refactor: group dark mode logic to useDark

* fix: cannot get the bewlyWrapper

---------

Co-authored-by: hakadao <[email protected]>
  • Loading branch information
hyoban and hakadao committed May 1, 2024
1 parent 9a15d17 commit 79f11cb
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 211 deletions.
1 change: 1 addition & 0 deletions src/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ declare global {
const useBewlyImage: typeof import('./composables/useImage')['useBewlyImage']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useDark: typeof import('./composables/useDark')['useDark']
const useDelayedHover: typeof import('./composables/useDelayedHover')['useDelayedHover']
const useSlots: typeof import('vue')['useSlots']
const useStorageLocal: typeof import('./composables/useStorageLocal')['useStorageLocal']
Expand Down
91 changes: 4 additions & 87 deletions src/components/Dock/Dock.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { usePreferredDark } from '@vueuse/core'
import type { HoveringDockItem } from './types'
import { AppPage } from '~/enums/appEnums'
import { settings } from '~/logic'
Expand All @@ -10,9 +9,9 @@ import { useMainStore } from '~/stores/mainStore'
defineProps<{ activatedPage: AppPage }>()
const emit = defineEmits(['change-page', 'settings-visibility-change'])
const { mainAppRef } = useBewlyApp()
const mainStore = useMainStore()
const { isDark, toggleDark } = useDark()
const hideDock = ref<boolean>(false)
const hoveringDockItem = reactive<HoveringDockItem>({
Expand All @@ -31,16 +30,6 @@ const tooltipPlacement = computed(() => {
return 'right'
})
const isPreferredDark = usePreferredDark()
const currentSystemColorScheme = computed(() => isPreferredDark.value ? 'dark' : 'light')
const currentAppColorScheme = computed((): 'dark' | 'light' => {
if (settings.value.theme !== 'auto')
return settings.value.theme
else
return currentSystemColorScheme.value
})
watch(() => settings.value.autoHideDock, (newValue) => {
hideDock.value = newValue
})
Expand Down Expand Up @@ -76,78 +65,6 @@ onMounted(() => {
currentDockItems.value = computeDockItem()
})
function toggleDark(e: MouseEvent) {
const updateThemeSettings = () => {
if (currentAppColorScheme.value !== currentSystemColorScheme.value)
settings.value.theme = 'auto'
else
settings.value.theme = isPreferredDark.value ? 'light' : 'dark'
}
const isAppearanceTransition = typeof document !== 'undefined'
// @ts-expect-error: Transition API
&& document.startViewTransition
&& !window.matchMedia('(prefers-reduced-motion: reduce)').matches
if (!isAppearanceTransition) {
updateThemeSettings()
}
else {
const x = e.clientX
const y = e.clientY
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
)
// https://github.com/vueuse/vueuse/pull/3129
const style = document.createElement('style')
const styleString = `
*, *::before, *::after
{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`
style.appendChild(document.createTextNode(styleString))
document.head.appendChild(style)
// Since the above normal dom style cannot be applied in shadow dom style
// We need to add this style again to the shadow dom
const shadowDomStyle = document.createElement('style')
const shadowDomStyleString = `
*, *::before, *::after
{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important; will-change: background}`
shadowDomStyle.appendChild(document.createTextNode(shadowDomStyleString))
mainAppRef.value.appendChild(shadowDomStyle)
// @ts-expect-error: Transition API
const transition = document.startViewTransition(async () => {
updateThemeSettings()
await nextTick()
})
transition.ready.then(() => {
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
]
const animation = document.documentElement.animate(
{
clipPath: currentAppColorScheme.value === 'dark'
? [...clipPath].reverse()
: clipPath,
},
{
duration: 300,
easing: 'ease-in-out',
pseudoElement: currentAppColorScheme.value === 'dark'
? '::view-transition-old(root)'
: '::view-transition-new(root)',
},
)
animation.addEventListener('finish', () => {
document.head.removeChild(style!)
mainAppRef.value.removeChild(shadowDomStyle!)
}, { once: true })
})
}
}
function toggleDockHide(hide: boolean) {
if (settings.value.autoHideDock)
hideDock.value = hide
Expand Down Expand Up @@ -209,7 +126,7 @@ function toggleDockHide(hide: boolean) {
<!-- dividing line -->
<div class="divider" />

<Tooltip :content="currentAppColorScheme === 'dark' ? $t('dock.dark_mode') : $t('dock.light_mode')" :placement="tooltipPlacement">
<Tooltip :content="isDark ? $t('dock.dark_mode') : $t('dock.light_mode')" :placement="tooltipPlacement">
<button
class="dock-item"
@click="toggleDark"
Expand All @@ -218,13 +135,13 @@ function toggleDockHide(hide: boolean) {
>
<Transition name="fade">
<div v-show="hoveringDockItem.themeMode" absolute>
<line-md:sunny-outline-to-moon-loop-transition v-if="currentAppColorScheme === 'dark'" />
<line-md:sunny-outline-to-moon-loop-transition v-if="isDark" />
<line-md:moon-alt-to-sunny-outline-loop-transition v-else />
</div>
</Transition>
<Transition name="fade">
<div v-show="!hoveringDockItem.themeMode" absolute>
<line-md:sunny-outline-to-moon-transition v-if="currentAppColorScheme === 'dark'" />
<line-md:sunny-outline-to-moon-transition v-if="isDark" />
<line-md:moon-to-sunny-outline-transition v-else />
</div>
</Transition>
Expand Down
92 changes: 4 additions & 88 deletions src/components/RightSideButtons/RightSideButtons.vue
Original file line number Diff line number Diff line change
@@ -1,97 +1,13 @@
<script setup lang="ts">
import { usePreferredDark } from '@vueuse/core'
import type { HoveringDockItem } from './types'
import { settings } from '~/logic'
const emit = defineEmits(['settings-visibility-change'])
const { mainAppRef } = useBewlyApp()
const { isDark, toggleDark } = useDark()
const hoveringDockItem = reactive<HoveringDockItem>({
themeMode: false,
settings: false,
})
const isPreferredDark = usePreferredDark()
const currentSystemColorScheme = computed(() => isPreferredDark.value ? 'dark' : 'light')
const currentAppColorScheme = computed((): 'dark' | 'light' => {
if (settings.value.theme !== 'auto')
return settings.value.theme
else
return currentSystemColorScheme.value
})
function toggleDark(e: MouseEvent) {
const updateThemeSettings = () => {
if (currentAppColorScheme.value !== currentSystemColorScheme.value)
settings.value.theme = 'auto'
else
settings.value.theme = isPreferredDark.value ? 'light' : 'dark'
}
const isAppearanceTransition = typeof document !== 'undefined'
// @ts-expect-error: Transition API
&& document.startViewTransition
&& !window.matchMedia('(prefers-reduced-motion: reduce)').matches
if (!isAppearanceTransition) {
updateThemeSettings()
}
else {
const x = e.clientX
const y = e.clientY
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
)
// https://github.com/vueuse/vueuse/pull/3129
const style = document.createElement('style')
const styleString = `
*, *::before, *::after
{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`
style.appendChild(document.createTextNode(styleString))
document.head.appendChild(style)
// Since normal dom style cannot be applied in shadow dom style
// We need to add this style again to the shadow dom
const shadowDomStyle = document.createElement('style')
const shadowDomStyleString = `
*, *::before, *::after
{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`
shadowDomStyle.appendChild(document.createTextNode(shadowDomStyleString))
mainAppRef.value.appendChild(shadowDomStyle)
// @ts-expect-error: Transition API
const transition = document.startViewTransition(async () => {
updateThemeSettings()
await nextTick()
})
transition.ready.then(() => {
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
]
const animation = document.documentElement.animate(
{
clipPath: currentAppColorScheme.value === 'dark'
? [...clipPath].reverse()
: clipPath,
},
{
duration: 300,
easing: 'ease-in-out',
pseudoElement: currentAppColorScheme.value === 'dark'
? '::view-transition-old(root)'
: '::view-transition-new(root)',
},
)
animation.addEventListener('finish', () => {
document.head.removeChild(style!)
mainAppRef.value.removeChild(shadowDomStyle!)
}, { once: true })
})
}
}
</script>

<template>
Expand All @@ -100,7 +16,7 @@ function toggleDark(e: MouseEvent) {
pointer-events-none
>
<div flex="~ gap-2 col" pointer-events-auto>
<Tooltip :content="currentAppColorScheme === 'dark' ? $t('dock.dark_mode') : $t('dock.light_mode')" placement="left">
<Tooltip :content="isDark ? $t('dock.dark_mode') : $t('dock.light_mode')" placement="left">
<Button
class="ctrl-btn"
style="backdrop-filter: var(--bew-filter-glass-1);"
Expand All @@ -111,13 +27,13 @@ function toggleDark(e: MouseEvent) {
>
<Transition name="fade">
<div v-show="hoveringDockItem.themeMode" absolute>
<line-md:sunny-outline-to-moon-loop-transition v-if="currentAppColorScheme === 'dark'" />
<line-md:sunny-outline-to-moon-loop-transition v-if="isDark" />
<line-md:moon-alt-to-sunny-outline-loop-transition v-else />
</div>
</Transition>
<Transition name="fade">
<div v-show="!hoveringDockItem.themeMode" absolute>
<line-md:sunny-outline-to-moon-transition v-if="currentAppColorScheme === 'dark'" />
<line-md:sunny-outline-to-moon-transition v-if="isDark" />
<line-md:moon-to-sunny-outline-transition v-else />
</div>
</Transition>
Expand Down
122 changes: 122 additions & 0 deletions src/composables/useDark.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { usePreferredDark } from '@vueuse/core'
import { settings } from '~/logic'

export function useDark() {
const isPreferredDark = usePreferredDark()
const currentSystemColorScheme = computed(() => isPreferredDark.value ? 'dark' : 'light')
const currentAppColorScheme = computed((): 'dark' | 'light' => {
if (settings.value.theme !== 'auto')
return settings.value.theme
else
return currentSystemColorScheme.value
})
const isDark = computed(() => currentAppColorScheme.value === 'dark')

// Watch for changes in the 'settings.value.theme' variable and add the 'dark' class to the 'mainApp' element
// to prevent some Unocss dark-specific styles from failing to take effect
watch(
() => [settings.value.theme, isPreferredDark.value],
() => {
setAppAppearance()
},
{ immediate: true },
)

/**
* Watch for changes in the 'settings.value.theme' variable and add the 'dark' class to the 'mainApp' element
* to prevent some Unocss dark-specific styles from failing to take effect
*/
function setAppAppearance() {
if (isDark.value) {
document.querySelector('#bewly')?.classList.add('dark')
document.documentElement.classList.add('dark')
}
else {
document.querySelector('#bewly')?.classList.remove('dark')
document.documentElement.classList.remove('dark')
}
}

function toggleDark(e: MouseEvent) {
const updateThemeSettings = () => {
if (currentAppColorScheme.value !== currentSystemColorScheme.value)
settings.value.theme = 'auto'
else
settings.value.theme = isPreferredDark.value ? 'light' : 'dark'
}

const isAppearanceTransition = typeof document !== 'undefined'
// @ts-expect-error: Transition API
&& document.startViewTransition
&& !window.matchMedia('(prefers-reduced-motion: reduce)').matches
if (!isAppearanceTransition) {
updateThemeSettings()
}
else {
const x = e.clientX
const y = e.clientY
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
)
// https://github.com/vueuse/vueuse/pull/3129
const style = document.createElement('style')
const styleString = `
*, *::before, *::after
{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`
style.appendChild(document.createTextNode(styleString))
document.head.appendChild(style)

// Since the above normal dom style cannot be applied in shadow dom style
// We need to add this style again to the shadow dom
const shadowDomStyle = document.createElement('style')
const shadowDomStyleString = `
*, *::before, *::after
{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important; will-change: background}`
shadowDomStyle.appendChild(document.createTextNode(shadowDomStyleString))

const bewlyShadowRoot = document.getElementById('bewly')?.shadowRoot
const bewlyWrapper = bewlyShadowRoot?.getElementById('bewly-wrapper')
if (!bewlyWrapper)
throw new Error('mainAppRef is not found')

bewlyWrapper.appendChild(shadowDomStyle)

// @ts-expect-error: Transition API
const transition = document.startViewTransition(async () => {
updateThemeSettings()
await nextTick()
})

transition.ready.then(() => {
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
]
const animation = document.documentElement.animate(
{
clipPath: currentAppColorScheme.value === 'dark'
? [...clipPath].reverse()
: clipPath,
},
{
duration: 300,
easing: 'ease-in-out',
pseudoElement: currentAppColorScheme.value === 'dark'
? '::view-transition-old(root)'
: '::view-transition-new(root)',
},
)
animation.addEventListener('finish', () => {
document.head.removeChild(style!)
bewlyWrapper.removeChild(shadowDomStyle!)
}, { once: true })
})
}
}

return {
isDark,
toggleDark,
}
}
Loading

0 comments on commit 79f11cb

Please sign in to comment.