mirror of
https://github.com/pockethost/pockethost.git
synced 2025-06-20 21:16:38 +00:00
Darkmode cookie fix (#38)
This commit is contained in:
parent
a149df0d58
commit
22e6966fcb
@ -6,3 +6,12 @@ export function assertExists<TType>(
|
||||
throw new Error(message)
|
||||
}
|
||||
}
|
||||
|
||||
export function assertTruthy<TType>(
|
||||
v: unknown,
|
||||
message = `Value should be truthy`
|
||||
): asserts v is NonNullable<TType> {
|
||||
if (!v) {
|
||||
throw new Error(message)
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@
|
||||
"dependencies": {
|
||||
"@pockethost/common": "0.0.1",
|
||||
"@s-libs/micro-dash": "12",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"js-cookie": "^3.0.1",
|
||||
"pocketbase": "^0.7.0",
|
||||
"random-word-slugs": "^0.1.6",
|
||||
"sass": "^1.54.9",
|
||||
|
@ -1,76 +1,66 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment'
|
||||
import { assertTruthy } from '@pockethost/common'
|
||||
import { find } from '@s-libs/micro-dash'
|
||||
import Cookies from 'js-cookie'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
// Set some default values to be referenced later
|
||||
enum ThemeNames {
|
||||
Light = 'light',
|
||||
Dark = 'dark'
|
||||
}
|
||||
const ALLOWED_THEMES: ThemeNames[] = [ThemeNames.Light, ThemeNames.Dark]
|
||||
const DEFAULT_THEME: ThemeNames = ThemeNames.Light
|
||||
const STORAGE_NAME: string = 'theme'
|
||||
const THEME_ATTRIBUTE: string = 'data-theme'
|
||||
const THEME_ICONS: { [_ in ThemeNames]: string } = {
|
||||
[ThemeNames.Light]: 'bi bi-moon-stars',
|
||||
[ThemeNames.Dark]: 'bi bi-brightness-high'
|
||||
}
|
||||
|
||||
const html = () => {
|
||||
const htmlElement = document.querySelector('html')
|
||||
assertTruthy(htmlElement, `Expected <html> element to exist`)
|
||||
return htmlElement
|
||||
}
|
||||
const currentTheme = () => {
|
||||
const htmlElement = html()
|
||||
const _att = htmlElement.getAttribute(THEME_ATTRIBUTE)
|
||||
const currentTheme = find(ALLOWED_THEMES, (v) => _att === v) || DEFAULT_THEME
|
||||
return currentTheme
|
||||
}
|
||||
const currentIcon = () => {
|
||||
return THEME_ICONS[currentTheme()]
|
||||
}
|
||||
|
||||
// This can change the CSS a bit depending on where the theme toggle is rendered
|
||||
export let navLink: boolean = false
|
||||
|
||||
// Set the default icon to be light mode
|
||||
let iconClass: string = 'bi bi-moon-stars'
|
||||
|
||||
// Set some default values to be referenced later
|
||||
const STORAGE_NAME: string = 'theme'
|
||||
const THEME_ATTRIBUTE: string = 'data-theme'
|
||||
|
||||
// FIXME: I don't think these enums are right
|
||||
enum PossibleThemeValues {
|
||||
Dark = {
|
||||
icon: 'bi bi-brightness-high',
|
||||
theme: 'dark'
|
||||
},
|
||||
Light = {
|
||||
icon: 'bi bi-moon-stars',
|
||||
theme: 'light'
|
||||
}
|
||||
}
|
||||
|
||||
// This will track the user's theme throughout the app
|
||||
let localStorageTheme = ''
|
||||
let iconClass: string = browser ? currentIcon() : ''
|
||||
|
||||
// Wait for the DOM to be available
|
||||
onMount(() => {
|
||||
// First get the site default theme
|
||||
const htmlElement: Element = document.querySelector('html')
|
||||
const currentTheme: string = htmlElement.getAttribute(THEME_ATTRIBUTE)
|
||||
|
||||
// If this is the user's first time on the site, set the default theme
|
||||
if (localStorage.getItem(STORAGE_NAME) === null) {
|
||||
localStorage.setItem(STORAGE_NAME, currentTheme)
|
||||
}
|
||||
|
||||
// Now get the user's theme value
|
||||
localStorageTheme = localStorage.getItem(STORAGE_NAME)
|
||||
|
||||
// If the storage item is different from the HTML theme attribute, update the HTML
|
||||
if (localStorageTheme === 'light') {
|
||||
updateTheme(PossibleThemeValues.Light)
|
||||
} else {
|
||||
updateTheme(PossibleThemeValues.Dark)
|
||||
}
|
||||
updateTheme(currentTheme())
|
||||
})
|
||||
|
||||
// Alternate the theme values on toggle click
|
||||
const handleClick = () => {
|
||||
// Get the user's current theme setting
|
||||
localStorageTheme = localStorage.getItem(STORAGE_NAME)
|
||||
|
||||
if (localStorageTheme === 'light') {
|
||||
updateTheme(PossibleThemeValues.Dark)
|
||||
} else {
|
||||
updateTheme(PossibleThemeValues.Light)
|
||||
}
|
||||
const newTheme = currentTheme() === ThemeNames.Light ? ThemeNames.Dark : ThemeNames.Light
|
||||
updateTheme(newTheme)
|
||||
}
|
||||
|
||||
const updateTheme = (type: PossibleThemeValues) => {
|
||||
const htmlElement: Element = document.querySelector('html')
|
||||
const updateTheme = (themeName: ThemeNames) => {
|
||||
const htmlElement = html()
|
||||
|
||||
// Update the icon class name to toggle between light and dark mode
|
||||
iconClass = type['icon']
|
||||
iconClass = THEME_ICONS[themeName]
|
||||
|
||||
// Update the HTML element to have the right data-theme value
|
||||
htmlElement.setAttribute(THEME_ATTRIBUTE, type['theme'])
|
||||
htmlElement.setAttribute(THEME_ATTRIBUTE, themeName)
|
||||
|
||||
// Now update the localStorage to have the latest value
|
||||
localStorage.setItem(STORAGE_NAME, type['theme'])
|
||||
Cookies.set(STORAGE_NAME, themeName)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -2,6 +2,21 @@
|
||||
import Navbar from '$components/Navbar.svelte'
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<script>
|
||||
{
|
||||
const THEME_ATTRIBUTE = 'data-theme'
|
||||
const currentTheme =
|
||||
document.cookie
|
||||
.split('; ')
|
||||
.find((row) => row.startsWith('theme='))
|
||||
?.split('=')?.[1] || 'light'
|
||||
console.log(`Current theme is ${currentTheme}`)
|
||||
document.querySelector('html')?.setAttribute(THEME_ATTRIBUTE, currentTheme)
|
||||
console.log(document.querySelector('html'))
|
||||
}
|
||||
</script>
|
||||
</svelte:head>
|
||||
<Navbar />
|
||||
|
||||
<main data-sveltekit-prefetch>
|
||||
|
@ -35,8 +35,7 @@ export const createCleanupManagerAsync = () => {
|
||||
return cleanup
|
||||
}
|
||||
|
||||
const cleanupAll = () =>
|
||||
reduce(cleanups, (c, v) => c.then(v()), Promise.resolve())
|
||||
const cleanupAll = () => reduce(cleanups, (c, v) => c.then(v()), Promise.resolve())
|
||||
|
||||
return { add, cleanupAll }
|
||||
}
|
||||
|
10
yarn.lock
10
yarn.lock
@ -924,6 +924,11 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/js-cookie@^3.0.2":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-3.0.2.tgz#451eaeece64c6bdac8b2dde0caab23b085899e0d"
|
||||
integrity sha512-6+0ekgfusHftJNYpihfkMu8BWdeHs9EOJuGcSofErjstGPfPGEu9yTu4t460lTzzAMl2cM5zngQJqPMHbbnvYA==
|
||||
|
||||
"@types/node@*":
|
||||
version "18.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.8.5.tgz#6a31f820c1077c3f8ce44f9e203e68a176e8f59e"
|
||||
@ -1982,6 +1987,11 @@ is-reference@1.2.1:
|
||||
dependencies:
|
||||
"@types/estree" "*"
|
||||
|
||||
js-cookie@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414"
|
||||
integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
|
Loading…
x
Reference in New Issue
Block a user