Waypoint / Scrollspy
Highlights the navigation entry for the section currently in view as the user scrolls, driven by the useWaypoint composable.
<!-- Sidebar scrollspy navigation -->
<nav class="vd-waypoint-nav"
data-vd-waypoint-nav="#scroll-container">
<a href="#section-1" class="is-active">Section 1</a>
<a href="#section-2">Section 2</a>
<a href="#section-3">Section 3</a>
</nav>
<div id="scroll-container" style="overflow-y:auto;">
<div id="section-1">...</div>
<div id="section-2">...</div>
<div id="section-3">...</div>
</div>Underline Variant
Overview of the current section with a compact underline indicator.
<nav class="vd-waypoint-nav vd-waypoint-underline"
data-vd-waypoint-nav="window">
<a href="#overview" class="is-active">Overview</a>
<a href="#features">Features</a>
<a href="#pricing">Pricing</a>
</nav>Pill Variant
Getting started stays selected while the card remains anchored in place.
<nav class="vd-waypoint-nav vd-waypoint-pill"
data-vd-waypoint-nav="#content">
<a href="#start" class="is-active">Getting Started</a>
<a href="#components">Components</a>
<a href="#utilities">Utilities</a>
</nav>API Reference
Wiring
import { ref } from 'vue';
import { useWaypoint } from "@vanduo-oss/vd3";
const root = ref<HTMLElement | null>(null);
useWaypoint(root); // wires [data-vd-waypoint-nav] inside root; cleanup on unmount
// react to the active section changing
root.value?.addEventListener('waypoint:change', (e) => {
console.log('active', e.detail.activeId);
});CSS Classes
| Class | Description | Type |
|---|---|---|
.vd-waypoint-nav | Base scrollspy navigation container — required | Base |
.vd-waypoint-border | Adds a left border highlight on the active link (sidebar style) | Modifier |
.vd-waypoint-pill | Rounded pill-shaped background on the active link | Modifier |
.vd-waypoint-underline | Bottom underline indicator on the active link (tab style) | Modifier |
.is-active | Applied automatically to the currently visible section's link | State |
Data Attributes
| Attribute | Description | Default |
|---|---|---|
data-vd-waypoint-nav | Selector for the scrollable container to observe (e.g. "#content" or "window") | window |
data-vd-waypoint-offset | Pixel offset from the top to trigger activation earlier or later | 0 |
data-vd-scrollspy-nav | Alias for data-vd-waypoint-nav | — |
Composable API
| Symbol | Description |
|---|---|
useWaypoint(root) | Composable — wires every [data-vd-waypoint-nav] inside the root ref; highlights the link of the topmost visible section. Call once in setup(). |
(automatic cleanup) | The IntersectionObserver and click listeners are removed on component unmount. |
Events
| Event | Description | Detail |
|---|---|---|
waypoint:change | Fired on the nav element when the active section changes | { activeId, link } |
Accessibility
- Navigation container uses
role="navigation"witharia-label="Table of contents" - Active link receives
aria-current="true"in addition to the.is-activeclass - Links use standard anchor elements for native keyboard navigation and focus management
- Smooth scrolling respects
prefers-reduced-motionmedia query - Section targets use semantic heading hierarchy for screen reader landmark navigation