feat: coordinate sections signs and native navigation
This commit is contained in:
@@ -1,43 +1,34 @@
|
||||
<script setup lang="ts">
|
||||
import type { SectionId } from '@/content/types';
|
||||
import { watch } from "vue";
|
||||
import type { SectionId } from "@/content/types";
|
||||
import { useJourneySections } from "@/composables/useJourneySections";
|
||||
import { useKeyboardNavigation } from "@/composables/useKeyboardNavigation";
|
||||
|
||||
defineProps<{ items: ReadonlyArray<{ id: SectionId; label: string }> }>();
|
||||
const props = defineProps<{
|
||||
items: ReadonlyArray<{ id: SectionId; label: string }>;
|
||||
}>();
|
||||
const canonicalIds = props.items.map((item) => item.id);
|
||||
const navigation = useKeyboardNavigation(canonicalIds);
|
||||
const journey = useJourneySections(canonicalIds, navigation.state);
|
||||
|
||||
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 }));
|
||||
};
|
||||
watch(
|
||||
() => journey.value.activeSectionId,
|
||||
(id) => navigation.notePassiveSection(id),
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="site-navigation" aria-label="Portfolio sections">
|
||||
<ul>
|
||||
<li v-for="item in items" :key="item.id">
|
||||
<a :href="`#${item.id}`" @click="focusActivatedSection">{{ item.label }}</a>
|
||||
<a
|
||||
:href="`#${item.id}`"
|
||||
:aria-current="
|
||||
journey.activeSectionId === item.id ? 'page' : undefined
|
||||
"
|
||||
@click="navigation.onSectionLinkClick"
|
||||
>{{ item.label }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
Reference in New Issue
Block a user