Fix Dark mode (#376)

Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
Chirag Chhatrala
2024-04-15 18:49:37 +05:30
committed by GitHub
parent e1faba8239
commit ae18bcbb8d
7 changed files with 188 additions and 55 deletions

View File

@@ -1,30 +1,121 @@
let darkModeNodeParent = import.meta.client ? document.body : null
/**
* Handle form public pages dark mode and transparent mode
*/
export function handleDarkMode (darkMode, elem = null) {
if (import.meta.server) return
if (import.meta.server)
return
darkModeNodeParent = elem ?? document.body
// Dark mode
if (['dark', 'light'].includes(darkMode)) {
if (['dark', 'light'].includes(darkMode))
return handleDarkModeToggle(darkMode === 'dark')
}
// Case auto
handleDarkModeToggle(window.matchMedia('(prefers-color-scheme: dark)').matches)
handleDarkModeToggle(
window.matchMedia('(prefers-color-scheme: dark)').matches
)
// Create listener
window.matchMedia('(prefers-color-scheme: dark)')
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', handleDarkModeToggle)
}
export function darkModeEnabled() {
if (import.meta.server) return false
return computed(() => document.body.classList.contains('dark'))
export function useClassWatcher (elem, className) {
const hasClass = ref(false)
const updateClassPresence = () => {
hasClass.value = elem.value?.classList.contains(className) ?? false
}
let observer = null
const startObserving = () => {
if (elem.value) {
updateClassPresence()
observer = new MutationObserver(updateClassPresence)
observer.observe(elem.value, { attributes: true, attributeFilter: ['class'] })
}
}
const stopObserving = () => {
if (observer) {
observer.disconnect()
observer = null
}
}
onMounted(() => {
watch(elem, (newElem, oldElem, onCleanup) => {
stopObserving()
startObserving()
onCleanup(stopObserving)
}, { immediate: true })
})
onUnmounted(() => {
stopObserving()
})
return computed(() => hasClass.value)
}
export function useDarkMode (elem = ref(null)) {
// Define a computed property to handle the element reference reactively
const effectiveElem = computed(() => {
return elem.value || (process.client ? document.body : null)
})
// Pass the computed property to useClassWatcher
return useClassWatcher(effectiveElem, 'dark')
}
export function darkModeEnabled (elem = ref(null)) {
if (import.meta.server)
return ref(false)
// TODO: replace this with a function that returns a watcher for the given of dark class element
// Simplify this
const isDark = ref(false)
// Update isDark based on the current class
const updateIsDark = () => {
console.log(elem.value, 'test')
const finalElement = elem.value ?? document.body
isDark.value = finalElement.classList.contains('dark')
}
// MutationObserver callback to react to class changes
let observer = new MutationObserver(updateIsDark)
// Initialize and clean up the observer
const initObserver = (element) => {
if (observer) {
observer.disconnect()
}
if (element) {
observer = new MutationObserver(updateIsDark)
observer.observe(element, { attributes: true, attributeFilter: ['class'] })
}
}
onMounted(() => {
if (!import.meta.server) {
initObserver(elem)
}
})
onUnmounted(() => {
if (observer) {
observer.disconnect()
}
})
// Return a computed ref that depends on isDark
return computed(() => isDark.value)
}
function handleDarkModeToggle (enabled) {
@@ -32,20 +123,27 @@ function handleDarkModeToggle (enabled) {
// if we received an event
enabled = enabled.matches
}
enabled ? darkModeNodeParent.classList.add('dark') : darkModeNodeParent.classList.remove('dark')
enabled
? darkModeNodeParent.classList.add('dark')
: darkModeNodeParent.classList.remove('dark')
}
export function disableDarkMode () {
if (import.meta.server) return
if (import.meta.server)
return
const body = document.body
body.classList.remove('dark')
// Remove event listener
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', handleDarkModeToggle)
window
.matchMedia('(prefers-color-scheme: dark)')
.removeEventListener('change', handleDarkModeToggle)
}
export function handleTransparentMode (transparentModeEnabled) {
if (import.meta.server) return
if (!useIsIframe() || !transparentModeEnabled) return
if (import.meta.server)
return
if (!useIsIframe() || !transparentModeEnabled)
return
const app = document.getElementById('app')
app.classList.remove('bg-white')
@@ -53,9 +151,12 @@ export function handleTransparentMode (transparentModeEnabled) {
app.classList.add('bg-transparent')
}
export function focusOnFirstFormElement() {
if (import.meta.server) return
for (const ele of document.querySelectorAll('input,button,textarea,[role="button"]')) {
export function focusOnFirstFormElement () {
if (import.meta.server)
return
for (const ele of document.querySelectorAll(
'input,button,textarea,[role="button"]'
)) {
if (ele.offsetWidth !== 0 || ele.offsetHeight !== 0) {
ele.focus()
break