@@ -67,6 +67,7 @@ export const SidebarProduct = () => {
6767 const productSection = ( ) => (
6868 < div data-testid = "product-sidebar" >
6969 < NavList aria-label = "Product sidebar" >
70+ { navListLevelSentinel ( ) }
7071 { sidebarTree &&
7172 sidebarTree . childPages . map ( ( childPage ) => (
7273 < NavListItem key = { childPage . href } childPage = { childPage } />
@@ -85,6 +86,7 @@ export const SidebarProduct = () => {
8586 return (
8687 < div >
8788 < NavList aria-label = "REST sidebar overview articles" >
89+ { navListLevelSentinel ( ) }
8890 { conceptualPages . map ( ( childPage ) => (
8991 < NavListItem key = { childPage . href } childPage = { childPage } />
9092 ) ) }
@@ -93,6 +95,7 @@ export const SidebarProduct = () => {
9395 < hr data-testid = "rest-sidebar-reference" className = "m-2" />
9496
9597 < NavList aria-label = "REST sidebar reference pages" >
98+ { navListLevelSentinel ( ) }
9699 { restPages . map ( ( category ) => (
97100 < RestNavListItem key = { category . href } category = { category } />
98101 ) ) }
@@ -135,6 +138,37 @@ function ExpandableItem({
135138 )
136139}
137140
141+ // Brand NavList picks its starting nesting level by *statically* introspecting its
142+ // direct children for a NavList.SubNav (see the `m = d ? 1 : 2` check in the brand
143+ // esm source). Our items are custom wrapper components, so brand can't see their
144+ // SubNavs, treats the list as flat, and starts numbering at level 2 — wasting one of
145+ // its 5 available levels. Docs content nests 5 levels deep, so that lost level pushes
146+ // the deepest articles over brand's cap and the depth guard flattens them (#6757).
147+ // Brand exposes no `startLevel` prop, so this hidden sentinel gives brand a real
148+ // top-level SubNav to detect, making it number from level 1 and freeing the level the
149+ // deep content needs.
150+ //
151+ // The detector accepts a NavList.SubNav nested in ANY direct child's props.children,
152+ // not only a NavList.Item — so we use a plain <li> we fully control rather than a
153+ // NavList.Item. Brand's NavList.Item forwards style/aria-hidden to its inner <button>,
154+ // NOT the outer <li>, so a NavList.Item sentinel would leave a visible, focusable 40px
155+ // container (and trip the sibling-separator styles) at the top of every sidebar. A
156+ // hidden native <li> keeps the whole sentinel — container included — out of layout and
157+ // the a11y tree. It MUST be spread inline (returned by this factory), not rendered as a
158+ // <Component/>: brand's detector never renders function components, so a wrapper would
159+ // stay invisible to it.
160+ function navListLevelSentinel ( ) {
161+ return (
162+ < li aria-hidden = "true" style = { { display : 'none' } } >
163+ < NavList . SubNav aria-label = "" >
164+ < NavList . Item as = "a" href = "#" >
165+ { '' }
166+ </ NavList . Item >
167+ </ NavList . SubNav >
168+ </ li >
169+ )
170+ }
171+
138172function LeafLink ( { node } : { node : ProductTreeNode } ) {
139173 const router = useRouter ( )
140174 const { asPath, locale } = router
@@ -151,7 +185,7 @@ function LeafLink({ node }: { node: ProductTreeNode }) {
151185 )
152186}
153187
154- function NavListItem ( { childPage, level = 2 } : { childPage : ProductTreeNode ; level ?: number } ) {
188+ function NavListItem ( { childPage, level = 1 } : { childPage : ProductTreeNode ; level ?: number } ) {
155189 const router = useRouter ( )
156190 const { asPath, locale } = router
157191 const routePath = `/${ locale } ${ asPath . split ( '?' ) [ 0 ] . split ( '#' ) [ 0 ] } `
0 commit comments