Last active
September 11, 2021 04:00
-
-
Save heyztb/2a31d68a4be40696d21290e8b48f1df2 to your computer and use it in GitHub Desktop.
Svelte Dark Mode implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
// snip | |
import { theme } from '$lib/stores/theme-store'; | |
theme.init() | |
// /snip | |
</script> | |
<!-- we import our theme store and call it's init method in our layout component so that it will | |
read the user's preferences and set the theme accordingly --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
// snip | |
import { theme } from '$lib/stores/theme-store' | |
const toggleTheme = () => { | |
if ($theme === 'dark') { | |
$theme = 'light' | |
} else { | |
$theme = 'dark' | |
} | |
} | |
// /snip | |
</script> | |
<!-- and then have a button further down in this component with on:click={toggleTheme} that will handle the user explicitly setting | |
their theme to either light or dark --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { get, writable } from "svelte/store"; | |
import { browser } from "$app/env"; | |
function _theme() { | |
const { set, subscribe } = writable('') | |
return { | |
subscribe, | |
update: (theme) => get(theme), | |
get: (theme) => get(theme), | |
set: (theme) => { | |
if (!browser) return // ignore during SSR | |
const currentTheme = document.querySelector('html').classList.contains('dark') ? 'dark' : 'light' | |
set(theme) | |
document.querySelector('html').classList.replace(currentTheme, theme) | |
localStorage.setItem('theme', theme) | |
}, | |
init: () => { | |
if (!browser) return // ignore during SSR | |
if (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches) { | |
set('dark') | |
document.querySelector('html').classList.add('dark') | |
localStorage.setItem('theme', 'dark') | |
} else { | |
const theme = localStorage.getItem('theme') || 'light' | |
document.querySelector('html').classList.add(theme) | |
set(localStorage.getItem('theme')) | |
} | |
}, | |
reset: () => { | |
set(undefined) | |
browser ? localStorage.removeItem('theme') : null | |
} | |
} | |
} | |
export const theme = _theme() | |
// the docs on svelte stores can be found here if this is a bit confusing | |
// essentially you can use these to share state between many components | |
// https://svelte.dev/docs#svelte_store |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment