test: lock semantic and no-script portfolio behavior
This commit is contained in:
@@ -2,13 +2,42 @@
|
||||
import type { SectionId } from '@/content/types';
|
||||
|
||||
defineProps<{ items: ReadonlyArray<{ id: SectionId; label: string }> }>();
|
||||
|
||||
const focusActivatedSection = (event: MouseEvent): void => {
|
||||
if (
|
||||
event.defaultPrevented ||
|
||||
event.button !== 0 ||
|
||||
event.altKey ||
|
||||
event.ctrlKey ||
|
||||
event.metaKey ||
|
||||
event.shiftKey ||
|
||||
!(event.currentTarget instanceof HTMLAnchorElement)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let sectionId: string;
|
||||
try {
|
||||
sectionId = decodeURIComponent(event.currentTarget.hash.slice(1));
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const section = document.getElementById(sectionId);
|
||||
const heading = section?.querySelector<HTMLElement>(
|
||||
':scope > h2[tabindex="-1"]',
|
||||
);
|
||||
if (heading === undefined || heading === null) return;
|
||||
|
||||
requestAnimationFrame(() => heading.focus({ preventScroll: true }));
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="site-navigation" aria-label="Portfolio sections">
|
||||
<ul>
|
||||
<li v-for="item in items" :key="item.id">
|
||||
<a :href="`#${item.id}`">{{ item.label }}</a>
|
||||
<a :href="`#${item.id}`" @click="focusActivatedSection">{{ item.label }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
Reference in New Issue
Block a user