Repository navigation
Manager: Type index titles by their contents - #36659
Merged
Merged
Conversation
The manager index typed every title by its position, so an unattached MDX page got a synthetic component wrapper that the sidebar hid at render time and search, keyboard navigation and addons did not. Build untyped title nodes from the full index first, then type each node from what sits under it: other titles make a group, any story makes a component, a single docs page takes the title's place, and several docs pages make a group. Filters only prune entries, so index and filteredIndex always agree on the shape. The sidebar's render-time docs hoist and the search-layer workaround from #35495 are no longer needed and are removed. Closes #35513 Co-authored-by: Prajakta Ukirde <165979795+prajaktaukirde@users.noreply.github.com>
7 of 9 tasks
A URL such as ?path=/docs/brand-typography used to resolve through the component wrapper. Without the wrapper the id is not in the index, so the STORY_SPECIFIED handler treated it as a known leaf, pushed it back to the preview and showed "Couldn't find story matching id". Only a story or docs entry counts as the current selection now, so the manager follows the entry the preview resolved from the partial id.
4 of 9 tasks
Contributor
Package BenchmarksCommit: No significant changes detected, all good. 👏 |
The jump also stops on docs pages without a component, so the name and the menu and shortcut labels now say so. The shortcut keys keep their names so customized bindings carry over.
Sidnioulz
self-requested a review
October 19, 2026 07:57
Sidnioulz
approved these changes
Oct 19, 2026
valentinpalkovic
marked this pull request as ready for review
October 19, 2026 13:06
A component whose stories are all hidden, for example with autodocs and '!dev' on the meta, is left with only its docs entry after filtering. The sidebar showed it as one docs page before the index change; restore that render-time hoist so the documented docs-only pattern looks the same.
…x-title-types # Conflicts: # MIGRATION.md # code/core/src/manager/components/sidebar/Tree.stories.tsx # code/core/src/manager/components/sidebar/Tree.tsx
Rename the leaf check in the STORY_SPECIFIED handler to isLeaf, and use the established 'unattached docs page' term in the jumpToSubtree JSDoc.
This was referenced Oct 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #35513
Supersedes #35522
What I did
The manager index types every title by its position: the last segment of a title always becomes a
component.An unattached MDX page therefore gets a fake
componentwrapper with a singleDocschild.The sidebar hides that wrapper at render time, but search, keyboard navigation and addons see it, so in search the Typography page shows up as "Docs" under the path
brand / Typography.This rebuilds the manager hash so that each title is typed by what the full index puts under it.
The hash then matches what the sidebar renders, and filters can no longer change its shape.
The rule that decides it:
Manager hash of the internal Storybook,
nextagainst this branch, every entry dumped throughapi.resolveStoryand diffed (children lists omitted):Across 2,129 entries the only differences are 10 removed wrappers, their docs pages taking their place, and the parents'
childrenlists.Tags, import paths and every story, test and component entry are identical.
Sidebar search for "typography":
Why the type comes from the full index
#35522 hoisted wrappers after filtering, which made
filteredIndexandindexdisagree.With every story of a component filtered out,
indexstill had the component whilefilteredIndexdid not, soapi.selectStory('Button')andlinkTo('Button')silently did nothing.Captured from a unit test against that branch:
Here a component whose stories are all filtered out stays a
componentwith its docs child, and navigation works.A regression test covers this and fails when the type is computed from the filtered set.
Follow-on changes
getComponentLookupListtreats a docs entry without a component parent as its own group, so Alt+ArrowUp/Down still lands on these pages.selectStory(title)andlinkTo(title)fall back to the docs entry with that title, because no hash key equals the title anymore.API_DocsEntry.parentis optional, because a top-level MDX page has no parent.groupinstead of acomponent.?path=/docs/brand-typographyused to resolve through the wrapper. TheSTORY_SPECIFIEDhandler now follows the entry the preview resolved, so the link still opens the page instead of "Couldn't find story matching id".Breaking change for addons
useStorybookState().indexandfilteredIndexchange shape for docs-only titles, so this is listed in MIGRATION.md under 11.0.sidebar.renderLabeland sidebar filter functions receive thedocsentry instead of the wrapper and itsDocschild.api.jumpToComponentis renamed toapi.jumpToSubtree.QA walkthrough
Every step below ran in a real browser against the internal Storybook with a few extra fixtures (on the
valentin/manager-index-title-types-qabranch, one commit on top of this PR): a top-level MDX page, two MDX pages sharing a title, an MDX page sharing a title with a CSF file, and stories that calllinkTo.The recording is the Playwright run of the same steps; each step asserts its result, so the video only exists because every step passed.
The top-right banner says what is being tested, the bottom-right badge shows the key combination a user presses, and the bottom caption shows the result.
qa-36659.mp4
Checklist from #35513
Core change
Keyboard navigation
jumpToComponenttojumpToSubtree. The shortcut keysprevComponent/nextComponentkeep their names so customized bindings carry over.getComponentLookupListtreats a docs page without a component parent as its own group.findSiblingStoryIdinstead. Not needed, the item above covers it.["guides-faq--setup","welcome--docs"].Previous component or page/Next component or page.Navigation and API
selectStory/linkToby title:linkTo('Welcome'),linkTo('Guides/Intro'),linkTo('Guides/FAQ')(first page of the group).linkTo('Guides/Intro', 'Docs'),selectStory('Guides/Button', 'Primary'),selectStory('Guides/FAQ', 'Usage'); an unknown title still throws.findLeafEntrycall sites:selectStory('Guides/Button')opens its docs page while every story is filtered out.importPath: set on components and on each hoisted page; "Open in editor" is offered on docs pages.Consumers
?path=/docs/guides-introand?path=/docs/welcomewere broken by the change and are fixed here, with an e2e test.sidebar.renderLabel/renderAriaLabelreceive the docs entry (docs Welcome); documented in MIGRATION.md.nexteither; that is fixed separately in Manager: Fix ArrowLeft and ArrowRight not collapsing sidebar nodes #36660.index.json: unchanged (pages still namedDocs, no wrappers).Edge cases
group(Guides/FAQ).component(Guides/Button with Notes).--docs): a title left with one page collapses into it; FAQ stays a group.linkTo(title, 'Docs')still resolves.Tests
stories.test.ts/refs.test.tsupdated.Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
yarn storybook:uifrom thecode/directory.typographyin the sidebar search. Check that the first result is "Typography" with the path "brand", not "Docs".Monospace. Check that the heading result reads "Typography / Monospace".Documentation
Checklist for Maintainers
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes.qa:neededorqa:skipfeature request,bug,maintenance, etc.).🤖 Generated with Claude Code