Skip to content

feat: generalize island: true beyond listings - #3851

Merged
Mpdreamz merged 5 commits into
feature/toc-listingsfrom
feature/toc-islands
Aug 13, 2026
Merged

feat: generalize island: true beyond listings#3851
Mpdreamz merged 5 commits into
feature/toc-listingsfrom
feature/toc-islands

Conversation

@Mpdreamz

@Mpdreamz Mpdreamz commented Aug 13, 2026

Copy link
Copy Markdown
Member

Summary

Extends island: true from listing-only to any TOC element. Islands render as a stub in the parent sidebar; clicking swaps the sidebar for a dedicated island nav with a root-first back-link stack.

Stacked on: #3781

cursorful-video-1786623994046.mp4

New placement options for island: true

  • Root of docset.yml or any nested toc.yml
  • Inline beside - toc: <path> in parent docset.yml/toc.yml (OR-ed with the toc.yml's own flag — can enable, never disable)
  • Any - toc: entry in config/navigation.yml (assembler-side override; same OR semantics)
  • In isolated builds the docset root with island: true is silently inert (no parent → RendersAsIsland() returns false)
  • Nested islands: each island sidebar shows a root-first back-link stack (nav root → each enclosing island → immediate parent)
  • Existing listing: … island: true keeps working through the same mechanism

Design

Three old members (IslandListingRoot, IsIslandListing, IslandVisual) on INavigationItem are collapsed into a single bool IsIsland, set via a new IAssignableIslandNavigation interface. The island root of a page is found by walking the Parent chain:

  • RendersAsIsland()item.IsIsland && item.Parent is not null
  • FindIslandRoot() → nearest ancestor where RendersAsIsland() is true

The island view model now reuses the same NavigationRenderNode tree the main sidebar uses, plus a back-link stack from NavigationRenderModel.CreateIsland(). The old hand-rolled IslandNavGroup/IslandNavPage types and duplicated writer code are gone. NavigationRenderCache key widened from IRootNavigationItem to INavigationItem — the old per-writer ConcurrentDictionary that collided across repos is deleted.

Tests added

  • IslandNavigationTests (7 tests): isolation-level coverage of all goal cases
  • IslandSiteNavigationTests (3 tests): assembler-level OR semantics, docset root island after re-parenting, navigation.yml override
  • NavigationRenderModelTests: IslandNode_ProjectsAsIslandKind, CreateIsland_BuildsBackLinkStack, CreateIsland_ContentHash tests
  • Configuration tests: island: true parsing at all four config levels, private-repo stripping survival

Test plan

  • ./build.sh unit-test passes (4000+ tests)
  • dotnet format --verify-no-changes clean
  • Isolated serve: add island: true to a nested toc.yml, confirm stub in parent and back-link stack in island sidebar
  • Isolated serve: add island: true to docset root, confirm it renders as the main nav (root exemption)
  • Assembled build: add island: true to a navigation.yml entry, confirm island behavior with correct path_prefix-based URLs

🤖 Generated with Claude Code

@Mpdreamz
Mpdreamz requested a review from a team as a code owner August 13, 2026 09:41
@Mpdreamz
Mpdreamz requested a review from technige August 13, 2026 09:41
Mpdreamz and others added 4 commits August 13, 2026 15:30
Extends the island navigation concept from listing-only to any TOC
element. Islands render as a ≫ stub in the parent sidebar; clicking
swaps the sidebar for a dedicated island nav with a root-first back-link
stack.

## New placement options for island: true

- Root of docset.yml or any nested toc.yml
- Inline beside - toc: <path> in parent docset.yml/toc.yml (OR-ed with
  the toc.yml's own flag)
- Any - toc: entry in config/navigation.yml (assembler-side override;
  can only enable, never disable)

In isolated builds the docset root with island: true is silently inert
(no parent → RendersAsIsland() returns false). After SiteNavigation
re-parents it the same flag becomes active.

## Design

Three old members (IslandListingRoot, IsIslandListing, IslandVisual) on
INavigationItem are collapsed into a single bool IsIsland, set via a new
IAssignableIslandNavigation interface. The island root of a page is now
found by walking the Parent chain (FindIslandRoot()), which makes
nesting work for free.

RendersAsIsland() = item.IsIsland && item.Parent is not null
FindIslandRoot() = nearest ancestor where RendersAsIsland() is true

## Island sidebar

The island view model now reuses the same NavigationRenderNode tree the
main sidebar uses, plus a root-first back-link stack built by
NavigationRenderModel.CreateIsland(). The old hand-rolled
IslandNavGroup/IslandNavPage types and duplicated writer code are gone.

The NavigationRenderCache key is widened from IRootNavigationItem to
INavigationItem so islands share the same cache without the old per-
writer ConcurrentDictionary that collided across repos.

## Tests added

- IslandNavigationTests (7 tests): isolation-level coverage of all goal
  cases
- IslandSiteNavigationTests (3 tests): assembler-level OR semantics,
  docset root island after re-parenting, navigation.yml override
- NavigationRenderModelTests: IslandNode_ProjectsAsIslandKind,
  CreateIsland_BuildsBackLinkStack, CreateIsland_ContentHash tests
- Configuration Tests: island: true parsing at all four config levels,
  private-repo stripping survival

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

- SiteNavigation implicitly marks every top-level toc entry as an island
  so the two parallel 'owns the sidebar' mechanisms (top-level sections +
  explicit islands) are now one: FindIslandRoot resolves both.

- Delete _IslandNav.cshtml and IslandNavViewModel; merge their behavior
  into NavigationRenderModel + _TocTree.cshtml:
  - NavigationRenderModel.Create gains BackLinks computed from the
    render root's ancestor walk (nav root suppressed when dropdown is on)
  - CreateRootIndex now shows the island's own title row for nested islands
    in assembler builds
  - Current top-level item resolved by ancestor walk so nested islands
    correctly highlight the right dropdown entry

- Both writers simplified to a single GetOrRenderAsync(renderRoot) path;
  RenderIslandAsync removed.

- config/navigation.yml: add island: true to 69 reference section entries
  (elasticsearch, kibana, cloud, security, observability, ingestion tools,
  APM agents x8, elasticsearch-clients x11, ecs-logging x9, EDOT SDKs x8,
  beats, logstash, logstash plugins, fleet, machine-learning, search-ui, ecs)
  Top-level entries (reference, troubleshoot, …) stay without the marker —
  SiteNavigation makes them islands structurally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace heavy border-2 box back-links with compact text links in a
  subtle grouped section separated from the dropdown by a border-b line
- Add <hr class="border-grey-20"> after the island root-index row so the
  island home heading is visually distinct from the tree content below it

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Mpdreamz
Mpdreamz force-pushed the feature/toc-islands branch from 3bc6aa8 to f50cb1e Compare August 13, 2026 13:31
…tsFileSystem

FileSystemFactory.ScopeSourceDirectory was removed; callers now construct
CheckoutsFileSystem directly, matching the pattern in SiteNavigationTests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Mpdreamz
Mpdreamz merged commit e9b13b2 into main Aug 13, 2026
34 of 35 checks passed
@Mpdreamz
Mpdreamz deleted the feature/toc-islands branch August 13, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants