feat: improved tab navigation
This commit is contained in:
parent
7943179e16
commit
ccce1537fd
20 changed files with 171 additions and 59 deletions
|
@ -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)
|
||||
}
|
||||
})
|
64
src/assets/scripts/menu.js
Normal file
64
src/assets/scripts/menu.js
Normal 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()
|
||||
}
|
||||
})
|
||||
})
|
|
@ -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'
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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%;
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue