Component Contract
In-page Nav (Table of Contents)
A vertical “On this page” anchor list that tracks the reader's position in long-form content.
Live Demo
Rendered
On this page
First link shown as the current section (.active).
1. Summary
| Component name | In-page Nav (Table of Contents) |
|---|---|
| AEM resource type | caat/components/in-page-nav |
| Tier | Base — composes nothing but tokens |
| Purpose | An anchor list to page sections, highlighting the current one as the reader scrolls. Reusable on any long page (articles, policy, guides). |
| Variants | Default · Sticky (--sticky) |
| Status | New |
| Replaces | .caat-article__toc (article-internal) |
Used by
- Article Layout — sidebar table of contents.
- Any long-form page (policy, guides, FAQ) needing section wayfinding.
2. Design Tokens
| Token | Role |
|---|---|
--caat-color-bg-page / --caat-color-border | Card surface + border |
--caat-color-text | Link (resting) |
--caat-color-text-link-hover | Link hover + active accent rule |
--caat-color-text-heading | Title + active link text |
--caat-color-state-selected-subtle | Active link background |
--caat-color-focus-ring / outline | Focus indicator |
3. Authoring Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| Title | Text | No | Default "On this page" |
| Source | Select | Yes | Auto (from page headings) · Manual list |
| Items (manual) | Multifield | Conditional | Label + anchor target |
| Sticky | Checkbox | No | Pins the nav while scrolling (when standalone) |
4. Validation Rules
No author-managed content beyond an accessible label, so there are no authoring validation rules. Accessibility requirements are covered in Section 8 (Accessibility).
5. Content Guidance
- Use for pages longer than ~3 screens with clear section headings.
- Mirror the page's
<h2>headings; keep labels short. - Don't duplicate the global navigation — this is within-page wayfinding only.
6. Semantic HTML
<div class="caat-in-page-nav" data-bs-spy="…">
<p class="caat-in-page-nav__title">On this page</p>
<nav class="nav flex-column" aria-label="On this page">
<a class="nav-link active" href="#calculated">How your pension is calculated</a>
<a class="nav-link" href="#retirement">When can you retire?</a>
</nav>
</div>
Use Bootstrap Scrollspy to toggle .active on the current section's link automatically.
7. CSS Contract
| Selector | Purpose |
|---|---|
.caat-in-page-nav | Card wrapper (surface, border, padding) |
.caat-in-page-nav--sticky | Pins to top: 5rem while scrolling |
.caat-in-page-nav__title | Uppercase section heading |
.caat-in-page-nav .nav-link | Anchor link; .active shows current section (left accent + subtle bg + bold) |
:hover · :focus-visible | States |
8. Accessibility
| Requirement | Implementation |
|---|---|
| Landmark | Wrap links in <nav aria-label="On this page"> so it's a distinct, named landmark. |
| Current section | Active link carries aria-current="true" (in addition to .active), and is not signalled by colour alone (left accent + weight). |
| Keyboard / focus | Native anchors; visible :focus-visible outline. |
| Target size | Comfortable link padding meets the 24px target. |
9. SEO
Transient / structural UI with no indexable content of its own — no SEO markup required. Ensure any content this component wraps or reveals stays server-rendered and crawlable.
10. Analytics
Analytics are captured through the shared data-analytics-component attribute on the component root (emitted automatically) and reported to the central data layer. Event names and payloads follow the organisation's standard analytics schema — defined centrally with the analytics team, not invented per component — so no bespoke tracking is specified here.
11. AEM Implementation Notes
- Resource type:
caat/components/in-page-nav. - Auto mode: a Sling model harvests
<h2>ids from the page's content tree; manual mode reads an items multifield. - Bootstrap Scrollspy is initialised on the article body container.
12. Dialog Model (cq:dialog)
Not authored directly. The in page nav is a sub-element emitted and configured by its host component (or generated from page structure), so it has no standalone cq:dialog — any options are exposed through the host component's dialog.
13. QA Checklist
| # | Check | Pass? |
|---|---|---|
| 1 | Active link tracks the scrolled section (scrollspy) | |
| 2 | Current section signalled by accent + weight, not colour alone | |
| 3 | Wrapped in a labelled <nav> landmark | |
| 4 | Keyboard focus ring visible on each link | |
| 5 | Every anchor resolves to a real page id |
14. Definition of Done
- Styling token-driven — no hard-coded colours.
- Scrollspy wired; active state + aria-current verified.
- article-layout refactored to consume it (was
.caat-article__toc). - Accessibility audit — landmark, focus, colour-independence.
- QA checklist signed off.