mirror of
https://github.com/mat-1/matdoesdev.git
synced 2025-08-02 14:46:04 +00:00
add lightswitch
This commit is contained in:
parent
5376d198d7
commit
9a10a0d910
7 changed files with 147 additions and 0 deletions
21
src/app.css
21
src/app.css
|
@ -100,3 +100,24 @@ pre {
|
|||
.token.string {
|
||||
color: #aad94c;
|
||||
}
|
||||
|
||||
body.light-theme,
|
||||
body.extra-light-theme {
|
||||
--background-color: #fff;
|
||||
--background-color-transparent: #fff0;
|
||||
--background-color-alt: #f7f7f7;
|
||||
--background-color-alt-2: #eee;
|
||||
--background-color-alt-3: #ddd;
|
||||
|
||||
--text-color: #000;
|
||||
--text-color-alt: #333;
|
||||
--text-color-alt-2: #666;
|
||||
--text-color-alt-3: #999;
|
||||
}
|
||||
body.extra-light-theme {
|
||||
filter: brightness(1) opacity(0.1);
|
||||
}
|
||||
body.extra-dark-theme {
|
||||
background-color: #000;
|
||||
filter: brightness(0.1);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import { fly } from 'svelte/transition'
|
||||
import type { LayoutData } from '../$types'
|
||||
import { browser } from '$app/environment'
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
export let data: LayoutData
|
||||
|
||||
|
@ -50,6 +51,24 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
const initialTheme = localStorage.getItem('theme') ?? 'dark'
|
||||
let globalTheme = writable(initialTheme)
|
||||
window.addEventListener('storage', (e) => {
|
||||
if (e.key === 'theme' && e.newValue) {
|
||||
globalTheme.set(e.newValue)
|
||||
}
|
||||
})
|
||||
let lastGlobalTheme = initialTheme
|
||||
globalTheme.subscribe((theme) => {
|
||||
document.body.classList.remove(`${lastGlobalTheme}-theme`)
|
||||
if (theme !== 'dark') {
|
||||
document.body.classList.add(`${theme}-theme`)
|
||||
}
|
||||
lastGlobalTheme = theme
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
{#key data.pathname}
|
||||
|
|
107
src/routes/lightswitch/+page.svelte
Normal file
107
src/routes/lightswitch/+page.svelte
Normal file
|
@ -0,0 +1,107 @@
|
|||
<script lang="ts">
|
||||
import lightSwitchOnImage from './lightswitch-on.png'
|
||||
import lightSwitchOnSound from './lightswitch-on.mp3'
|
||||
import lightSwitchOffImage from './lightswitch-off.png'
|
||||
import lightSwitchOffSound from './lightswitch-off.mp3'
|
||||
|
||||
import { writable } from 'svelte/store'
|
||||
import { browser } from '$app/environment'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
let globalTheme = writable(browser ? localStorage.getItem('theme') ?? 'dark' : 'dark')
|
||||
let isLightSwitchOn = writable($globalTheme === 'light' || $globalTheme === 'extra-light')
|
||||
|
||||
let mounted = false
|
||||
|
||||
onMount(() => {
|
||||
window.addEventListener('storage', (e) => {
|
||||
if (e.key === 'theme' && e.newValue) {
|
||||
globalTheme.set(e.newValue)
|
||||
}
|
||||
})
|
||||
|
||||
mounted = true
|
||||
|
||||
let lastGlobalTheme = $globalTheme
|
||||
globalTheme.subscribe((theme) => {
|
||||
document.body.classList.remove(`${lastGlobalTheme}-theme`)
|
||||
// dark theme is the default so it doesn't need to be added
|
||||
if (theme !== 'dark') {
|
||||
document.body.classList.add(`${theme}-theme`)
|
||||
}
|
||||
lastGlobalTheme = theme
|
||||
})
|
||||
})
|
||||
|
||||
isLightSwitchOn.subscribe((isLight) => {
|
||||
if (!mounted) return
|
||||
|
||||
// play sound effect
|
||||
const audio = new Audio(isLight ? lightSwitchOnSound : lightSwitchOffSound)
|
||||
audio.play()
|
||||
|
||||
// 100ms delay to be slightly more realistic
|
||||
setTimeout(() => {
|
||||
if (isLight) {
|
||||
$globalTheme = $globalTheme !== 'light' ? 'light' : 'extra-light'
|
||||
} else {
|
||||
$globalTheme = $globalTheme !== 'dark' ? 'dark' : 'extra-dark'
|
||||
}
|
||||
localStorage.setItem('theme', $globalTheme)
|
||||
}, 100)
|
||||
})
|
||||
</script>
|
||||
|
||||
<main>
|
||||
{#if mounted}
|
||||
<button on:click={() => ($isLightSwitchOn = !$isLightSwitchOn)}>
|
||||
<img
|
||||
src={$isLightSwitchOn ? lightSwitchOnImage : lightSwitchOffImage}
|
||||
alt="Light switch on"
|
||||
class="lightswitch"
|
||||
/>
|
||||
</button>
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
<style>
|
||||
:global(html, body) {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
main {
|
||||
background-color: #000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
filter: brightness(0.5);
|
||||
}
|
||||
|
||||
:global(body.light-theme) main {
|
||||
background-color: #fff;
|
||||
filter: brightness(1);
|
||||
}
|
||||
:global(body.extra-light-theme) main {
|
||||
background-color: #fff;
|
||||
filter: brightness(1) opacity(0.1);
|
||||
}
|
||||
:global(body.extra-dark-theme) main {
|
||||
background-color: #000;
|
||||
filter: brightness(0.05);
|
||||
}
|
||||
|
||||
.lightswitch {
|
||||
image-rendering: pixelated;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
BIN
src/routes/lightswitch/lightswitch-off.mp3
Normal file
BIN
src/routes/lightswitch/lightswitch-off.mp3
Normal file
Binary file not shown.
BIN
src/routes/lightswitch/lightswitch-off.png
Normal file
BIN
src/routes/lightswitch/lightswitch-off.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
src/routes/lightswitch/lightswitch-on.mp3
Normal file
BIN
src/routes/lightswitch/lightswitch-on.mp3
Normal file
Binary file not shown.
BIN
src/routes/lightswitch/lightswitch-on.png
Normal file
BIN
src/routes/lightswitch/lightswitch-on.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Loading…
Add table
Reference in a new issue