feat: auto-render TOC / PrevNext / Breadcrumb from a shared DocsPageState - #16
Merged
Conversation
…nd section content
…and navigation behavior
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.
Summary
Kills the per-page wiring ceremony consumers were paying to render TOC, PrevNext, and Breadcrumb chrome.
DocsLayoutnow auto-renders all three from a sharedDocsPageStatescoped service thatMarkdownContentpublishes into. New primitive:<DocsBreadcrumb />. Preview app'sDocsPage.razorcollapses from ~15 lines of explicit chrome wiring to a single<MarkdownContent Document="_document" />.The old ceremony
Before this branch, every consumer's
DocsPage.razorhad to:That's boilerplate for a docs framework to force on every consumer. And plain
.mdfiles with no accompanyingDocsPagewiring got no chrome at all. And there was noDocsBreadcrumbprimitive.The new shape
DocsPage.razor(existing consumers migrate to this; new scaffolds get it out of the box via the updated CLI template):That's it. TOC, PrevNext, Breadcrumb all render automatically from
DocsLayout.How it works
New scoped service
DocsPageStateMarkdownContentcallsPageState.SetDocument(doc)inOnParametersSet— so anything that renders a docs page publishes its document into the shared state.NavigationManager.LocationChangedand recomputesCurrentNode/Prev/Next/Breadcrumbsfrom the injectedNavigationGraph— so route changes propagate without waiting forMarkdownContentto re-render.OnChangeon every recompute so subscribers (TOC, PrevNext, Breadcrumb) re-render.IDisposableunsubscribes on scope teardown.Chrome components read from state when params are omitted
TableOfContents—Headingsparam is now optional; falls back toPageState.Document?.Headings. Subscribes toOnChangefor route transitions.PrevNextNav—Prev/Nextparams optional; fall back toPageState.Prev/PageState.Next. Same subscription.DocsBreadcrumb(new) — readsPageState.Breadcrumbs. Section nodes render as<span class="docs-breadcrumb-section">(no URL, not clickable — sections aren't pages); current page as<span aria-current="page">; only leaf pages become<a>links. Hides entirely when the trail has ≤ 1 nodes.DocsLayoutauto-mounts all threeRemoved the
<SectionOutlet SectionName="docs-toc" />slot indirection — the TOC now renders as<TableOfContents />directly. Added<DocsBreadcrumb />above@Bodyand<PrevNextNav />below@Bodyinside.docs-content.Scaffold template updated
ScaffoldTemplates.DocsPageRazor(emitted byshelldocs init) now mirrors the collapsed shape. Newly-scaffolded consumers get auto-chrome from t=0.Backward compat
DocsPage.razorstill explicitly wires<PrevNextNav Prev="_prev" Next="_next" />continue to work — the explicit-param path is preserved.Prev/Nextparams override state.DocsPage.razorstill does<SectionContent SectionName="docs-toc">will no longer render — theSectionOutletis gone, so orphanSectionContentfires into the void. Recommended migration: delete the explicit wiring.ShellDocsOptionsor the primitives themselves.Test plan
dotnet build shelldocs.slnx— clean, 0 warnings, 0 errorsdotnet test shelldocs.slnx— 129 / 129 passing (+3 new inDocsPageStateTests)/docs/components/callout→ breadcrumb reads "Docs > Components > Callout" (sections as text, current bold), TOC populated on right rail, prev/next cards below content/docs/introduction→ prev placeholder (first page in nav order), next card, TOC, breadcrumb "Docs > Introduction"New tests (
DocsPageStateTests)SetDocumentfiresOnChangeand stores the documentCurrentNode, nullPrev/Next, emptyBreadcrumbsDispose()unsubscribes cleanlyFiles touched
src/ShellDocs.Components/DocsPageState.cs(new)src/ShellDocs.Components/Chrome/DocsBreadcrumb.razor(new) +.razor.css(new)src/ShellDocs.Components/ServiceCollectionExtensions.cs—AddScoped<DocsPageState>()src/ShellDocs.Components/Content/MarkdownContent.razor— publishes to statesrc/ShellDocs.Components/Chrome/TableOfContents.razor— state fallback + subscriptionsrc/ShellDocs.Components/Chrome/PrevNextNav.razor— state fallback + subscriptionsrc/ShellDocs.Components/Layouts/DocsLayout.razor— auto-renders all three, drops SectionOutletsrc/ShellDocs.Templates/ScaffoldTemplates.cs—DocsPageRazortemplate collapsed to matchexamples/ShellDocs.Preview/Components/Pages/DocsPage.razor— proof-of-shape: collapsed to<MarkdownContent />tests/ShellDocs.Tests/DocsPageStateTests.cs(new, 3 tests)