Skip to content

Commit

Permalink
add track prop to track changes in system preference (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
ollema authored Oct 28, 2023
1 parent 9dbbb39 commit 8c93706
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-teachers-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'mode-watcher': patch
---

Add `track` prop which allows `<ModeWatcher>` to track changes in system preference
28 changes: 27 additions & 1 deletion src/lib/mode-watcher.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
<script lang="ts">
import { onMount } from 'svelte';
import { getSystemPrefersMode, setInitialClassState, setActiveMode } from './mode.js';
import {
getSystemPrefersMode,
getUserPrefersMode,
setActiveMode,
setInitialClassState
} from './mode';
// track `prefers-color-scheme` if no user preference is set
export let track = true;
onMount(() => {
if (!('mode' in localStorage)) {
setActiveMode(getSystemPrefersMode());
}
if (!track) {
return;
}
const mql = window.matchMedia('(prefers-color-scheme: light)');
const listener = () => {
if (getUserPrefersMode() === 'system') {
setActiveMode(getSystemPrefersMode());
}
};
mql.addEventListener('change', listener);
return () => {
mql.removeEventListener('change', listener);
};
});
</script>

Expand Down
20 changes: 14 additions & 6 deletions src/lib/mode.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Modified version of the light switch by: https://skeleton.dev

import { persisted } from 'svelte-persisted-store';
import { readonly } from 'svelte/store';
import { get, readonly } from 'svelte/store';

/**
* Stores
*/

const systemPrefersMode = persisted<'dark' | 'light'>('systemPrefersMode', 'dark');
const userPrefersMode = persisted<'dark' | 'light' | undefined>('userPrefersMode', undefined);
const userPrefersMode = persisted<'dark' | 'light' | 'system'>('userPrefersMode', 'system');
const activeMode = persisted<'dark' | 'light'>('mode', 'dark');

/** Readonly store with either `"light"` or `"dark"` depending on the active mode */
Expand All @@ -27,12 +27,17 @@ export function getSystemPrefersMode(): 'dark' | 'light' {
return prefersLightMode;
}

/** Get the user preference */
export function getUserPrefersMode(): 'dark' | 'light' | 'system' {
return get(userPrefersMode);
}

/**
* Setters
*/

/** Set the user preference */
function setUserPrefersMode(value: 'dark' | 'light' | undefined): void {
function setUserPrefersMode(value: 'dark' | 'light' | 'system'): void {
userPrefersMode.set(value);
}

Expand Down Expand Up @@ -67,14 +72,17 @@ export function setInitialClassState() {

let userPref: string | null = null;
try {
userPref = JSON.parse(localStorage.getItem('userPrefersMode') || 'null');
userPref = JSON.parse(localStorage.getItem('userPrefersMode') || 'system');
} catch {
// ignore JSON parsing errors
}

const systemPref = window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';

if (userPref === 'light' || (userPref === null && systemPref === 'light')) {
if (
userPref === 'light' ||
((userPref === 'system' || userPref === null) && systemPref === 'light')
) {
htmlEl.classList.remove('dark');
htmlEl.style.colorScheme = 'light';
} else {
Expand Down Expand Up @@ -105,7 +113,7 @@ export function setMode(mode: 'dark' | 'light'): void {
/** Reset the mode to operating system preference */
export function resetMode(): void {
activeMode.update(() => {
setUserPrefersMode(undefined);
setUserPrefersMode('system');
const next = getSystemPrefersMode();
setActiveMode(next);
return next;
Expand Down

0 comments on commit 8c93706

Please sign in to comment.