Skip to content

feat: section: entries with children become island tree nodes - #3867

Merged
theletterf merged 13 commits into
mainfrom
feature/section-island-sidebars
Aug 14, 2026
Merged

feat: section: entries with children become island tree nodes#3867
theletterf merged 13 commits into
mainfrom
feature/section-island-sidebars

Conversation

@theletterf

Copy link
Copy Markdown
Member

Summary

Follows up on #3792 to close the sidebar gap: section: entries with children: now become real SectionNavigation tree nodes (islands), giving every page in a grouped set a back-link breadcrumb to the section and preserving URL invariance throughout.

Problem: On #3792, Guides groups six toc roots but from any get-started page there is no sidebar path to Solutions or Manage data. The roots are flatly added as direct children of SiteNavigation and have no shared parent to link back to.

Fix: A section: with children creates a SectionNavigation node (IRootNavigationItem, IsIsland = true, Parent = SiteNavigation). Child docset roots are nested under it, each still individually marked as islands.

Behavior:

  • FindIslandRoot() from a deep page stops at the child docset root (not the section), so each docset renders its own sidebar tree unchanged.
  • CreateBackLinks emits "← Guides" because SectionNavigation is the immediate parent of the child island.
  • SectionTopNavBuilder collects child IDs from SectionNavigation.NavigationItems for multi-root active-state matching in the secondary nav bar.

URL invariance: HomeProvider.NavigationRoot = SectionNavigation and SectionNavigation.Parent is SiteNavigation, so relativeToContainer stays true at every depth — no page URL moves.

Files changed

File Change
src/Elastic.Documentation.Navigation/Assembler/SectionNavigation.cs New: island tree node for grouped sections
src/Elastic.Documentation.Navigation/Assembler/SiteNavigation.cs Create SectionNavigation for sections with children instead of flattening
src/services/Elastic.Documentation.Assembler/Navigation/SectionTopNavBuilder.cs Look up section children from tree node, not flat TopLevelItems
tests/Navigation.Tests/Assembler/SectionNavigationTests.cs 7 new tests: tree structure, island flags, FindIslandRoot, back-link, URL invariance, tab SectionIds

Known limitation (Phase 2)

The section's Url resolves to the first child's URL (e.g. /docs/get-started). Clicking "← Guides" navigates back to that page rather than a dedicated Guides landing page. Phase 2 adds a synthetic section landing page that renders the six child roots as stub rows, making the two-click navigation (back-link → stub click → sibling) fully functional.

Test plan

  • dotnet build — zero errors, zero lint warnings
  • 223 navigation tests pass (7 new + 216 existing)
  • SectionNavigationTests: tree structure, island flags, FindIslandRoot returns child not section, "← Guides" back-link present, URL invariance, SectionTopNavBuilder SectionIds correct
  • Preview build against navigation_preview.yml to verify Guides tab active state and back-link renders on get-started pages

🤖 Generated with Claude Code

@theletterf
theletterf requested a review from a team as a code owner August 14, 2026 08:34
@theletterf
theletterf requested a review from reakaleek August 14, 2026 08:34
@theletterf theletterf self-assigned this Aug 14, 2026
@theletterf
theletterf changed the base branch from feature/configurable-top-nav to main August 14, 2026 09:04
@theletterf

Copy link
Copy Markdown
Member Author

@Mpdreamz Feel free to merge when ready!

theletterf and others added 13 commits August 14, 2026 15:01
…w.yml

Adds a config-level section: grouping to navigation_preview.yml that maps
the 11 flat top-level toc: entries to 5 named tabs in the top nav bar.
Sections are config-only — children are added to the site tree as flat
roots, so no page URLs change.

New ISiteNavigationEntry interface and SiteSectionRef record allow the
YAML converter to parse both toc: and section: entries. SiteTableOfContents
becomes List<ISiteNavigationEntry>. SiteNavigation iterates entries and
descends into section children when encountered.

SectionTopNavBuilder derives TopNavRenderModel from the nav file's entry
list. Section tabs carry SectionIds so active state is resolved by
comparing the current page's NavigationRoot.Id to the tab's set.

BuildContext.TopNav wires the render model through to every page.
_SecondaryNav.cshtml renders the tabs and delegates dropdown/external
behaviour to secondary-nav.ts.

Section structure in navigation_preview.yml:
  - section: Guides (get-started, solutions, manage-data, explore-analyze,
                     deploy-manage, cloud-account)
  - section: Troubleshoot (troubleshoot)
  - section: Release notes (release-notes/intro + release children)
  - section: Reference (reference + reference children)
  - section: Extend (extend, contribute-docs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…row icon

Replace two-key syntax (external: true + url:) with single-key:
  - section: APIs
    external: https://...

SiteSectionRef now carries ExternalUrl (string?) with IsExternal computed.
_SecondaryNav.cshtml drops the SVG arrow from external link tabs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hetics

The sidebar dropdown (isUsingNavigationDropdown) is suppressed when
section tabs are active. Navigate to Reference via #secondary-nav instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Links to https://www.elastic.co/docs/api/ using the external: <url> syntax.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oot, Release notes, Extend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A SiteSectionRef with children now creates a SectionNavigation node
in the SiteNavigation tree instead of flattening its children directly
under the site root.

Key behaviors:
- SectionNavigation (e.g. Guides) is marked IsIsland = true with
  Parent = SiteNavigation, so RendersAsIsland() is true.
- Child docset roots (get-started, solutions, etc.) remain individual
  islands with Parent = SectionNavigation.
- FindIslandRoot() from a deep page stops at the child docset root,
  not the section, so each docset renders its own sidebar tree.
- CreateBackLinks emits a '← Guides' back-link because SectionNavigation
  is the immediate parent of the child island.
- URL invariance is preserved: HomeProvider.NavigationRoot = SectionNavigation,
  and SectionNavigation.Parent is SiteNavigation, so relativeToContainer
  stays true at every depth.
- SectionTopNavBuilder looks up SectionNavigation by title from
  TopLevelItems and collects child IDs for multi-root active-state
  matching in the secondary nav bar.

Seven new tests cover: tree structure, island flags, FindIslandRoot
returns child (not section), back-link breadcrumb, URL invariance, and
SectionTopNavBuilder SectionIds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- SiteNavigation: external/empty sections no longer fall through to the
  SiteTableOfContentsRef cast and throw; they are skipped (SectionTopNavBuilder
  handles them as tabs with no tree node).
- SectionNavigationTests: add using for SectionTopNavBuilder (IDE0002),
  remove unnecessary ! suppressors (IDE0370), use indexer instead of
  First() on IReadOnlyList (CA1826).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap top-level toc entries in section: nodes matching the island
sidebar proposal. Order: Guides, APIs (external), Reference,
Troubleshoot, Release notes, Extend.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SectionNavigation is the island; child docsets are branches within
it. FindIslandRoot now returns the section, so the sidebar shows all
sub-sections (Guides: Get started, Solutions, Manage data, ...).

Active-tab detection uses SectionId = sectionNav.Id since all pages
within the section have NavigationRoot = sectionNav.

Also reverts navigation.yml to main state: only navigation_preview.yml
carries the section: structure in this PR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…w.yml

All 69 island: true entries dropped by the initial section: rewrite
are restored. The OR-semantics override in CreateSiteTableOfContentsNavigation
means these entries (Reference sub-docsets) keep their own island sidebars
while section children without island: true (Guides) share the section sidebar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@theletterf
theletterf force-pushed the feature/section-island-sidebars branch from 3e9420b to 33e9697 Compare August 14, 2026 13:02
@theletterf
theletterf merged commit 226e4e8 into main Aug 14, 2026
25 checks passed
@theletterf
theletterf deleted the feature/section-island-sidebars branch August 14, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants