Skip to content

Add a sticky table of contents to lesson pages #131

Description

@ebouchut

Need

Lesson pages have no table of contents: readers of long lessons cannot
see the structure or jump to a section, and there are no heading
anchors to deep-link to.

Design

See ADR-0018

Hybrid, per the discussion and wireframe review:

  • Server: a post-sanitization pass in the renderer mints slugified
    anchor ids on h2..h4 and returns the TOC entries alongside the
    HTML.
    Ids are minted by our code AFTER sanitization, so
    author-supplied ids still die (the sanitizer strips id today, and
    that protects the #main skip-link target).
    The allowlist does not change, and spoofing stays structurally impossible.
  • Template: a details/summary TOC inside nav aria-label="Contents",
    rendered when the lesson has at least 2 entries.
    Sticky: a pinned sidebar on desktop (internal scroll for long TOCs)
    and a slim pinned collapsed bar on mobile, so the TOC is
    viewable at any scroll position. Works without JavaScript.
  • Client: lesson-toc.js auto-opens the panel on wide screens and
    adds an IntersectionObserver scroll-spy that marks the current
    section with aria-current (CP4: dynamic interface).

Acceptance criteria

  • Lessons with 2+ headings show the TOC; anchor links jump to the
    section and update the URL hash; single-heading lessons show none.
  • The TOC is viewable at any scroll position, desktop (pinned
    sidebar) and mobile (pinned collapsed bar), with no horizontal
    page scroll.
  • Without JavaScript, the TOC is present, sticky, and expandable
    (MockMvc pins the server-rendered nav and anchors).
  • Author-supplied ids in raw HTML are stripped; minted slugs fold
    accents and deduplicate repeated headings.
  • Scroll-spy moves aria-current across TOC links while scrolling.
  • axe (WCAG 2.1 A/AA) reports no new violations in both themes;
    full test suite and Checkstyle stay green.

Metadata

Metadata

Assignees

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions