theme switch as component, fixed accessibility
This commit is contained in:
parent
010051f823
commit
be5ada8bdf
6 changed files with 69 additions and 57 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "eleventy-excellent",
|
||||
"version": "2.1.1",
|
||||
"version": "2.1.2",
|
||||
"description": "Eleventy starter based on the workflow suggested by Andy Bell's buildexcellentwebsit.es.",
|
||||
"author": "Lene Saile",
|
||||
"license": "ISC",
|
||||
|
|
|
|||
16
src/_includes/components/theme-switch.njk
Normal file
16
src/_includes/components/theme-switch.njk
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<div
|
||||
role="region"
|
||||
class="theme-switch | cluster mt-xs"
|
||||
style="--cluster-horizontal-alignment: center; --gutter: 0.5rem"
|
||||
aria-labelledby="theme-switcher-label"
|
||||
data-theme-switcher
|
||||
hidden
|
||||
>
|
||||
<h2 id="theme-switcher-label">{{ meta.themeSwitch.title }}</h2>
|
||||
<button class="button" id="light-theme-toggle" data-theme="light">
|
||||
<span>{{ meta.themeSwitch.light }}</span>
|
||||
</button>
|
||||
<button class="button" id="dark-theme-toggle" data-theme="dark">
|
||||
<span>{{ meta.themeSwitch.dark }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -40,24 +40,9 @@
|
|||
</nav>
|
||||
</div>
|
||||
|
||||
<div
|
||||
role="region"
|
||||
class="theme-switch | cluster mt-xs"
|
||||
style="--cluster-horizontal-alignment: center; --gutter: 0.5rem;"
|
||||
aria-labelledby="theme-switcher-label theme-switcher-value"
|
||||
data-theme-switcher
|
||||
hidden
|
||||
>
|
||||
<!-- theme switch -->
|
||||
{% include 'components/theme-switch.njk' %}
|
||||
|
||||
<h2 id="theme-switcher-label">{{ meta.themeSwitch.title }}</h2>
|
||||
<button
|
||||
class="button"
|
||||
theme-toggle
|
||||
>
|
||||
<span id="theme-switcher-value">{{ meta.themeSwitch.initial }}</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
<div class="text-center mt-m-l">
|
||||
<a class="creator text-step-min-1" href="{{ meta.creator.website }}"
|
||||
>Made with <span>{% include 'svg/heart.svg' %}</span>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
(()=>{var r="theme-preference",l="{{ meta.themeSwitch.light }}",o="{{ meta.themeSwitch.dark }}",h=()=>{e.value=e.value==="light"?"dark":"light",document.querySelector("[theme-toggle]").querySelector("span").innerHTML=e.value==="light"?l:o,n()},i=()=>localStorage.getItem(r)?localStorage.getItem(r):window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",n=()=>{localStorage.setItem(r,e.value),c()},c=()=>{document.firstElementChild.setAttribute("data-theme",e.value)},e={value:i()};c();window.onload=()=>{let t=document.querySelector("[theme-toggle]"),a=document.querySelector("[data-theme-switcher]");a&&(a.removeAttribute("hidden"),c(),t.addEventListener("click",h),t.querySelector("span").innerHTML=e.value==="light"?l:o)};window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",({matches:t})=>{e.value=t?"dark":"light",n()});})();
|
||||
(()=>{var r="theme-preference",n="{{ meta.themeSwitch.light }}",d="{{ meta.themeSwitch.dark }}",t={value:s()};window.onload=()=>{let e=document.querySelector("#light-theme-toggle"),l=document.querySelector("#dark-theme-toggle"),o=document.querySelector("[data-theme-switcher]");o&&(o.removeAttribute("hidden"),a(),e.addEventListener("click",()=>c("light")),l.addEventListener("click",()=>c("dark")),e.setAttribute("aria-pressed",t.value==="light"),l.setAttribute("aria-pressed",t.value==="dark"))};window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",({matches:e})=>{t.value=e?"dark":"light",i()});function c(e){t.value=e,document.querySelector("#light-theme-toggle").setAttribute("aria-pressed",e==="light"),document.querySelector("#dark-theme-toggle").setAttribute("aria-pressed",e==="dark"),i()}function s(){return localStorage.getItem(r)?localStorage.getItem(r):window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function i(){localStorage.setItem(r,t.value),a()}function a(){document.firstElementChild.setAttribute("data-theme",t.value),document.querySelector("#light-theme-toggle")?.setAttribute("aria-label",n),document.querySelector("#dark-theme-toggle")?.setAttribute("aria-label",d)}a();})();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,15 @@
|
|||
.theme-switch .button {
|
||||
--button-border: var(--color-bg-accent-2);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: var(--size-step-min-1);
|
||||
padding: 0.1rem 0;
|
||||
font-size: var(--size-step-min-2);
|
||||
padding: 0.1rem 0.625rem;
|
||||
font-weight: 600;
|
||||
min-block-size: 1.5em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.theme-switch .button[aria-pressed='true'] {
|
||||
--button-bg: var(--color-primary);
|
||||
--button-text: var(--color-base-light);
|
||||
--button-border: var(--color-primary);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,14 @@
|
|||
const storageKey = 'theme-preference';
|
||||
|
||||
// get labels from meta
|
||||
const lightLabel = '{{ meta.themeSwitch.light }}';
|
||||
const darkLabel = '{{ meta.themeSwitch.dark }}';
|
||||
|
||||
const onClick = () => {
|
||||
// flip current value
|
||||
theme.value = theme.value === 'light' ? 'dark' : 'light';
|
||||
document.querySelector('[theme-toggle]').querySelector('span').innerHTML =
|
||||
theme.value === 'light' ? lightLabel : darkLabel;
|
||||
setPreference();
|
||||
};
|
||||
|
||||
const getColorPreference = () => {
|
||||
if (localStorage.getItem(storageKey)) return localStorage.getItem(storageKey);
|
||||
else
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
};
|
||||
|
||||
const setPreference = () => {
|
||||
localStorage.setItem(storageKey, theme.value);
|
||||
reflectPreference();
|
||||
};
|
||||
|
||||
const reflectPreference = () => {
|
||||
document.firstElementChild.setAttribute('data-theme', theme.value);
|
||||
|
||||
// themeToggle.querySelector('span').innerHTML =
|
||||
// theme.value === 'light' ? lightLabel : darkLabel;
|
||||
};
|
||||
|
||||
const theme = {
|
||||
value: getColorPreference()
|
||||
};
|
||||
|
||||
// set early so no page flashes / CSS is made aware
|
||||
reflectPreference();
|
||||
|
||||
window.onload = () => {
|
||||
const themeToggle = document.querySelector('[theme-toggle]');
|
||||
const lightThemeToggle = document.querySelector('#light-theme-toggle');
|
||||
const darkThemeToggle = document.querySelector('#dark-theme-toggle');
|
||||
const switcher = document.querySelector('[data-theme-switcher]');
|
||||
|
||||
if (!switcher) {
|
||||
|
|
@ -46,12 +16,13 @@ window.onload = () => {
|
|||
}
|
||||
|
||||
switcher.removeAttribute('hidden');
|
||||
|
||||
reflectPreference();
|
||||
|
||||
themeToggle.addEventListener('click', onClick);
|
||||
themeToggle.querySelector('span').innerHTML =
|
||||
theme.value === 'light' ? lightLabel : darkLabel;
|
||||
lightThemeToggle.addEventListener('click', () => onClick('light'));
|
||||
darkThemeToggle.addEventListener('click', () => onClick('dark'));
|
||||
|
||||
lightThemeToggle.setAttribute('aria-pressed', theme.value === 'light');
|
||||
darkThemeToggle.setAttribute('aria-pressed', theme.value === 'dark');
|
||||
};
|
||||
|
||||
// sync with system changes
|
||||
|
|
@ -61,3 +32,36 @@ window
|
|||
theme.value = isDark ? 'dark' : 'light';
|
||||
setPreference();
|
||||
});
|
||||
|
||||
function onClick(themeValue) {
|
||||
theme.value = themeValue;
|
||||
document
|
||||
.querySelector('#light-theme-toggle')
|
||||
.setAttribute('aria-pressed', themeValue === 'light');
|
||||
document
|
||||
.querySelector('#dark-theme-toggle')
|
||||
.setAttribute('aria-pressed', themeValue === 'dark');
|
||||
setPreference();
|
||||
}
|
||||
|
||||
function getColorPreference() {
|
||||
if (localStorage.getItem(storageKey)) {
|
||||
return localStorage.getItem(storageKey);
|
||||
} else {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
}
|
||||
|
||||
function setPreference() {
|
||||
localStorage.setItem(storageKey, theme.value);
|
||||
reflectPreference();
|
||||
}
|
||||
|
||||
function reflectPreference() {
|
||||
document.firstElementChild.setAttribute('data-theme', theme.value);
|
||||
document.querySelector('#light-theme-toggle')?.setAttribute('aria-label', lightLabel);
|
||||
document.querySelector('#dark-theme-toggle')?.setAttribute('aria-label', darkLabel);
|
||||
}
|
||||
|
||||
// set early so no page flashes / CSS is made aware
|
||||
reflectPreference();
|
||||
|
|
|
|||
Loading…
Reference in a new issue