Skip to content

Commit

Permalink
refactor to improve readability
Browse files Browse the repository at this point in the history
  • Loading branch information
ollema committed Oct 26, 2023
1 parent ce963ce commit 521e318
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 45 deletions.
6 changes: 3 additions & 3 deletions src/lib/mode-watcher.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts">
import { onMount } from 'svelte';
import { getModeOsPrefers, setInitialClassState, setModeCurrent } from './mode.js';
import { getSystemPrefersMode, setInitialClassState, setCurrentMode } from './mode.js';
onMount(() => {
if (!('modeCurrent' in localStorage)) {
setModeCurrent(getModeOsPrefers());
if (!('mode' in localStorage)) {
setCurrentMode(getSystemPrefersMode());
}
});
</script>
Expand Down
83 changes: 41 additions & 42 deletions src/lib/mode.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
// Modified version of the light switch by: https://skeleton.dev

import { derived } from 'svelte/store';
import { persisted } from 'svelte-persisted-store';

/**
* Stores
*/

const modeOsPrefers = persisted<'light' | 'dark'>('modeOsPrefers', 'dark');
const modeUserPrefers = persisted<'light' | 'dark' | undefined>('modeUserPrefers', undefined);
const modeCurrent = persisted<'light' | 'dark'>('modeCurrent', 'dark');

/** Derived store with either `"light"` or `"dark"` depending on the current mode */
export const mode = derived(modeCurrent, ($modeCurrent) => $modeCurrent);
const systemPrefersMode = persisted<'dark' | 'light'>('systemPrefersMode', 'dark');
const userPrefersMode = persisted<'dark' | 'light' | undefined>('userPrefersMode', undefined);
export const mode = persisted<'dark' | 'light'>('mode', 'dark');

/**
* Getters
*/

/** Get the OS preference */
export function getModeOsPrefers(): 'light' | 'dark' {
/** Get the operating system preference */
export function getSystemPrefersMode(): 'dark' | 'light' {
const prefersLightMode = window.matchMedia('(prefers-color-scheme: light)').matches
? 'light'
: 'dark';
modeOsPrefers.set(prefersLightMode);
systemPrefersMode.set(prefersLightMode);
return prefersLightMode;
}

Expand All @@ -32,80 +28,83 @@ export function getModeOsPrefers(): 'light' | 'dark' {
*/

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

/** Set the current mode */
export function setModeCurrent(value: 'light' | 'dark'): void {
export function setCurrentMode(value: 'dark' | 'light'): void {
const htmlEl = document.documentElement;

if (value === 'light') {
htmlEl.classList.remove('dark');
htmlEl.style.colorScheme = 'light';
}
if (value === 'dark') {
} else {
htmlEl.classList.add('dark');
htmlEl.style.colorScheme = 'dark';
}
modeCurrent.set(value);

mode.set(value);
}

/**
* Lightswitch Utility
*/

/**
* Set the visible light/dark mode on page load
* Set light/dark class based on user/system preference
*
* Should be added to <head> to prevent FOUC
*
* This function needs to be able to be stringified and thus it cannot use other functions
*/
export function setInitialClassState() {
const htmlEl = document.documentElement;

const userPrefersMode = localStorage.getItem('modeUserPrefers');

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

if (userPrefersMode === 'dark' || systemPrefersMode === 'dark') {
htmlEl.classList.add('dark');
htmlEl.style.colorScheme = 'dark';
let userPref: string | null = null;
try {
userPref = JSON.parse(localStorage.getItem('userPrefersMode') || 'null');
} catch {
// ignore JSON parsing errors
}

if (userPrefersMode === 'light' || systemPrefersMode === 'light') {
const systemPref = window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';

if (userPref === 'light' || (userPref === null && systemPref === 'light')) {
htmlEl.classList.remove('dark');
htmlEl.style.colorScheme = 'light';
} else {
htmlEl.classList.add('dark');
htmlEl.style.colorScheme = 'dark';
}
}

/** Toggle between light and dark mode */
export function toggleMode(): void {
modeCurrent.update((curr) => {
const next = curr === 'light' ? 'dark' : 'light';
setModeUserPrefers(next);
setModeCurrent(next);
mode.update((curr) => {
const next = curr === 'dark' ? 'light' : 'dark';
setUserPrefersMode(next);
setCurrentMode(next);
return next;
});
}

/** Set the mode to light or dark */
export function setMode(mode: 'light' | 'dark'): void {
modeCurrent.update((curr) => {
if (curr === mode) return curr;
setModeUserPrefers(mode);
setModeCurrent(mode);
return mode;
export function setMode(next: 'dark' | 'light'): void {
mode.update((curr) => {
if (curr === next) return curr;
setUserPrefersMode(next);
setCurrentMode(next);
return next;
});
}

/** Reset the mode to OS preference */
/** Reset the mode to operating system preference */
export function resetMode(): void {
modeCurrent.update(() => {
setModeUserPrefers(undefined);
const next = getModeOsPrefers();
setModeCurrent(next);
mode.update(() => {
setUserPrefersMode(undefined);
const next = getSystemPrefersMode();
setCurrentMode(next);
return next;
});
}

0 comments on commit 521e318

Please sign in to comment.