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
61 changes: 30 additions & 31 deletions src/app.html
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/images/logos/logo.svg" />
<link rel="stylesheet" href="/icon-font/aw-icon.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="”twitter:site”" content="@appwrite" />
%sveltekit.head%
</head>
<body class="theme-dark" data-sveltekit-preload-data="hover">
<script
type="module"
src="https://unpkg.com/@splinetool/viewer@0.9.455/build/spline-viewer.js"
></script>
<script>
const isDocs = window.location.pathname.startsWith('/docs');
if (isDocs) {
const theme = localStorage.getItem('theme');
document.body.classList.remove('theme-dark', 'theme-light') || 'dark';
if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
document.body.classList.add(`theme-${systemTheme}`);
} else {
document.body.classList.add(`theme-${theme}`);
}
localStorage.setItem('theme', theme);

<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/images/logos/logo.svg" />
<link rel="stylesheet" href="/icon-font/aw-icon.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="”twitter:site”" content="@appwrite" />
%sveltekit.head%
</head>

<body class="theme-dark" data-sveltekit-preload-data="hover">
<script>
const isDocs = window.location.pathname.startsWith('/docs');
if (isDocs) {
const theme = localStorage.getItem('theme');
document.body.classList.remove('theme-dark', 'theme-light');
if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
document.body.classList.add(`theme-${systemTheme}`);
} else {
document.body.classList.add(`theme-${theme}`);
}
</script>
<div id="top" style="display: contents">%sveltekit.body%</div>
</body>
</html>
}
</script>
<script type="module" src="https://unpkg.com/@splinetool/viewer@0.9.455/build/spline-viewer.js"></script>
<div id="top" style="display: contents">%sveltekit.body%</div>
</body>

</html>
50 changes: 7 additions & 43 deletions src/lib/components/ThemeSelect.svelte
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
<script lang="ts">
import { capitalize } from '$lib/utils/capitalize.js';
import { currentTheme, setTheme, type Theme } from '$routes/+layout.svelte';
import { createSelect, melt } from '@melt-ui/svelte';
import { onMount } from 'svelte';
import { fly } from 'svelte/transition';

const iconMap = {
const iconMap: Record<Theme, string> = {
dark: 'aw-icon-dark',
light: 'aw-icon-light',
system: 'icon-server'
} as const;
};

const themes = ['dark', 'light', 'system'] as const;

type Theme = (typeof themes)[number];
function isTheme(theme: unknown): theme is Theme {
return themes.includes(theme as Theme);
}
const themes: Array<Theme> = ['dark', 'light', 'system'];

const {
elements: { trigger, menu, option },
states: { open, selected, selectedLabel }
} = createSelect<Theme>({
preventScroll: false,
defaultSelected: {
value: 'dark',
label: 'Dark'
value: $currentTheme,
label: capitalize($currentTheme)
},
positioning: {
sameWidth: true,
Expand All @@ -33,44 +28,13 @@
forceVisible: true,
onSelectedChange({ curr, next }) {
const t = next?.value;
if (isTheme(t) && t !== curr?.value) {
if (t && t !== curr?.value) {
setTheme(t);
}
open.set(false);
return next;
}
});

function setSelected(theme: Theme) {
selected.set({
value: theme,
label: capitalize(theme)
});
}

function setTheme(theme: Theme) {
document.body.classList.remove('theme-dark', 'theme-light');
if (theme === 'system') {
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
document.body.classList.add(`theme-${systemTheme}`);
} else {
document.body.classList.add(`theme-${theme}`);
}
localStorage.setItem('theme', theme);
}

onMount(() => {
const theme = localStorage.getItem('theme');
if (isTheme(theme)) {
setTheme(theme);
setSelected(theme);
} else {
setTheme('dark');
setSelected('dark');
}
});
</script>

<button class="aw-select is-colored" use:melt={$trigger}>
Expand Down
4 changes: 0 additions & 4 deletions src/lib/layouts/Main.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,6 @@
label: 'Blog',
href: '/blog'
},
// {
// label: 'Changelog',
// href: '#'
// },
{
label: 'Pricing',
href: '/pricing'
Expand Down
73 changes: 72 additions & 1 deletion src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
<script lang="ts" context="module">
export type Theme = 'dark' | 'light' | 'system';
export const currentTheme = writable<Theme>(getPreferredTheme());

function isTheme(theme: unknown): theme is Theme {
return ['dark', 'light', 'system'].includes(theme as Theme);
}

function getSystemTheme(): Theme {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}

function getPreferredTheme() {
if (!browser) {
return 'dark';
}

const theme = globalThis?.localStorage.getItem('theme');

if (!isTheme(theme)) {
return 'dark';
}

if (theme === 'system') {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}

return theme;
}

export function setTheme(theme: string) {
if (!isTheme(theme)) {
return;
}
currentTheme.set(theme === 'system' ? getSystemTheme() : theme);
globalThis?.localStorage.setItem('theme', theme);
}
</script>

<script lang="ts">
import '@fontsource/inter/100.css';
import '@fontsource/inter/200.css';
Expand All @@ -9,7 +48,39 @@
import '@fontsource/inter/800.css';
import '@fontsource/inter/900.css';
import '$scss/index.scss';
import { dev } from '$app/environment';
import { browser, dev } from '$app/environment';
import { writable } from 'svelte/store';
import { navigating, page } from '$app/stores';
import { onMount } from 'svelte';

function applyTheme(theme: Omit<Theme, 'system'>) {
const className = `theme-${theme}`;
document.body.classList.add(className);
document.body.classList.remove(`theme-${theme === 'dark' ? 'light' : 'dark'}`);
}

onMount(() => {
const initialTheme = $page.route.id?.startsWith('/docs') ? getPreferredTheme() : 'dark';

applyTheme(initialTheme);

navigating.subscribe((n) => {
if (!n?.to) {
return;
}

const isDocs = n.to.route.id?.startsWith('/docs');

if (isDocs) {
if (!document.body.classList.contains(`theme-${$currentTheme}`)) {
applyTheme($currentTheme);
}
} else {
applyTheme('dark');
}
});
});
$: browser && currentTheme.subscribe((theme) => applyTheme(theme));
</script>

<svelte:head>
Expand Down