"example/vscode:/vscode.git/clone" did not exist on "cee9295124049be2b81cb4df3e8ecbd12662cd3a"
Unverified Commit 1f0dcb4f authored by Timothy Jaeryang Baek's avatar Timothy Jaeryang Baek Committed by GitHub
Browse files

Merge pull request #1115 from dannyl1u/feat/system-wide-theme

feat: system os light/dark mode option 🔦
parents 1bfcd801 19f69c82
...@@ -8,18 +8,35 @@ ...@@ -8,18 +8,35 @@
<meta name="robots" content="noindex,nofollow" /> <meta name="robots" content="noindex,nofollow" />
<script> <script>
// On page load or when changing themes, best to add inline in `head` to avoid FOUC // On page load or when changing themes, best to add inline in `head` to avoid FOUC
(() => {
if ( if (
localStorage.theme === 'light' || localStorage.theme === 'light' ||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: light)').matches) (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: light)').matches)
) { ) {
document.documentElement.classList.add('light'); document.documentElement.classList.add('light');
} else if (localStorage.theme) { } else if (localStorage.theme && localStorage.theme !== 'system') {
localStorage.theme.split(' ').forEach((e) => { localStorage.theme.split(' ').forEach((e) => {
document.documentElement.classList.add(e); document.documentElement.classList.add(e);
}); });
} else if (localStorage.theme && localStorage.theme === 'system') {
systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.classList.add(systemTheme ? 'dark' : 'light');
} else { } else {
document.documentElement.classList.add('dark'); document.documentElement.classList.add('dark');
} }
window.matchMedia('(prefers-color-scheme: dark)').addListener((e) => {
if (localStorage.theme === 'system') {
if (e.matches) {
document.documentElement.classList.add('dark');
document.documentElement.classList.remove('light');
} else {
document.documentElement.classList.add('light');
document.documentElement.classList.remove('dark');
}
}
});
})();
</script> </script>
%sveltekit.head% %sveltekit.head%
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import { getLanguages } from '$lib/i18n'; import { getLanguages } from '$lib/i18n';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
import { models, user } from '$lib/stores'; import { models, user, theme } from '$lib/stores';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
// General // General
let themes = ['dark', 'light', 'rose-pine dark', 'rose-pine-dawn light']; let themes = ['dark', 'light', 'rose-pine dark', 'rose-pine-dawn light'];
let theme = 'dark'; let selectedTheme = 'system';
let languages = []; let languages = [];
let lang = $i18n.language; let lang = $i18n.language;
let notificationEnabled = false; let notificationEnabled = false;
...@@ -68,10 +69,11 @@ ...@@ -68,10 +69,11 @@
}; };
onMount(async () => { onMount(async () => {
selectedTheme = localStorage.theme ?? 'system';
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}'); let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
languages = await getLanguages(); languages = await getLanguages();
theme = localStorage.theme ?? 'dark';
notificationEnabled = settings.notificationEnabled ?? false; notificationEnabled = settings.notificationEnabled ?? false;
system = settings.system ?? ''; system = settings.system ?? '';
...@@ -87,38 +89,52 @@ ...@@ -87,38 +89,52 @@
options = { ...options, ...settings.options }; options = { ...options, ...settings.options };
options.stop = (settings?.options?.stop ?? []).join(','); options.stop = (settings?.options?.stop ?? []).join(',');
}); });
</script>
<div class="flex flex-col h-full justify-between text-sm"> const applyTheme = (_theme: string) => {
<div class=" pr-1.5 overflow-y-scroll max-h-[22rem]"> let themeToApply = _theme;
<div class="">
<div class=" mb-1 text-sm font-medium">{$i18n.t('WebUI Settings')}</div>
<div class="flex w-full justify-between"> if (_theme === 'system') {
<div class=" self-center text-xs font-medium">{$i18n.t('Theme')}</div> themeToApply = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
<div class="flex items-center relative"> }
<select
class=" dark:bg-gray-900 w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
bind:value={theme}
placeholder="Select a theme"
on:change={(e) => {
localStorage.theme = theme;
themes themes
.filter((e) => e !== theme) .filter((e) => e !== themeToApply)
.forEach((e) => { .forEach((e) => {
e.split(' ').forEach((e) => { e.split(' ').forEach((e) => {
document.documentElement.classList.remove(e); document.documentElement.classList.remove(e);
}); });
}); });
theme.split(' ').forEach((e) => { themeToApply.split(' ').forEach((e) => {
document.documentElement.classList.add(e); document.documentElement.classList.add(e);
}); });
console.log(theme); console.log(_theme);
}} };
const themeChangeHandler = (_theme: string) => {
theme.set(_theme);
localStorage.setItem('theme', _theme);
applyTheme(_theme);
};
</script>
<div class="flex flex-col h-full justify-between text-sm">
<div class=" pr-1.5 overflow-y-scroll max-h-[22rem]">
<div class="">
<div class=" mb-1 text-sm font-medium">{$i18n.t('WebUI Settings')}</div>
<div class="flex w-full justify-between">
<div class=" self-center text-xs font-medium">{$i18n.t('Theme')}</div>
<div class="flex items-center relative">
<select
class=" dark:bg-gray-900 w-fit pr-8 rounded py-2 px-2 text-xs bg-transparent outline-none text-right"
bind:value={selectedTheme}
placeholder="Select a theme"
on:change={() => themeChangeHandler(selectedTheme)}
> >
<option value="system">⚙️ {$i18n.t('System')}</option>
<option value="dark">🌑 {$i18n.t('Dark')}</option> <option value="dark">🌑 {$i18n.t('Dark')}</option>
<option value="light">☀️ {$i18n.t('Light')}</option> <option value="light">☀️ {$i18n.t('Light')}</option>
<option value="rose-pine dark">🪻 {$i18n.t('Rosé Pine')}</option> <option value="rose-pine dark">🪻 {$i18n.t('Rosé Pine')}</option>
......
...@@ -7,7 +7,7 @@ export const config = writable(undefined); ...@@ -7,7 +7,7 @@ export const config = writable(undefined);
export const user = writable(undefined); export const user = writable(undefined);
// Frontend // Frontend
export const theme = writable('dark'); export const theme = writable('system');
export const chatId = writable(''); export const chatId = writable('');
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment