Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions apps/svelte.dev/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
/>

<script>
document.documentElement.classList.add(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do need this to avoid/minimize the FOUC

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no you don't, it's injected via ThemeToggle.svelte

JSON.parse(localStorage.getItem('svelte:theme'))?.current ??
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
);

document.documentElement.classList.add(
`font-${localStorage.getItem('svelte:font') ?? 'elegant'}`
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { afterNavigate, goto, replaceState } from '$app/navigation';
import type { Gist } from '$lib/db/types';
import { Repl } from '@sveltejs/repl';
import { theme } from '@sveltejs/site-kit/stores';
import { theme } from '@sveltejs/site-kit/state';
import { mapbox_setup } from '../../../../config.js';
import AppControls from './AppControls.svelte';
import { compress_and_encode_text, decode_and_decompress_text } from './gzip.js';
Expand Down Expand Up @@ -240,7 +240,7 @@
injectedJS={mapbox_setup}
{onchange}
{download}
previewTheme={$theme.current}
previewTheme={theme.current}
/>
</div>
{/if}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { browser } from '$app/environment';
import { afterNavigate, replaceState } from '$app/navigation';
import { theme } from '@sveltejs/site-kit/stores';
import { theme } from '@sveltejs/site-kit/state';
import { Repl } from '@sveltejs/repl';
import { mapbox_setup } from '../../../../../config.js';
import { page } from '$app/state';
Expand Down Expand Up @@ -50,7 +50,7 @@
{relaxed}
can_escape
injectedJS={mapbox_setup}
previewTheme={$theme.current}
previewTheme={theme.current}
embedded
/>
{/if}
Expand Down
27 changes: 12 additions & 15 deletions apps/svelte.dev/src/routes/tutorial/[...slug]/Output.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<script lang="ts">
import { browser, dev } from '$app/environment';
import { afterNavigate } from '$app/navigation';
import { theme, type Theme } from '@sveltejs/site-kit/stores';
import { theme } from '@sveltejs/site-kit/state';
import { onMount } from 'svelte';
import Chrome from './Chrome.svelte';
import Loading from './Loading.svelte';
Expand Down Expand Up @@ -43,18 +43,6 @@
clearTimeout(timeout);
});

function change_theme(theme: Theme) {
if (!iframe) return;

try {
const url = new URL(iframe.src);

url.searchParams.set('theme', theme.current);

iframe.src = url.href;
} catch {}
}

let timeout: any;

async function handle_message(e: MessageEvent) {
Expand Down Expand Up @@ -97,7 +85,7 @@
parentNode?.removeChild(iframe);

const url = new URL(src);
url.searchParams.set('theme', $theme.current);
url.searchParams.set('theme', theme.current);

iframe.src = url.href;
parentNode?.appendChild(iframe);
Expand All @@ -112,8 +100,17 @@
$effect(() => {
if (adapter_state.base) set_iframe_src(adapter_state.base + (path = exercise.path));
});

$effect(() => {
change_theme($theme);
if (!iframe) return;

try {
const url = new URL(iframe.src);

url.searchParams.set('theme', theme.current);

iframe.src = url.href;
} catch {}
});
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import Viewer from '@sveltejs/repl/viewer';
// @ts-expect-error TODO types
import Console, { type Log } from '@sveltejs/repl/console';
import { theme } from '@sveltejs/site-kit/stores';
import { theme } from '@sveltejs/site-kit/state';
import Chrome from './Chrome.svelte';
import Loading from './Loading.svelte';
import { adapter_state, update } from './adapter.svelte';
Expand Down Expand Up @@ -37,7 +37,7 @@
can_escape
onLog={(l: Log[]) => (logs = l)}
{bundle}
theme={$theme.current}
theme={theme.current}
injectedCSS="@import '/tutorial/shared.css';"
/>
{/if}
Expand Down
6 changes: 3 additions & 3 deletions packages/repl/src/lib/Input/RunesInfo.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
let { runes }: { runes: boolean } = $props();

const { workspace, svelteVersion } = get_repl_context();
const majorVersion = Number(svelteVersion.split(".")[0]);
const majorVersion = Number(svelteVersion.split('.')[0]);
</script>

<Dropdown align="right">
Expand All @@ -19,8 +19,8 @@
<div class="popup">
{#if Number.isInteger(majorVersion) && majorVersion < 5}
<p>
<a href="/blog/runes">Runes</a> are available from Svelte 5 onwards, and this playground is
using Svelte {svelteVersion}.
<a href="/blog/runes">Runes</a> are available from Svelte 5 onwards, and this playground
is using Svelte {svelteVersion}.
</p>
{:else if workspace.current.name.endsWith('.svelte.js')}
<p>
Expand Down
3 changes: 3 additions & 0 deletions packages/site-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
"./actions": {
"default": "./src/lib/actions/index.ts"
},
"./state": {
"default": "./src/lib/state/index.ts"
},
"./stores": {
"default": "./src/lib/stores/index.ts"
},
Expand Down
36 changes: 21 additions & 15 deletions packages/site-kit/src/lib/components/ThemeToggle.svelte
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
<script lang="ts">
import { on } from 'svelte/events';
import { theme } from '../stores';
import { theme } from '../state';

function toggle() {
const next = $theme.current === 'light' ? 'dark' : 'light';
const system = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';

$theme.preference = next === system ? 'system' : next;
$theme.current = next;
theme.current = theme.current === 'light' ? 'dark' : 'light';
}

$effect(() => {
if ($theme.preference === 'system') {
const query = window.matchMedia('(prefers-color-scheme: dark)');

return on(query, 'change', (e) => {
$theme.current = e.matches ? 'dark' : 'light';
});
}
document.documentElement.classList.remove('light', 'dark');
document.documentElement.classList.add(theme.current);
});
</script>

<svelte:head>
<script>
{
const theme = localStorage.getItem('sv:theme');

document.documentElement.classList.add(
theme === 'system'
? window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
: theme
);
}
</script>
</svelte:head>

<button
onclick={toggle}
class="raised icon"
type="button"
aria-pressed={$theme.current === 'dark'}
aria-pressed={theme.current === 'dark'}
aria-label="Toggle dark mode"
></button>

Expand Down
39 changes: 39 additions & 0 deletions packages/site-kit/src/lib/state/Persisted.svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { on } from 'svelte/events';
import { createSubscriber } from 'svelte/reactivity';

export class Persisted<T extends string = string> {
#key: string;
#storage: Storage | undefined;
#fallback: T;
#version = $state(0);

#subscribe = createSubscriber((update) => {
return on(window, 'storage', (e) => {
if (e.key === this.#key) {
update();
}
});
});

constructor(
key: string,
fallback: T,
storage = typeof localStorage === 'undefined' ? undefined : localStorage
) {
this.#key = key;
this.#fallback = fallback;
this.#storage = storage;
}

get current() {
this.#subscribe(); // handle cross-tab updates
this.#version; // handle same-tab updates

return (this.#storage?.getItem(this.#key) as T) ?? this.#fallback;
}

set current(v: T) {
this.#storage?.setItem(this.#key, v);
this.#version += 1;
}
}
2 changes: 2 additions & 0 deletions packages/site-kit/src/lib/state/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Persisted } from './Persisted.svelte';
export { theme } from './theme.svelte';
18 changes: 18 additions & 0 deletions packages/site-kit/src/lib/state/theme.svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { MediaQuery } from 'svelte/reactivity';
import { Persisted } from './Persisted.svelte';

class Theme {
#preference = new Persisted<'system' | 'light' | 'dark'>('sv:theme', 'system');
#query = new MediaQuery('prefers-color-scheme: dark');
#system = $derived<'dark' | 'light'>(this.#query.current ? 'dark' : 'light');

get current() {
return this.#preference.current === 'system' ? this.#system : this.#preference.current;
}

set current(value: 'light' | 'dark') {
this.#preference.current = value === this.#system ? 'system' : value;
}
}

export const theme = new Theme();
1 change: 0 additions & 1 deletion packages/site-kit/src/lib/stores/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ export { mql } from './mql';
export { nav_open, on_this_page_open, overlay_open, should_nav_autohide } from './nav';
export { reduced_motion } from './reduced-motion';
export { search_query, search_recent, searching } from './search';
export { theme, type Theme } from './theme';
23 changes: 0 additions & 23 deletions packages/site-kit/src/lib/stores/theme.ts

This file was deleted.

Loading