Skip to content

Commit ef333f8

Browse files
theletterfclaude
andcommitted
fix(nav-v2): compact left-aligned top bar, section root highlight, auto-expand
- Wrap all V2 content in a single "Docs" section; add Release notes, Troubleshoot, Reference as separate section tabs - Secondary nav: left-aligned, 55px height, restored md:text-base font - Skip current-page highlighting on section root pages via data-section-url attribute (includes site prefix) - Auto-expand top-level folders on section root pages so content is visible without a specific page being marked current Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3a46434 commit ef333f8

5 files changed

Lines changed: 51 additions & 5 deletions

File tree

src/Elastic.Documentation.Site/Assets/pages-nav-v2.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ function normalizeDocPathname(pathname: string) {
5151
return p === '' ? '/' : p
5252
}
5353

54+
/**
55+
* Returns true when the current page is the section root URL.
56+
* Section root pages should not get current-page highlighting in the sidebar
57+
* because the section URL is a tab target, not a page within the nav tree.
58+
*/
59+
function isOnSectionRootPage(nav: HTMLElement): boolean {
60+
const sectionUrl = nav.dataset.sectionUrl
61+
if (!sectionUrl) {
62+
return false
63+
}
64+
65+
return (
66+
normalizeDocPathname(window.location.pathname) ===
67+
normalizeDocPathname(sectionUrl)
68+
)
69+
}
70+
5471
/** Matches {@link markCurrentPage} / {@link expandToCurrentPage} href selectors (not root-normalized). */
5572
function stripTrailingSlashForNavHref(pathname: string) {
5673
return pathname.replace(/\/$/, '')
@@ -318,6 +335,9 @@ function deepestCurrentSidebarLink(nav: HTMLElement): HTMLAnchorElement | null {
318335
*/
319336
function applyActiveSubtreeHighlight(nav: HTMLElement) {
320337
clearActiveSubtreeHighlight(nav)
338+
if (isOnSectionRootPage(nav)) {
339+
return
340+
}
321341
const current = deepestCurrentSidebarLink(nav)
322342
if (!current || !nav.contains(current)) {
323343
return
@@ -377,8 +397,13 @@ function markCurrentPageForPath(nav: HTMLElement, pathnameRaw: string) {
377397

378398
/**
379399
* Mark the current page's nav link with the "current" CSS class.
400+
* Skips marking when the current page is the section root URL.
380401
*/
381402
function markCurrentPage(nav: HTMLElement) {
403+
if (isOnSectionRootPage(nav)) {
404+
$$('.current', nav).forEach((el) => el.classList.remove('current'))
405+
return
406+
}
382407
markCurrentPageForPath(nav, window.location.pathname)
383408
}
384409

@@ -461,6 +486,16 @@ function expandToCurrentPageForPath(nav: HTMLElement, pathnameRaw: string) {
461486
* is the current page (see session storage + folder row link match).
462487
*/
463488
function expandToCurrentPage(nav: HTMLElement) {
489+
if (isOnSectionRootPage(nav)) {
490+
// On the section root page, expand all top-level folders so the
491+
// section content is visible even though no specific page is current.
492+
nav.querySelectorAll<HTMLInputElement>(
493+
'#nav-tree > li > .peer > input[type="checkbox"]'
494+
).forEach((cb) => {
495+
cb.checked = true
496+
})
497+
return
498+
}
464499
expandToCurrentPageForPath(nav, window.location.pathname)
465500
}
466501

src/Elastic.Documentation.Site/Layout/_SecondaryNav.cshtml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
<ask-ai></ask-ai>
55
<nav id="secondary-nav" hx-select-oob="#main-container" hx-swap="none"
66
class="bg-grey-10 border-b border-grey-20">
7-
<div class="w-full max-w-(--max-layout-width) mx-auto px-4 py-2">
7+
<div class="w-full max-w-(--max-layout-width) mx-auto px-4 h-[55px] flex items-center">
88
@if (Model.NavV2Sections is { Count: > 0 } navTabs)
99
{
10-
<ul class="flex gap-5 font-sans font-semibold text-sm text-ink-light">
10+
<ul class="flex gap-6 font-sans font-semibold text-sm text-ink-light md:text-base">
1111
@foreach (var navTab in navTabs.Where(s => !s.Isolated))
1212
{
1313
var isActive = navTab.Id == Model.ActiveSectionId;
@@ -27,7 +27,7 @@
2727
}
2828
else
2929
{
30-
<ul class="flex gap-5 font-sans font-semibold text-sm text-ink-light">
30+
<ul class="flex gap-6 font-sans font-semibold text-sm text-ink-light md:text-base">
3131
<li class="text-nowrap text-blue-elastic">
3232
<a href="@Model.Link("/")">Docs</a>
3333
</li>

src/Elastic.Documentation.Site/Navigation/NavigationViewModel.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,7 @@ public class NavigationViewModel
2929

3030
/// <summary>When true, the sidebar renders a back arrow instead of appearing in the top bar.</summary>
3131
public bool IsIsolatedSection { get; init; }
32+
33+
/// <summary>The section's own URL, used by JS to skip current-page highlighting on the section root.</summary>
34+
public string? SectionUrl { get; init; }
3235
}

src/Elastic.Documentation.Site/Navigation/_TocTree.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
</a>
8484
}
8585
@* Root for V2-only CSS; JS still uses [data-nav-v2]. Scope overrides: .docs-sidebar-nav-v2 … *@
86-
<nav class="docs-sidebar-nav-v2" data-nav-v2>
86+
<nav class="docs-sidebar-nav-v2" data-nav-v2 @if (Model.SectionUrl is not null) { <text>data-section-url="@Model.SectionUrl"</text> }>
8787
<ul class="docs-sidebar-nav-v2__tree block" id="nav-tree">
8888
@await RenderPartialAsync(_TocTreeNavV2.Create(new NavigationTreeItem
8989
{

src/services/Elastic.Documentation.Assembler/Navigation/GlobalNavigationHtmlWriter.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ Cancel ctx
105105
Htmx = new DefaultHtmxAttributeProvider("/"),
106106
BuildType = BuildType.Assembler,
107107
IsNavV2 = true,
108-
IsIsolatedSection = section.Isolated
108+
IsIsolatedSection = section.Isolated,
109+
SectionUrl = CombineWithSitePrefix(navV2, section.Url)
109110
};
110111

111112
var html = await ((INavigationHtmlWriter)this).Render(model, ctx);
@@ -118,6 +119,13 @@ Cancel ctx
118119
}
119120
}
120121

122+
private static string CombineWithSitePrefix(SiteNavigation nav, string sectionUrl)
123+
{
124+
var prefix = nav.Url.TrimEnd('/');
125+
var path = sectionUrl.TrimStart('/');
126+
return string.IsNullOrEmpty(path) ? $"{prefix}/" : $"{prefix}/{path}";
127+
}
128+
121129
private static NavigationRenderResult CreateSectionResult(string html, NavigationSection activeSection, SiteNavigationV2 navV2) =>
122130
new()
123131
{

0 commit comments

Comments
 (0)