Skip to content

Prototype nav-v2: new IA with label sections, accordion sidebar#2927

Draft
theletterf wants to merge 71 commits intomainfrom
nav-v2
Draft

Prototype nav-v2: new IA with label sections, accordion sidebar#2927
theletterf wants to merge 71 commits intomainfrom
nav-v2

Conversation

@theletterf
Copy link
Copy Markdown
Member

@theletterf theletterf commented Mar 20, 2026

Prototypes a new information architecture sidebar gated behind the nav-v2 feature flag (auto-enabled in dev and preview environments). Content is served at the same URL paths as V1 — only the sidebar layout changes.

Demo: https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2927/get-started


Navigation YAML format (config/navigation-v2.yml)

A new navigation-v2.yml file drives the sidebar, separate from navigation.yml. It supports five item types:

Key Behaviour
label: Non-clickable section heading; always expanded at any depth
toc: Wires in a real TOC root (same as V1, no path_prefix: required)
page: Cross-link to a specific .md file; renders as a real clickable link
group: Placeholder folder — expand/collapse chevron, greyed link → stub page
title: Placeholder leaf — greyed link → stub page

The current navigation-v2.yml contains the full proposed IA skeleton translated from the card-sort design. page: and toc: refs are used where content already exists; group: and title: placeholders mark items still to be wired up.


Placeholder stub pages

Every title: leaf and group: folder that lacks a page: now gets a generated stub page at /{sitePrefix}/_placeholder/{hash}/. The stub renders the full site chrome (header, V2 nav sidebar, footer) with an <h1> of the placeholder title and a "This content is coming soon." paragraph.

This means all placeholder nav items are greyed but clickable — clicking them navigates to the stub instead of doing nothing.


Filling the gaps

To wire up a placeholder:

  • Replace title: Foo with toc: repo://path (optionally keeping title: Foo to override the root's own nav title) when a whole TOC root covers the topic.
  • Replace title: Foo with page: docs-content://path/to/file.md (optionally keeping title: Foo to override the page's own nav title) when a specific existing page covers the topic. The URL is resolved automatically from the file path.
  • Replace group: Foo with toc: when the folder gains a real root, or keep it as group: with page:/toc: children if the folder itself has no canonical URL.

In other words, title: doubles as a display name override — you never have to remove it when promoting a placeholder to a real link.


Sidebar behaviour

  • Labels (any depth): always expanded, no toggle, no chevron
  • group: nodes: expand/collapse toggle; accordion at top level (open one → siblings collapse); greyed link → stub page
  • toc: nodes: full live tree, same expand/collapse as V1
  • page: leaves: clickable link to the canonical page URL
  • title: leaves: greyed link → stub page

Visual hierarchy

Level Style
Level-1 label text-xs font-semibold uppercase tracking-widest · full ink · thin horizontal rule above
Level-2+ label same small-caps · 65% opacity
TOC / group / page link sentence-case, normal weight, clickable (or greyed for placeholders)

URL scheme — known limitation and future direction

toc: entries currently use the same URL paths as V1 (navigation.yml), because the file-writing pipeline (GlobalNavigationPathProvider) derives output paths from NavigationTocMappings, which is populated from navigation.yml before SiteNavigationV2 is constructed. Changes to path prefixes in the navigation model do not propagate back to where HTML files are physically written.

The intended final scheme is deterministic and URI-derived: {scheme}/{host}/{path} for non-docs-content repos, and {host}/{path} for docs-content (the default narrative repo, so the scheme adds no disambiguation value). Making this work end-to-end requires wiring the V2 nav file into AssembleSources.AssembleAsync so that NavigationTocMappings is populated from navigation-v2.yml instead of navigation.yml. That work is out of scope for this prototype PR.

🤖 Generated with Claude Code

theletterf and others added 9 commits March 20, 2026 09:37
Adds a new `navigation-v2.yml`-driven sidebar behind the `nav-v2`
feature flag (enabled by default in dev/preview environments).

- New YAML format: label sections (non-clickable headings), toc entries
  that resolve to existing navigation nodes at their original URL paths,
  page crosslinks, and title-only placeholder (disabled) links
- `SiteNavigationV2` extends `SiteNavigation`, passes the original
  nav file to the base constructor so content URLs are unchanged; builds
  a separate `V2NavigationItems` tree for sidebar rendering
- `GlobalNavigationHtmlWriter` detects `SiteNavigationV2` and returns
  the same full V2 nav HTML (cached once) for every page
- `_TocTreeNavV2.cshtml` renders labels as `<span>`, placeholders as
  `aria-disabled` anchors, folders/leaves same as V1
- `pages-nav-v2.ts` adds accordion collapse (open one section → others
  collapse) and current-page marking with no auto-expand
- Feature flag key normalisation: assembler.yml uses `NAV_V2` (underscore)
  but lookup uses `nav-v2` (hyphen); fixed by calling `featureFlags.Set`
  which normalises via `ToLowerInvariant().Replace('_', '-')`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ShortId.Create("label") always produced the same SHA256 hash, so all
8 label checkboxes shared id="v2-label-1ACA80E8". Every <label for="">
targeted the first checkbox, making only "Get Started" expandable.

Fix: include the label text in the hash — ShortId.Create("label", label).

Also updates nav-v2-status.md to reflect verified accordion behaviour.

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

Translates the team's proposed information architecture into the V2 nav:

Top-level labels:
  • Elasticsearch fundamentals (get-started + placeholder concepts)
  • Install, deploy, and administer (deploy-manage + cloud-account)
  • The Elasticsearch Platform (container for nested labels)
  • Solutions and project types (solutions)
  • Reference (elasticsearch + kibana)
  • Troubleshooting (troubleshoot)

"The Elasticsearch Platform" has three nested labels:
  • Ingest and manage data → toc: manage-data
  • Search, visualize, and analyze → toc: explore-analyze
  • AI and machine learning → title: placeholders (content lives in
    explore-analyze today; dedicated toc roots needed to wire up)

Nested labels work with no code changes — the YAML parser, SiteNavigationV2
builder, and _TocTreeNavV2 partial already recurse through children at any
depth. The Razor partial applies level-aware styling (font-semibold at
level 0, lighter weight at depth 1+).

Also documents the proposed IA mapping and content split analysis
in nav-v2-status.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Labels at any depth are now unconditionally expanded — no checkbox,
no chevron, children always visible. This applies to both top-level
labels (Elasticsearch fundamentals, The Elasticsearch Platform, etc.)
and nested labels (Ingest and manage data, Search/visualize, AI/ML).

_TocTreeNavV2.cshtml: for LabelNavigationNode, removed the peer div /
checkbox / chevron pattern; render a plain <span> heading followed by
an always-visible <ul> of children. Removed data-v2-accordion from
label <li> elements since labels no longer participate in accordion.

TOC folder nodes (INodeNavigationItem) retain their existing
checkbox-driven expand/collapse toggle unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Verified behaviours: labels always expanded (no toggle), nested
  labels same, placeholders render as disabled, TOC folders still
  toggle, accordion scoped to TOC siblings
- Mark nested label support as done
- Correct build/serve commands to dotnet run invocations
- Note LabelNavigationNode.ExpandedByDefault is now unused

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Level-1 labels (top-level sections): font-semibold text-sm text-ink — bold,
14px, full ink colour.

Level-2+ labels (sub-section dividers): text-[10px] font-semibold uppercase
tracking-widest text-ink/50 — all-caps, 10px, wide letter-spacing, 50%
opacity. This is the standard sidebar sub-group treatment (VS Code, Linear,
Notion style) and makes the hierarchy immediately legible at a glance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Level-1 label text: text-xs uppercase tracking-widest font-semibold
  text-ink — same small-caps treatment as level-2 but full ink colour,
  making them clearly structural dividers not clickable links
- Level-1 label <li>: border-t border-grey-20 pt-4 mt-4 to draw a thin
  horizontal rule between each top-level section; first: variant removes
  the border/padding from the first item

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Was text-[10px] text-ink/50 — too small and too dim to read comfortably.
Now text-xs (12px) text-ink/65 — same small-caps uppercase treatment,
clearly subordinate to level-1 but readable at a glance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 20, 2026

🔍 Preview links for changed docs

Introduces `GroupNavV2Item` — a YAML `group:` item that renders as an
expandable folder with a disabled (cursor-not-allowed) link and a chevron
toggle. Unlike `label:` (always-expanded section heading), `group:` behaves
like a regular TOC folder but with no real URL.

Changes:
- `NavigationV2File.cs`: add `GroupNavV2Item` record + `group:` YAML parsing
- `PlaceholderNavigationNode.cs`: new nav node implementing INodeNavigationItem
- `SiteNavigationV2.cs`: `CreateGroup` builder (mirrors `CreateLabel`)
- `_TocTreeNavV2.cshtml`: render PlaceholderNavigationNode as disabled folder
- `navigation-v2.yml`: replace `toc: manage-data` in "Ingest and manage data"
  with the full "Ingest or migrate: bring your data into Elasticsearch" tree
  (placeholder titles only; no toc/page refs yet)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Translates the complete card-sort JSON into navigation-v2.yml using
group:/title: placeholders throughout. All 6 top-level labels are
populated with the full proposed IA structure — no toc/page refs yet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch NavV2Deserializer from DeserializerBuilder to
  StaticDeserializerBuilder — our NavV2FileYamlConverter parses
  manually via parser events so the static context is sufficient;
  fixes IL3050/IL2055 AOT errors in the native build
- Remove unused `$` import from pages-nav-v2.ts; fixes ESLint
  @typescript-eslint/no-unused-vars error in the npm check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Set top-level tree li padding-bottom to 32px; margins for label--top and
  label--nested; first nested header under an icon title uses margin-top 12px.
- Remove hardcoded Platform subsection li classes; rely on generic markup and CSS.
- Adjust border and nested label colors to match design.
- Nav link default/hover colors (#1d2a3e, #f1f6ff); wrap label text instead of
  single-line ellipsis; clip nav for Tippy; styles for nav-v2-active-ancestor rows.
- Drop nav-v2-truncate Tippy theme rules (tooltips disabled while text wraps).
Align with elastic/docs-content#5279: move perform-index-operations
from under Index basics to a sibling group under The Elasticsearch
data store, and add new index-operations-reference.md as its child.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
theletterf and others added 2 commits April 1, 2026 13:55
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CSS: force default text colour on nav-v2-active-ancestor rows (keep font-weight); hover/grey-40 variants; scope global #pages-nav .current away from V2 sidebar links.

- JS: when several a.sidebar-link.current share the URL, use the deepest in the tree so subtree/ancestor classes attach to the correct rows.

Made-with: Cursor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
theletterf and others added 2 commits April 2, 2026 15:13
The merge from main changed the FileSystem parameter from `fs` to
`readFs`/`writeFs` (ScopedFileSystem). The nav-v2 line reading
navigation-v2.yml was not auto-resolved.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
theletterf and others added 14 commits April 7, 2026 15:42
… PRs (#2971)

Add IsAotCompatible to 12 library projects referenced by docs-builder so
Roslyn's trim/AOT analyzers (IL2026/IL3050) run during regular builds.
This catches AOT issues at compile time, removing the need for the
expensive native ILC publish step on pull requests.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* HTML: Omit version meta tags for versionless pages

Versionless pages (serverless, cloud, etc.) were rendering the sentinel
value 99999.0+ in product_version and DC.identifier meta tags. Now these
tags are omitted entirely when the page's versioning system is versionless.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* HTML: Restore required modifier on CurrentVersion property

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…3025)

* Layout: Adapt to static elastic-nav by making secondary nav sticky

The global elastic-nav.js (v2026-03) changed the header from fixed to
static positioning. This makes the secondary docs nav sticky at the top
and simplifies --offset-top to match its height.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Layout: Only make secondary nav sticky on md+ viewports

On mobile the sticky secondary nav takes too much vertical space.
Keep it static on small screens (--offset-top: 0) and only sticky
on md+ where it provides persistent navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: Upgrade lodash to 4.18.x to fix high severity vulnerabilities

Fixes code injection via _.template (GHSA-r5fr-rjxr-66jc) and
prototype pollution via _.unset/_.omit (GHSA-f23m-r3pf-42rh).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Layout: Add bottom border to secondary nav

The visual separator was coming from #main-container's border-top,
which scrolls away. Adding border-b to the nav itself keeps the
line visible while sticky.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Layout: Remove border-top from main-container

The secondary nav now has border-b, so the main-container border-t
was causing a double border.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rvice (#3023)

IncrementalDeployService accepted a single ScopedFileSystem used for both
reading and writing. The deploy commands passed RealRead which lacks
AllowedSpecialFolder.Temp, causing ScopedFileSystemException when
AwsS3SyncApplyStrategy stages files in /tmp/ for S3 upload.

Rather than just swapping RealRead for RealWrite, properly separate the
concerns: the service now accepts distinct read and write filesystems,
using each for the appropriate operations (plan file reads vs temp dir
writes). This also fixes the Plan command which was writing its output
file through a read-scoped filesystem.

Made-with: Cursor
* Add skip-labels to evaluate-pr's output

* Add tests

* Resolve conflicts

* Fix docs-builder redirect tests (#3008)

* Fix redirect tests

* Remove changelog redirects implemented elsewhere

* Search: Use default semantic_text inference, remove Jina mappings (#3014)

Elasticsearch Serverless now defaults semantic_text to Jina, making
the explicit Jina sub-fields redundant and the ELSER inference ID
unnecessary. This removes both inference ID constants, all .jina
field mappings, and lets semantic_text fields use the platform default.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: Update config/versions.yml eck 3.3.2 (#3019)

Made with ❤️️ by updatecli

Co-authored-by: elastic-observability-automation[bot] <180520183+elastic-observability-automation[bot]@users.noreply.github.com>

* Deploy: Use write-scoped filesystem for apply command (#3021)

The deploy apply command used RealRead which lacks AllowedSpecialFolder.Temp,
causing ScopedFileSystemException when AwsS3SyncApplyStrategy stages files
in /tmp/ for S3 upload. Switch to RealWrite which permits temp directory access.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Update Azure EDOT CF version (#3022)

+CC @zmoog

* Enable AOT/trim analyzers on library projects and skip AOT publish on PRs (#2971)

Add IsAotCompatible to 12 library projects referenced by docs-builder so
Roslyn's trim/AOT analyzers (IL2026/IL3050) run during regular builds.
This catches AOT issues at compile time, removing the need for the
expensive native ILC publish step on pull requests.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* HTML: Omit version meta tags for versionless pages (#3020)

* HTML: Omit version meta tags for versionless pages

Versionless pages (serverless, cloud, etc.) were rendering the sentinel
value 99999.0+ in product_version and DC.identifier meta tags. Now these
tags are omitted entirely when the page's versioning system is versionless.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* HTML: Restore required modifier on CurrentVersion property

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Layout: Adapt to static elastic-nav by making secondary nav sticky (#3025)

* Layout: Adapt to static elastic-nav by making secondary nav sticky

The global elastic-nav.js (v2026-03) changed the header from fixed to
static positioning. This makes the secondary docs nav sticky at the top
and simplifies --offset-top to match its height.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Layout: Only make secondary nav sticky on md+ viewports

On mobile the sticky secondary nav takes too much vertical space.
Keep it static on small screens (--offset-top: 0) and only sticky
on md+ where it provides persistent navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: Upgrade lodash to 4.18.x to fix high severity vulnerabilities

Fixes code injection via _.template (GHSA-r5fr-rjxr-66jc) and
prototype pollution via _.unset/_.omit (GHSA-f23m-r3pf-42rh).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Layout: Add bottom border to secondary nav

The visual separator was coming from #main-container's border-top,
which scrolls away. Adding border-b to the nav itself keeps the
line visible while sticky.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Layout: Remove border-top from main-container

The secondary nav now has border-b, so the main-container border-t
was causing a double border.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* lint

---------

Co-authored-by: Lisa Cawley <lcawley@elastic.co>
Co-authored-by: Jan Calanog <jan.calanog@elastic.co>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: elastic-observability-automation[bot] <180520183+elastic-observability-automation[bot]@users.noreply.github.com>
Co-authored-by: Fabrizio Ferri-Benedetti <fabri.ferribenedetti@elastic.co>
* feat(nav-v2): wire entire Install, deploy, and administer section

Replace ~97 placeholder title: entries with real page: cross-links
across the full "Install, deploy, and administer" label section:

- Distributed architecture: 6 pages + group index
- Plan your install: 5 pages (versioning, deployment comparison,
  reference architectures, production guidance)
- Install and deploy: 4 pages + group indices (Cloud, ECE, ECK,
  self-managed, command line tools via elasticsearch://)
- Administer your deployment: ~80 pages covering autoscaling, backup
  tools, security (24 pages), auth/users/roles, API keys, remote
  clusters, monitoring, cloud organization, licenses, maintenance,
  upgrades, and uninstall
- Deployment tools: ECCTL via toc: ecctl://reference

3 placeholder titles dropped (Skills pages and Overview roundup) as
no matching pages exist in docs-content.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(nav-v2): restore dropped placeholder titles

Re-add 3 placeholder titles that were incorrectly removed:
- Skills for installation and deployment
- Skills for cluster and deployment administration
- Overview (roundup) under Deployment and administration tools

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@theletterf
Copy link
Copy Markdown
Member Author

@shainaraskas I've incorporated the Install and deploy changes to this branch. Could you review?

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.

7 participants