🌓 Adds Dark Mode (#210)

* feat(dark mode): set up first set of colors

* feat(dark mode): define state colours

* 🧹

* feat(dark mode): variablify all teh wordz

* feat(dark mode): set colors on body

* feat(dark mode): replace hard coded color value

* feat(dark mode): 🌑

* feat(a11y): update link focus styles

- restores visible focus in windows high contrast mode
- increases visibility in boxes with bg colour

* feat(dark mode): enable postcss

* 💅

* feat(dark mode): add user control

* chore: use generic headline name

* feat(dark mode): hide switch until script loads

* feat(dark mode): increase link contrast

* add content warning to footer nav partial

* feat(dark mode): replace hard coded colour value in alertbox

* feat(dark mode): tone down text colour

* feat(dark mode): properly invert code elements

* 🧹 move box styles into own partial

* feat(dark mode): use darker colour as background for links
This commit is contained in:
Oscar
2020-08-26 12:10:24 +02:00
committed by GitHub
parent 7f11b552a6
commit 7f7943d2fc
31 changed files with 880 additions and 241 deletions

7
11ty/_data/site.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = {
themes: [
{ value: 'system', label: 'Operating System' },
{ value: 'light', label: 'Light' },
{ value: 'dark', label: 'Dark' }
]
};

View File

@ -0,0 +1,29 @@
<footer class="site-footer">
<nav aria-label="Complimentary">
<ul class="navigation-list">
<li>
<a href="/documentation/">Documentation</a>
</li>
<li>
<a href="/content-warning-guidelines/">Content Warning Guidelines</a>
</li>
<li>
<a href="{{ metadata.feedPermalink | absoluteUrl(metadata.url) }}">RSS Feed</a>
</li>
</ul>
</nav>
<div role="group" class="js-theme-switch" aria-labelledby="clrmd-hl" hidden>
<h2 id="clrmd-hl" class="smcp-headline">Colour mode</h2>
{% for theme in site.themes %}
<div class="radio-wrapper">
<input
type="radio"
name="display-mode"
value="{{ theme.value }}"
id="display-mode-{{ theme.value }}"
>
<label for="display-mode-{{ theme.value }}">{{ theme.label }}</label>
</div>
{% endfor %}
</div>
</footer>

View File

@ -42,22 +42,9 @@
</head>
<body>
{% block content %}{% endblock content %}
<footer class="site-footer">
<nav aria-label="Complimentary">
<ul class="navigation-list">
<li>
<a href="/documentation/">Documentation</a>
</li>
<li>
<a href="/content-warning-guidelines/">Content Warning Guidelines</a>
</li>
<li>
<a href="{{ metadata.feedPermalink | absoluteUrl(metadata.url) }}">RSS Feed</a>
</li>
</ul>
</nav>
</footer>
{% include 'components/base/site-footer.njk' %}
{% block pageScript %}
{% endblock pageScript %}
</body>
<script defer src="/js/theme-switcher.js"></script>
</html>

View File

@ -0,0 +1,63 @@
function initThemeSwitch() {
let $switchContainer = document.querySelector('.js-theme-switch');
if (!$switchContainer) return;
$switchContainer.hidden = false;
let userOverwrite = ['light', 'dark'];
let $buttons = $switchContainer.querySelectorAll('[type="radio"]');
/**
* @type String
*/
let userThemeSetting = localStorage.getItem('sdUserTheme');
function setInitialState() {
if (userThemeSetting) {
document.documentElement.setAttribute(
'data-user-theme',
userThemeSetting
);
$switchContainer.querySelector(
`[value="${userThemeSetting}"]`
).checked = true;
} else {
$switchContainer.querySelector('[value="system"]').checked = true;
}
}
function setUserPreference(value) {
localStorage.setItem('sdUserTheme', value);
document.documentElement.setAttribute('data-user-theme', value);
}
function unsetUserPreference() {
localStorage.removeItem('sdUserTheme');
document.documentElement.removeAttribute('data-user-theme');
}
Array.from($buttons).forEach(function($button) {
$button.addEventListener('change', function() {
// only run the switch functionality for the currently active radio button
if (!$button.checked) return;
if (userOverwrite.includes($button.value)) {
setUserPreference($button.value);
} else {
unsetUserPreference();
}
});
});
setInitialState();
}
if (document.readyState === 'complete') {
initThemeSwitch();
} else {
window.addEventListener('load', function() {
initThemeSwitch();
});
}

View File

@ -11,11 +11,11 @@ test('first item', (t) => {
renderDefinitionContentNextEntries(title, slug, testCollection),
`<section class="definition-navigation definition__further-definitions_nav">
<h2 class="visually-hidden">Browse</h2>
<div><h3 class="definition-navigation__sub-headline" id="context-nav-previous">Previous words</h3>
<div><h3 class="smcp-headline" id="context-nav-previous">Previous words</h3>
<nav class="definition-navigation__nav" aria-labelledby="context-nav-previous">
</nav>
</div>
<div><h3 class="definition-navigation__sub-headline" id="context-nav-next">Next words</h3>
<div><h3 class="smcp-headline" id="context-nav-next">Next words</h3>
<nav class="definition-navigation__nav" aria-labelledby="context-nav-next"><ul class="definition-navigation__list"><li><a href=/definitions/ableism/>Ableism</a></li><li><a href=/definitions/barbaric/>Barbaric</a></li><li><a href=/definitions/biromantic/>Biromantic</a></li></ul></nav>
</div>
</section>`
@ -28,11 +28,11 @@ test('last item', (t) => {
renderDefinitionContentNextEntries(title, slug, testCollection),
`<section class="definition-navigation definition__further-definitions_nav">
<h2 class="visually-hidden">Browse</h2>
<div><h3 class="definition-navigation__sub-headline" id="context-nav-previous">Previous words</h3>
<div><h3 class="smcp-headline" id="context-nav-previous">Previous words</h3>
<nav class="definition-navigation__nav" aria-labelledby="context-nav-previous">
<ul class="definition-navigation__list"><li><a href=/definitions/transgender/>Transgender</a></li><li><a href=/definitions/unreal/>unreal</a></li><li><a href=/definitions/white-fragility/>White Fragility</a></li></ul></nav>
</div>
<div><h3 class="definition-navigation__sub-headline" id="context-nav-next">Next words</h3>
<div><h3 class="smcp-headline" id="context-nav-next">Next words</h3>
<nav class="definition-navigation__nav" aria-labelledby="context-nav-next"></nav>
</div>
</section>`

View File

@ -19,7 +19,7 @@ module.exports = function definitionContentNextEntries(
return `<section class="definition-navigation definition__further-definitions_nav">
<h2 class="visually-hidden">Browse</h2>
<div><h3 class="definition-navigation__sub-headline" id="context-nav-previous">Previous words</h3>
<div><h3 class="smcp-headline" id="context-nav-previous">Previous words</h3>
<nav class="definition-navigation__nav" aria-labelledby="context-nav-previous">
${
previous.length
@ -29,7 +29,7 @@ module.exports = function definitionContentNextEntries(
: ''
}</nav>
</div>
<div><h3 class="definition-navigation__sub-headline" id="context-nav-next">Next words</h3>
<div><h3 class="smcp-headline" id="context-nav-next">Next words</h3>
<nav class="definition-navigation__nav" aria-labelledby="context-nav-next">${
next.length
? `<ul class="definition-navigation__list">${next