Mobile plan section navigation and desktop TOC filtering
Long plan entities (specs, work items, decisions) are hard to navigate on mobile — you have to scroll through the entire document to reach a section. The toolbar scrolls away so you can't even reach the sidebar nav. On desktop, the TOC sidebar lists every H2/H3 heading, which becomes a wall of text for detailed specs and is hard to scan.
Plan runes already declare known sections with canonical names (Acceptance Criteria, Dependencies, Approach, etc.) and the transform wraps them in <section data-name="..."> elements. We can leverage this to build focused section navigation for both mobile and desktop.
Acceptance Criteria
- Plan toolbar is sticky on mobile (stays visible when scrolling)
- Toolbar title shows the entity ID (e.g., "WORK-127") instead of the hardcoded "Plan"
- Toolbar has a three-dot icon button on the right side that opens a section nav
- Section nav lists only known sections present on the current page
- Tapping a section in the nav smooth-scrolls to that section
- Current section is highlighted in the section nav via scrollspy integration
- Section nav dismisses after selecting a section
- On desktop, the TOC sidebar for plan pages is filtered to known sections only (not all H2/H3 headings)
- Plan rune transform marks known-section headings with a
data-known-sectionattribute so both mobile nav and desktop TOC can key off the same signal - Spec and milestone runes (which lack known sections) retain the existing full-heading TOC behaviour
Dependencies
- Add knownSections to Plan Rune Content Models — knownSections framework support (done)
- knownSections scanner integration: section-scoped refs and validation — scanner integration for known sections (done)
Approach
Three layers of change:
1. Transform: mark known-section headings. During plan rune transform, add data-known-section to the H2 heading element of each known section. This provides a single signal that both the mobile behavior and the desktop TOC builder can use.
2. Layout + CSS: sticky toolbar with page ID and section nav trigger. Make the plan toolbar position: sticky. Source the title from the page's entity ID (available in frontmatter). Add a three-dot chrome element on the right side. The section nav should be a compact dropdown/popover (not a fullscreen panel — there are only 4-6 items). Wire scrollspy to highlight the active section.
3. Desktop TOC filtering. The buildToc() function in packages/transform/src/computed.ts currently includes all headings matching minLevel/maxLevel. For the plan layout, add filtering to only include headings that have data-known-section. Since this attribute is added at transform time, the TOC builder (which runs after transform) can read it. Spec and milestone runes don't declare known sections, so their headings won't have the attribute — the TOC should fall back to the existing full-heading behaviour when no known-section headings are found.
References
- Plan Site UX at Scale — Plan site UX (notes mobile-specific UI as out of scope, but this is a targeted improvement that benefits responsive use)
- Plan Package Hardening — Plan package hardening (knownSections design)
Resolution
Completed: 2026-04-12
Branch: claude/mobile-plan-section-nav-SNE06
What was done
runes/plan/src/util.ts—buildSectionsnow addsdata-known-sectionattribute (canonical name) to H2 headings that match a known section via$canonicalNamefrom the resolverrunes/plan/src/commands/render-pipeline.ts— AddedannotateKnownSections()that walks the rendered Markdoc tree post-transform and propagatesdata-known-sectionto theHeadingInfoarray; populatedfrontmatter.toolbarTitlewith entity ID for layout accesspackages/runes/src/util.ts— ExtendedHeadingInfointerface with optionalknownSectionfieldpackages/transform/src/types.ts— ExtendedLayoutPageData.headingstype withknownSectionpackages/transform/src/layouts.ts— Plan layout: toolbar title usespageText: 'frontmatter.toolbarTitle'(shows entity ID), addedsectionNavTogglechrome element (three-dot button), addedsection-navbehavior, setknownSectionsOnly: trueon TOC computed configpackages/transform/src/layout.ts—resolveComputedTOC case: addedknownSectionsOnlyfiltering with fallback to all headings when no known sections existpackages/behaviors/src/behaviors/section-nav.ts— New behavior: scans[data-known-section]headings, builds dropdown with smooth-scroll links, integrates IntersectionObserver scrollspy for active section highlighting, dismisses on selection/Escape/outside-clickpackages/behaviors/src/index.ts— Registeredsection-navas layout behaviorrunes/plan/styles/default.css— Sticky toolbar (position: sticky; top: 0; z-index: 100), toolbar title flex-grow for button alignment, section nav toggle button styles, section nav dropdown (absolute positioned, shadow, active state with blue border accent)
Notes
- The
data-known-sectionattribute serves as the single source of truth for both the mobile section nav behavior and the desktop TOC filter — no duplication of known-section definitions - Desktop TOC filtering uses a graceful fallback: when
knownSectionsOnlyis true but no headings haveknownSectionset (specs, milestones), the full H2/H3 heading list is used instead - The section-nav behavior hides the toggle button entirely when no
[data-known-section]headings exist on the page
Relationships
Depends on
History
- 0ed7874statusready→done
- ☑ Plan toolbar is sticky on mobile (stays visible when scrolling)
- ☑ Toolbar title shows the entity ID (e.g., "WORK-127") instead of the hardcoded "Plan"
- ☑ Toolbar has a three-dot icon button on the right side that opens a section nav
- +7 more criteria
- 9e16183Created (ready, medium, moderate, SPEC-015, plan, layout, mobile, behaviors, css)