mirror of
https://codeberg.org/likwid/likwid.git
synced 2026-02-09 21:13:09 +00:00
ux: improve navigation accessibility
This commit is contained in:
parent
b501c9da75
commit
8ce353262b
3 changed files with 108 additions and 8 deletions
|
|
@ -114,6 +114,30 @@
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.is-scroll-locked {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link {
|
||||||
|
position: fixed;
|
||||||
|
top: 0.75rem;
|
||||||
|
left: 0.75rem;
|
||||||
|
z-index: 1000;
|
||||||
|
padding: 0.65rem 0.9rem;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
background: var(--color-surface);
|
||||||
|
color: var(--color-text);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
|
transform: translateY(calc(-100% - 1rem));
|
||||||
|
transition: transform var(--motion-normal) var(--easing-standard);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link:focus,
|
||||||
|
.skip-link:focus-visible {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: var(--color-primary-muted);
|
background: var(--color-primary-muted);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ const publicDemoSite = isEnabled((globalThis as any).process?.env?.PUBLIC_DEMO_S
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<a class="skip-link" href="#main-content">Skip to content</a>
|
||||||
<VotingIcons />
|
<VotingIcons />
|
||||||
<div class="app">
|
<div class="app">
|
||||||
<header class="header">
|
<header class="header">
|
||||||
|
|
@ -109,7 +110,7 @@ const publicDemoSite = isEnabled((globalThis as any).process?.env?.PUBLIC_DEMO_S
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<main class="main">
|
<main class="main" id="main-content" tabindex="-1">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
|
|
@ -121,15 +122,29 @@ const publicDemoSite = isEnabled((globalThis as any).process?.env?.PUBLIC_DEMO_S
|
||||||
const nav = document.getElementById('site-nav');
|
const nav = document.getElementById('site-nav');
|
||||||
const navToggle = document.getElementById('nav-toggle');
|
const navToggle = document.getElementById('nav-toggle');
|
||||||
|
|
||||||
function setNavOpen(open) {
|
function openNav() {
|
||||||
if (!nav || !navToggle) return;
|
if (!nav || !navToggle) return;
|
||||||
nav.classList.toggle('is-open', open);
|
nav.classList.add('is-open');
|
||||||
navToggle.setAttribute('aria-expanded', open ? 'true' : 'false');
|
navToggle.setAttribute('aria-expanded', 'true');
|
||||||
|
if (window.matchMedia('(max-width: 640px)').matches) {
|
||||||
|
document.body.classList.add('is-scroll-locked');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeNav() {
|
||||||
|
if (!nav || !navToggle) return;
|
||||||
|
nav.classList.remove('is-open');
|
||||||
|
navToggle.setAttribute('aria-expanded', 'false');
|
||||||
|
document.body.classList.remove('is-scroll-locked');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nav && navToggle) {
|
if (nav && navToggle) {
|
||||||
navToggle.addEventListener('click', () => {
|
navToggle.addEventListener('click', () => {
|
||||||
setNavOpen(!nav.classList.contains('is-open'));
|
if (nav.classList.contains('is-open')) {
|
||||||
|
closeNav();
|
||||||
|
} else {
|
||||||
|
openNav();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
nav.addEventListener('click', (event) => {
|
nav.addEventListener('click', (event) => {
|
||||||
|
|
@ -138,13 +153,27 @@ const publicDemoSite = isEnabled((globalThis as any).process?.env?.PUBLIC_DEMO_S
|
||||||
if (target.closest('#nav-toggle')) return;
|
if (target.closest('#nav-toggle')) return;
|
||||||
if (!target.closest('a')) return;
|
if (!target.closest('a')) return;
|
||||||
if (window.matchMedia('(max-width: 640px)').matches) {
|
if (window.matchMedia('(max-width: 640px)').matches) {
|
||||||
setNavOpen(false);
|
closeNav();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
if (!nav.classList.contains('is-open')) return;
|
||||||
|
const target = event.target;
|
||||||
|
if (!(target instanceof Node)) return;
|
||||||
|
if (nav.contains(target)) return;
|
||||||
|
closeNav();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
closeNav();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
if (window.innerWidth > 640) {
|
if (window.innerWidth > 640) {
|
||||||
setNavOpen(false);
|
closeNav();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ const defaultTheme = DEFAULT_THEME;
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<a class="skip-link" href="#main-content">Skip to content</a>
|
||||||
<div class="public-app">
|
<div class="public-app">
|
||||||
<header class="public-header">
|
<header class="public-header">
|
||||||
<nav class="public-nav" id="public-nav">
|
<nav class="public-nav" id="public-nav">
|
||||||
|
|
@ -108,7 +109,7 @@ const defaultTheme = DEFAULT_THEME;
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<main class="public-main">
|
<main class="public-main" id="main-content" tabindex="-1">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
<footer class="public-footer">
|
<footer class="public-footer">
|
||||||
|
|
@ -156,15 +157,39 @@ const defaultTheme = DEFAULT_THEME;
|
||||||
if (!nav || !toggle) return;
|
if (!nav || !toggle) return;
|
||||||
nav.classList.add('is-open');
|
nav.classList.add('is-open');
|
||||||
toggle.setAttribute('aria-expanded', 'true');
|
toggle.setAttribute('aria-expanded', 'true');
|
||||||
|
if (window.matchMedia('(max-width: 768px)').matches) {
|
||||||
|
document.body.classList.add('is-scroll-locked');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeNav() {
|
function closeNav() {
|
||||||
if (!nav || !toggle) return;
|
if (!nav || !toggle) return;
|
||||||
nav.classList.remove('is-open');
|
nav.classList.remove('is-open');
|
||||||
toggle.setAttribute('aria-expanded', 'false');
|
toggle.setAttribute('aria-expanded', 'false');
|
||||||
|
document.body.classList.remove('is-scroll-locked');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setActiveNav() {
|
||||||
|
const links = document.querySelectorAll('#public-nav-menu a');
|
||||||
|
const path = window.location.pathname.replace(/\/$/, '') || '/';
|
||||||
|
|
||||||
|
links.forEach((a) => {
|
||||||
|
if (!(a instanceof HTMLAnchorElement)) return;
|
||||||
|
const hrefPath = a.pathname.replace(/\/$/, '') || '/';
|
||||||
|
if (hrefPath === '/' || hrefPath === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isActive = path === hrefPath || path.indexOf(hrefPath + '/') === 0;
|
||||||
|
if (isActive) {
|
||||||
|
a.setAttribute('aria-current', 'page');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nav && toggle) {
|
if (nav && toggle) {
|
||||||
|
setActiveNav();
|
||||||
|
|
||||||
toggle.addEventListener('click', () => {
|
toggle.addEventListener('click', () => {
|
||||||
if (nav.classList.contains('is-open')) {
|
if (nav.classList.contains('is-open')) {
|
||||||
closeNav();
|
closeNav();
|
||||||
|
|
@ -181,6 +206,20 @@ const defaultTheme = DEFAULT_THEME;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
if (!nav.classList.contains('is-open')) return;
|
||||||
|
const target = event.target;
|
||||||
|
if (!(target instanceof Node)) return;
|
||||||
|
if (nav.contains(target)) return;
|
||||||
|
closeNav();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('keydown', (event) => {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
closeNav();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
if (window.innerWidth > 768) {
|
if (window.innerWidth > 768) {
|
||||||
closeNav();
|
closeNav();
|
||||||
|
|
@ -331,6 +370,14 @@ const defaultTheme = DEFAULT_THEME;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-links a[aria-current='page'] {
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links a[aria-current='page']::after {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-actions {
|
.nav-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue