From e9d39759d4e9e3210f69c70693826bb4285b3998 Mon Sep 17 00:00:00 2001
From: Djuri Baars <dsbaars@users.noreply.github.com>
Date: Thu, 28 Nov 2024 23:30:14 +0100
Subject: [PATCH] Add color mode switcher

---
 src/components/ColorSchemeSwitcher.svelte | 53 +++++++++++++++++++++++
 src/lib/style/app.scss                    |  2 +-
 src/routes/+layout.svelte                 |  2 +
 3 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100644 src/components/ColorSchemeSwitcher.svelte

diff --git a/src/components/ColorSchemeSwitcher.svelte b/src/components/ColorSchemeSwitcher.svelte
new file mode 100644
index 0000000..49e3175
--- /dev/null
+++ b/src/components/ColorSchemeSwitcher.svelte
@@ -0,0 +1,53 @@
+<script lang="ts">
+	import { onMount } from 'svelte';
+	import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from '@sveltestrap/sveltestrap';
+
+	type Theme = 'light' | 'dark' | 'auto';
+
+	let theme: Theme = 'auto';
+
+	// Set the theme based on user selection and store it in localStorage
+	function setTheme(newTheme: Theme) {
+		theme = newTheme;
+		localStorage.setItem('theme', newTheme);
+		applyTheme(newTheme);
+	}
+
+	// Apply the selected theme to the document
+	function applyTheme(selectedTheme: Theme) {
+		if (selectedTheme === 'auto') {
+			const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
+			document.documentElement.setAttribute('data-bs-theme', prefersDark ? 'dark' : 'light');
+		} else {
+			document.documentElement.setAttribute('data-bs-theme', selectedTheme);
+		}
+	}
+
+	// On component mount, check localStorage and apply the saved theme
+	onMount(() => {
+		const savedTheme = (localStorage.getItem('theme') as Theme) || 'auto';
+		applyTheme(savedTheme);
+		theme = savedTheme;
+
+		// Listen for changes in the system color scheme preference
+		const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
+		mediaQuery.addEventListener('change', () => {
+			if (theme === 'auto') {
+				applyTheme('auto');
+			}
+		});
+	});
+</script>
+
+<Dropdown inNavbar class="ms-3">
+	<DropdownToggle nav caret>
+		{theme === 'auto' ? '🌗' : theme === 'dark' ? '🌙' : '☀️'}
+	</DropdownToggle>
+	<DropdownMenu end>
+		<DropdownItem active={theme === 'light'} on:click={() => setTheme('light')}
+			>☀️ Light</DropdownItem
+		>
+		<DropdownItem active={theme === 'dark'} on:click={() => setTheme('dark')}>🌙 Dark</DropdownItem>
+		<DropdownItem active={theme === 'auto'} on:click={() => setTheme('auto')}>🌗 Auto</DropdownItem>
+	</DropdownMenu>
+</Dropdown>
diff --git a/src/lib/style/app.scss b/src/lib/style/app.scss
index 00bf40b..0fd0702 100644
--- a/src/lib/style/app.scss
+++ b/src/lib/style/app.scss
@@ -9,7 +9,7 @@
 
 @import './satsymbol';
 
-$color-mode-type: media-query;
+$color-mode-type: data;
 $font-family-base: 'Ubuntu';
 $font-size-base: 0.9rem;
 $input-font-size-sm: $font-size-base * 0.875;
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index a34ea20..494ab86 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -15,6 +15,7 @@
 
 	import { page } from '$app/stores';
 	import { locale, locales, isLoading } from 'svelte-i18n';
+	import ColorSchemeSwitcher from '../components/ColorSchemeSwitcher.svelte';
 
 	export const setLocale = (lang: string) => () => {
 		locale.set(lang);
@@ -88,6 +89,7 @@
 				</DropdownMenu>
 			</Dropdown>
 		{/if}
+		<ColorSchemeSwitcher></ColorSchemeSwitcher>
 	</Collapse>
 </Navbar>