diff --git a/assets/main.js b/assets/main.js index 35c7f745..ca459c0f 100644 --- a/assets/main.js +++ b/assets/main.js @@ -2,7 +2,53 @@ 'use strict'; const onLoaded = () => { - // Nothing for now + document.documentElement.classList.add('js'); + + for (const header of document.querySelectorAll('.sidebar .sub-title')) { + header.role = 'button'; + header.tabIndex = 0; + header.ariaExpanded = true; + header.ariaControlsElement = header.nextElementSibling; + const toggle = () => { + header.nextElementSibling.classList.toggle('collapsed'); + const collapsed = + header.nextElementSibling.classList.contains('collapsed'); + header.ariaExpanded = !collapsed; + header.parentNode.classList.toggle('collapsed', collapsed); + }; + header.addEventListener('click', toggle); + header.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === 'Space' || e.key === ' ') { + toggle(); + e.preventDefault(); + } + }); + if (!header.nextElementSibling.querySelector('.active')) { + toggle(); + } + } + + const toggle = document.querySelector('.sidebar .toggle-button'); + toggle.addEventListener('click', () => { + const collapsed = document.querySelectorAll( + '.sidebar li.collapsed:not(.stay-collapsed)' + ); + if (collapsed.length) { + for (const collapsible of collapsed) { + collapsible.querySelector('.sub-title').click(); + } + toggle.querySelector('strong').textContent = '\u2212'; // minus sign + toggle.querySelector('span').textContent = 'Collapse All'; + } else { + for (const collapsible of document.querySelectorAll( + '.sidebar > ul > li:not(.stay-collapsed)' + )) { + collapsible.querySelector('.sub-title').click(); + } + toggle.querySelector('strong').textContent = '+'; + toggle.querySelector('span').textContent = 'Expand All'; + } + }); }; if (['interactive', 'complete'].indexOf(document.readyState) !== -1) { diff --git a/assets/style.scss b/assets/style.scss index 460744ac..372e2b3f 100644 --- a/assets/style.scss +++ b/assets/style.scss @@ -77,7 +77,7 @@ table { border-spacing: 0; } -a { +a:not(:focus-visible) { outline: 0; } @@ -125,6 +125,10 @@ body { margin-top: 12px; margin-bottom: 52px; + :root.js & { + margin-bottom: 42px; + } + img { height: 38px; } @@ -138,9 +142,52 @@ body { } } + .toggle-button { + -webkit-appearance: none; + appearance: none; + background: lighten($darkest, 4%); + border: none; + border-radius: 4px; + padding: 6px 12px 4px; + margin: 0; + font: inherit; + cursor: pointer; + color: inherit; + margin-bottom: 20px; + display: flex; + align-items: center; + font-weight: 500; + + strong { + font-size: 1.3em; + line-height: 0; + margin-right: 0.5em; + margin-bottom: 0.1em; + } + + &:hover, + &:focus { + background: lighten($darkest, 8%); + } + &:active { + background: lighten($darkest, 12%); + } + + :root:not(.js) & { + display: none; + } + } + & > ul > li { margin-bottom: 26px; + &.collapsed { + & > .sub-title::before { + transform: rotate(-90deg); + } + margin-bottom: 10px; + } + &:last-child { margin-bottom: 0; } @@ -151,6 +198,21 @@ body { padding: 10px; font-weight: 500; text-transform: uppercase; + + :root.js & { + -webkit-user-select: none; + user-select: none; + cursor: pointer; + + &::before { + content: ''; + display: inline-block; + width: 8px; + height: 8px; + margin-right: 10px; + background: url('data:image/svg+xml;utf8,') no-repeat; + } + } } & > ul a { @@ -161,11 +223,11 @@ body { padding: 10px; } - .sub-menu { - a.active { - color: $vibrant; - } + a.active { + color: $vibrant; + } + .sub-menu { &.collapsed { display: none; } @@ -840,4 +902,4 @@ main { align-content: center; margin-left: 0.25em; } -} \ No newline at end of file +} diff --git a/layouts/partials/sidebar.html b/layouts/partials/sidebar.html index f93a3515..7c839615 100644 --- a/layouts/partials/sidebar.html +++ b/layouts/partials/sidebar.html @@ -4,8 +4,9 @@