theme switch as component, fixed accessibility

This commit is contained in:
madrilene 2024-02-09 11:07:18 +01:00
parent 010051f823
commit be5ada8bdf
6 changed files with 69 additions and 57 deletions

View file

@ -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",

View 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>

View file

@ -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>

View file

@ -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();})();

View file

@ -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);
}

View file

@ -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();