feat: improved tab navigation

This commit is contained in:
Cory Dransfeldt 2024-06-18 15:32:25 -07:00
parent 7943179e16
commit ccce1537fd
No known key found for this signature in database
20 changed files with 171 additions and 59 deletions

View file

@ -1,4 +1,4 @@
window.onload = () => {
window.addEventListener('load', () => {
const initializeButtonSet = (buttonSet) => {
const buttons = buttonSet.querySelectorAll('button')
const buttonIds = Array.from(buttons).map(button => button.getAttribute('data-toggle'))
@ -27,4 +27,4 @@ window.onload = () => {
const buttonSets = document.querySelectorAll('.section-header-buttons')
buttonSets.forEach(initializeButtonSet)
}
})

View file

@ -0,0 +1,64 @@
window.addEventListener('load', () => {
const menuInput = document.getElementById('menu-toggle')
const menuButtonContainer = document.querySelector('.menu-button-container')
const menuItems = document.querySelectorAll('.menu-primary li[role="menu-item"]')
const isMobile = () => window.innerWidth <= 768
const updateTabIndex = () => {
const isExpanded = menuInput.checked
menuButtonContainer.setAttribute('aria-expanded', isExpanded)
menuItems.forEach(item => {
const link = item.querySelector('a')
if (link) link.setAttribute('tabindex', isMobile() && !isExpanded ? '-1' : '0')
})
}
const handleMenuChange = () => {
updateTabIndex()
if (menuInput.checked) {
const firstLink = menuItems[0].querySelector('a')
if (firstLink) firstLink.focus()
} else {
menuButtonContainer.focus()
}
}
updateTabIndex()
menuInput.addEventListener('change', handleMenuChange)
menuButtonContainer.addEventListener('keydown', e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
menuInput.checked = !menuInput.checked
handleMenuChange()
}
})
menuItems.forEach(item => {
item.addEventListener('keydown', e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
item.querySelector('a').click()
}
})
})
document.addEventListener('keydown', e => {
if (e.key === 'Escape') {
if (isMobile() && menuInput.checked) {
menuInput.checked = false
handleMenuChange()
}
}
})
window.addEventListener('resize', () => {
updateTabIndex()
if (!isMobile() && menuInput.checked) {
menuInput.checked = false
handleMenuChange()
}
})
})

View file

@ -1,4 +1,4 @@
window.onload = () => {
window.addEventListener('load', () => {
const button = document.querySelector('[data-toggle-button]')
const content = document.querySelector('[data-toggle-content]')
const text = document.querySelectorAll('[data-toggle-content] p')
@ -21,4 +21,4 @@ window.onload = () => {
button.textContent = 'Show more'
}
});
}
})

View file

@ -35,6 +35,11 @@ body {
height: var(--sizing-xs);
}
a:focus,
a:focus-within {
outline: 2px dashed var(--accent-color);
}
body::-webkit-scrollbar {
width: var(--sizing-md);
height: var(--sizing-md);

View file

@ -1,4 +1,9 @@
button {
&:focus,
&:focus-within {
outline: 2px dashed var(--accent-color);
}
&:not(.theme-toggle) {
border-radius: var(--rounded-full);
padding: var(--sizing-sm) var(--sizing-lg);

View file

@ -18,16 +18,13 @@ textarea {
margin-bottom: var(--sizing-base);
font-weight: var(--font-weight-base);
line-height: var(--line-height-base);
transition-property: border-color;
transition-timing-function: var(--transition-ease-in-out);
transition-duration: var(--transition-duration-default);
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="search"]:focus,
textarea:focus {
border: 1px solid var(--accent-color-hover);
input:focus,
input:focus-within,
textarea:focus,
textarea:focus-within {
outline: 2px dashed var(--accent-color);
}
.search__results {

View file

@ -24,22 +24,25 @@
.menu-button-container {
display: none;
margin-left: var(--sizing-md);
outline: 0;
& .menu-open,
& .menu-closed {
cursor: pointer;
&:focus,
&:focus-within {
outline: 2px dashed var(--accent-color);
}
& svg {
cursor: pointer;
transform: rotate(0deg);
transition-property: transform;
transition-timing-function: var(--transition-ease-in-out);
transition-duration: var(--transition-duration-default);
}
& svg:hover,
& svg:active,
& svg:focus {
&:hover svg,
&:focus svg,
&:focus-within svg,
&:active svg {
stroke: var(--accent-color-hover);
transform: rotate(8deg);
}
@ -49,24 +52,24 @@
display: none;
}
#menu-toggle:checked + .menu-button-container {
& .menu-closed {
display: none;
}
& .menu-open {
display: block;
}
#menu-toggle:checked + .menu-button-container .menu-closed {
display: none;
}
#menu-toggle:not(:checked) + .menu-button-container {
& .menu-closed {
display: block;
}
#menu-toggle:checked + .menu-button-container .menu-open {
display: block;
}
& .menu-open {
display: none;
}
#menu-toggle:not(:checked) + .menu-button-container .menu-closed {
display: block;
}
#menu-toggle:not(:checked) + .menu-button-container .menu-open {
display: none;
}
a[role="menu-item"]:focus {
outline: none;
}
@media (max-width: 768px) {
@ -120,6 +123,17 @@
& .active {
font-size: var(--font-size-lg);
}
&:focus a,
&:focus-within a {
outline: 0;
}
&:focus,
&:focus-within {
border-top: 2px dashed var(--accent-color);
border-bottom: 2px dashed var(--accent-color);
}
}
.menu-button-container {

View file

@ -11,6 +11,18 @@ theme-toggle {
& svg {
cursor: pointer;
transform: rotate(0deg);
transition-property: transform;
transition-timing-function: var(--transition-ease-in-out);
transition-duration: var(--transition-duration-default);
}
&:hover svg,
&:focus svg,
&:focus-within svg,
&:active svg {
stroke: var(--accent-color-hover);
transform: rotate(8deg);
}
& > .light svg { stroke: var(--sun) !important; }

View file

@ -37,8 +37,8 @@
}
& .progress-bar-wrapper {
margin-top: var(--font-size-xs);
max-width: 75%;
margin-bottom: 0;
}
& blockquote.description {
@ -65,6 +65,7 @@
& p {
&.title {
font-size: var(--font-size-xl);
line-height: 1;
}
&.sub-meta {
@ -109,6 +110,7 @@
align-items: start;
& .progress-bar-wrapper {
margin-top: 0;
max-width: 40%;
}
}