kopia lustrzana https://github.com/shoelace-style/shoelace
docs changed theme toggle to theme selector (#1395)
rodzic
8e831aa3e7
commit
2914475821
|
@ -42,8 +42,8 @@
|
||||||
<script>
|
<script>
|
||||||
(() => {
|
(() => {
|
||||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
const theme = localStorage.getItem('theme');
|
const theme = localStorage.getItem('theme') || 'auto';
|
||||||
document.documentElement.classList.toggle('sl-theme-dark', theme === 'dark' || (!theme && prefersDark));
|
document.documentElement.classList.toggle('sl-theme-dark', theme === 'dark' || (theme === 'auto' && prefersDark));
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -80,16 +80,20 @@
|
||||||
<sl-icon name="twitter"></sl-icon>
|
<sl-icon name="twitter"></sl-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{# Theme toggle #}
|
{# Theme selector #}
|
||||||
<button
|
<sl-dropdown id="theme-selector" placement="bottom-end">
|
||||||
id="theme-toggle"
|
<sl-button size="small" variant="text" slot="trigger" caret>
|
||||||
type="button"
|
|
||||||
aria-label="Toggle light and dark theme"
|
|
||||||
title="Toggle theme (press backslash)"
|
|
||||||
>
|
|
||||||
<sl-icon class="only-light" name="sun-fill"></sl-icon>
|
<sl-icon class="only-light" name="sun-fill"></sl-icon>
|
||||||
<sl-icon class="only-dark" name="moon-fill"></sl-icon>
|
<sl-icon class="only-dark" name="moon-fill"></sl-icon>
|
||||||
</button>
|
</sl-button>
|
||||||
|
<sl-menu>
|
||||||
|
<sl-menu-label>Toggle <kbd>\</kbd></sl-menu-label>
|
||||||
|
<sl-menu-item type="checkbox" value="light">Light</sl-menu-item>
|
||||||
|
<sl-menu-item type="checkbox" value="dark">Dark</sl-menu-item>
|
||||||
|
<sl-divider></sl-divider>
|
||||||
|
<sl-menu-item type="checkbox" value="auto">Auto</sl-menu-item>
|
||||||
|
</sl-menu>
|
||||||
|
</sl-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<aside id="sidebar" data-preserve-scroll>
|
<aside id="sidebar" data-preserve-scroll>
|
||||||
|
|
|
@ -74,22 +74,56 @@
|
||||||
})();
|
})();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Theme switcher
|
// Theme selector
|
||||||
//
|
//
|
||||||
(() => {
|
(() => {
|
||||||
function toggleTheme() {
|
function getTheme() {
|
||||||
const isDark = !document.documentElement.classList.contains('sl-theme-dark');
|
return localStorage.getItem('theme') || 'auto';
|
||||||
document.documentElement.classList.toggle('sl-theme-dark', isDark);
|
|
||||||
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle the theme
|
function isDark() {
|
||||||
document.addEventListener('click', event => {
|
if (theme === 'auto') {
|
||||||
const themeToggle = event.target.closest('#theme-toggle');
|
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
if (!themeToggle) return;
|
}
|
||||||
toggleTheme();
|
return theme === 'dark';
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTheme(newTheme) {
|
||||||
|
theme = newTheme;
|
||||||
|
localStorage.setItem('theme', theme);
|
||||||
|
|
||||||
|
// Update the UI
|
||||||
|
updateSelection();
|
||||||
|
|
||||||
|
// Toggle the dark mode class
|
||||||
|
document.documentElement.classList.toggle('sl-theme-dark', isDark());
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelection() {
|
||||||
|
const menu = document.querySelector('#theme-selector sl-menu');
|
||||||
|
if (!menu) return;
|
||||||
|
[...menu.querySelectorAll('sl-menu-item')].map(item => (item.checked = item.getAttribute('value') === theme));
|
||||||
|
}
|
||||||
|
|
||||||
|
let theme = getTheme();
|
||||||
|
|
||||||
|
// Selection is not preserved when changing page, so update when opening dropdown
|
||||||
|
document.addEventListener('sl-show', event => {
|
||||||
|
const themeSelector = event.target.closest('#theme-selector');
|
||||||
|
if (!themeSelector) return;
|
||||||
|
updateSelection();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Listen for selections
|
||||||
|
document.addEventListener('sl-select', event => {
|
||||||
|
const menu = event.target.closest('#theme-selector sl-menu');
|
||||||
|
if (!menu) return;
|
||||||
|
setTheme(event.detail.item.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update the theme when the preference changes
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => setTheme(theme));
|
||||||
|
|
||||||
// Toggle with backslash
|
// Toggle with backslash
|
||||||
document.addEventListener('keydown', event => {
|
document.addEventListener('keydown', event => {
|
||||||
if (
|
if (
|
||||||
|
@ -97,9 +131,12 @@
|
||||||
!event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))
|
!event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase()))
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
toggleTheme();
|
setTheme(isDark() ? 'light' : 'dark');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set the initial theme and sync the UI
|
||||||
|
setTheme(theme);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -1054,6 +1054,31 @@ html.sidebar-open #menu-toggle {
|
||||||
transition: 250ms scale ease;
|
transition: 250ms scale ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#theme-selector:not(:defined) {
|
||||||
|
/* Hide when not defined to prevent extra wide icon toolbar while loading */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#theme-selector sl-menu {
|
||||||
|
/* Set an initial size to prevent width being initally too small when first opening on small screen width */
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
#theme-selector sl-button {
|
||||||
|
transition: 250ms scale ease;
|
||||||
|
}
|
||||||
|
#theme-selector sl-button::part(base) {
|
||||||
|
color: var(--sl-color-neutral-0);
|
||||||
|
}
|
||||||
|
#theme-selector sl-button::part(label) {
|
||||||
|
display: flex;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
#theme-selector sl-icon {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
.sl-theme-dark #theme-selector sl-button::part(base) {
|
||||||
|
color: var(--sl-color-neutral-1000);
|
||||||
|
}
|
||||||
|
|
||||||
.sl-theme-dark #icon-toolbar {
|
.sl-theme-dark #icon-toolbar {
|
||||||
background: var(--sl-color-neutral-200);
|
background: var(--sl-color-neutral-200);
|
||||||
}
|
}
|
||||||
|
@ -1064,7 +1089,8 @@ html.sidebar-open #menu-toggle {
|
||||||
}
|
}
|
||||||
|
|
||||||
#icon-toolbar button:hover,
|
#icon-toolbar button:hover,
|
||||||
#icon-toolbar a:hover {
|
#icon-toolbar a:hover,
|
||||||
|
#theme-selector sl-button:hover {
|
||||||
scale: 1.1;
|
scale: 1.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,6 +1110,10 @@ html.sidebar-open #menu-toggle {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#theme-selector sl-icon {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sidebar addons */
|
/* Sidebar addons */
|
||||||
|
|
Ładowanie…
Reference in New Issue