Dark mode toggle (#36)

* Add dark and light mode icons
* Respect user's OS preferences, unless they toggle manually


Co-authored-by: Brian Ginsburg <7957636+bgins@users.noreply.github.com>
This commit is contained in:
Jess Martin 2022-08-24 16:17:03 -04:00 committed by GitHub
parent f57beafa6c
commit eec81aa1bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 10 deletions

View File

@ -37,6 +37,6 @@
</head> </head>
<body> <body>
<div id="svelte">%sveltekit.body%</div> <div id="svelte" class="h-screen">%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@ -1,8 +1,16 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import { sessionStore } from '../stores' import { sessionStore, theme } from '../stores'
import { storeTheme, type Theme } from '$lib/theme/index'
import Shield from '$components/icons/Shield.svelte' import Shield from '$components/icons/Shield.svelte'
import LightMode from '$components/icons/LightMode.svelte'
import DarkMode from '$components/icons/DarkMode.svelte'
const setTheme = (newTheme: Theme) => {
theme.set(newTheme)
storeTheme(newTheme)
}
</script> </script>
<header class="navbar bg-base-100 pt-0"> <header class="navbar bg-base-100 pt-0">
@ -24,10 +32,22 @@
</button> </button>
</div> </div>
<span class="mr-2">
{#if $theme === 'light'}
<span on:click={() => setTheme('dark')}>
<LightMode />
</span>
{:else}
<span on:click={() => setTheme('light')}>
<DarkMode />
</span>
{/if}
</span>
{#if !$sessionStore.loading} {#if !$sessionStore.loading}
{#if !$sessionStore.authed} {#if !$sessionStore.authed}
<div class="flex-none"> <div class="flex-none">
<a class="btn btn-sm btn-primary normal-case" href="/connect"> <a class="btn btn-sm h-10 btn-primary normal-case" href="/connect">
Connect Connect
</a> </a>
</div> </div>

View File

@ -0,0 +1,16 @@
<svg
width="41"
height="40"
viewBox="0 0 41 40"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="stroke-slate-50 fill-slate-900 hover:stroke-slate-900 hover:fill-slate-50 hover:cursor-pointer transition-colors"
>
<rect x="1" y="0.5" width="39" height="39" rx="19.5" />
<path
d="M28.8542 23.3542C27.8176 23.7708 26.6856 24.0001 25.5 24.0001C20.5294 24.0001 16.5 19.9706 16.5 15.0001C16.5 13.8145 16.7292 12.6825 17.1458 11.6459C13.8365 12.9758 11.5 16.2151 11.5 20.0001C11.5 24.9706 15.5294 29.0001 20.5 29.0001C24.285 29.0001 27.5243 26.6636 28.8542 23.3542Z"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 673 B

View File

@ -0,0 +1,16 @@
<svg
width="41"
height="40"
viewBox="0 0 41 40"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="stroke-slate-900 fill-slate-50 hover:stroke-slate-50 hover:fill-slate-900 hover:cursor-pointer transition-colors"
>
<rect x="1" y="0.5" width="39" height="39" rx="19.5" />
<path
d="M20.5 11V12M20.5 28V29M29.5 20H28.5M12.5 20H11.5M26.864 26.364L26.1569 25.6569M14.8431 14.3431L14.136 13.636M26.864 13.6361L26.1569 14.3432M14.8432 25.6569L14.1361 26.364M24.5 20C24.5 22.2091 22.7091 24 20.5 24C18.2909 24 16.5 22.2091 16.5 20C16.5 17.7909 18.2909 16 20.5 16C22.7091 16 24.5 17.7909 24.5 20Z"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 700 B

View File

@ -4,7 +4,12 @@ export type Theme = 'light' | 'dark'
export const loadTheme = (): Theme => { export const loadTheme = (): Theme => {
if (browser) { if (browser) {
return (localStorage.getItem('theme') as Theme) ?? 'light' const browserTheme = localStorage.getItem('theme') as Theme
const osTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
return browserTheme ?? (osTheme as Theme) ?? 'light'
} }
} }

View File

@ -5,17 +5,12 @@
import { appName } from '$lib/app-name' import { appName } from '$lib/app-name'
import { initialize } from '$lib/common/webnative' import { initialize } from '$lib/common/webnative'
import { deviceStore, sessionStore, theme } from '../stores' import { deviceStore, sessionStore, theme } from '../stores'
import { storeTheme } from '$lib/theme'
import { errorToMessage, type Session } from '$lib/session' import { errorToMessage, type Session } from '$lib/session'
import Toast from '$components/notifications/Toast.svelte' import Toast from '$components/notifications/Toast.svelte'
import Header from '$components/Header.svelte' import Header from '$components/Header.svelte'
let session: Session = null let session: Session = null
theme.subscribe(val => {
storeTheme(val)
})
sessionStore.subscribe(val => { sessionStore.subscribe(val => {
session = val session = val
}) })
@ -50,7 +45,7 @@
<svelte:window on:resize={setDevice} /> <svelte:window on:resize={setDevice} />
<div data-theme={$theme}> <div data-theme={$theme} class="h-screen">
<Header /> <Header />
{#if session.error} {#if session.error}