Skip to content

feat: preview toolbar, Tabs, and static-host fixes (0.1.9-alpha) - #28

Merged
Shewart merged 18 commits into
mainfrom
feat/preview-toolbar
Oct 2, 2026
Merged

Shewart merged 18 commits into
mainfrom
feat/preview-toolbar

Conversation

@Shewart

@Shewart Shewart commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Summary

0.1.9-alpha. It adds a Preview | Code toolbar to every example and a general-purpose <Tabs> component. It also fixes problems found while building the ShellUI docs on 0.1.8: name collisions, code spans, hydration, the mobile nav, Shiki and CodeGroup on static hosts. The docs are brought in line with the code.

Added

  • Preview | Code toolbar on every razor:preview and <DemoPreview>: segmented Preview / Code tabs, a copy button, and a ⋯ menu with Open in new tab, Report a bug and Suggest something.
    • The issue links go to https://github.com/{GitHubRepo}/issues/new, pre-filled with the example and the page URL. Point them elsewhere with ShellDocsOptions.IssueTrackerUrl.
  • <Tabs> / <Tab> content primitive.
    • Server-rendered panels switched by shelldocs.js, so they work on static hosts.
    • DefaultValue (by Label or Value).
    • SyncKey groups that switch together and remember the choice in localStorage across pages.
    • WAI-ARIA keyboard support: arrows, Home, End.
  • DocsHeader.MobileMenu: the primary nav as a mobile menu, for pages without a sidebar (HomeLayout turns it on).

Changed

  • Your components win name collisions. When a registered component library has a Card, Callout, Tabs and so on, its version is used. ShellDocs' built-ins stay available as <DocsCard>, <DocsCallout>, <DocsTabs>, and each collision is logged at startup.
  • shelldocs init scaffolds packages at the CLI's own version instead of a hard-coded one.
  • Docs corrected to match the code:
    • README and ARCHITECTURE rewritten to describe what's built. The README marks --base-href, --spa-fallback and --site-url as opt-in build flags.
    • ROADMAP marks what shipped; DESIGN and TOKENS get status notes.
    • RELEASING describes the workflow's check that stops a release whose version is already on nuget.org, and what a dry run skips.
    • Package descriptions list the real CLI commands (init, add, dev, build).
    • Every component page on the example site matches its component and has live previews. Fixes include the Tabs, CodeBlock, TypeTable, ComponentPreview, Callout, Card and FileTree pages.

Fixed

  • "View Code" sometimes didn't expand. Clicks before the Blazor circuit started were dropped, and the circuit then replaced the DOM. Handlers now attach immediately, and the selected tab is restored after the swap.
  • Inline code rendered as components. `<Button>` in prose now stays literal code. Component child content is unmasked correctly.
  • <CodeGroup> didn't switch on static hosts. It used @onclick state. It now uses the same shelldocs.js contract as <Tabs>, and synced choices persist in localStorage.
  • Highlighted code threw replaceChild errors or went stale. Shiki replaced Blazor-owned <pre> nodes. Its output now renders in a JS-owned sibling and the source is hidden.
  • Mobile menu:
    • The hamburger did nothing on the home page.
    • Page text showed through above the open drawer.
    • The header now stays pinned and the page scroll is locked while the drawer is open.
  • Version folders showed in the sidebar outside a version (v1.9.1, v2.0 as expandable folders). They're left to the version selector now.
  • Home feature icons were barely visible in the example site.

Notes

  • Everything listed above works on static hosts. Search, the theme-toggle button, desktop sidebar collapse and stateful demos still need a running Blazor app; this is documented in the README.
  • CodeGroupSyncState is still registered so existing Program.cs files compile, but nothing uses it now.

Testing

  • dotnet build: 0 warnings, 0 errors. dotnet test: 266 passing.
  • New tests: PreviewToolbarTests, TabsRenderTests, MobileNavMarkupTests, TypeRegistryCollisionTests, CodeSpanMaskingTests, ScaffoldVersionTests; versioning tests extended.
  • Checked by hand in the example app:
    • Toolbar and ⋯ menu.
    • Tabs and CodeGroup switching, sync, keyboard, and persistence across reloads.
    • Mobile drawer at 390px.
    • Every component page renders its previews with no preview errors.
    • A client-side crawl of every page with no replaceChild or console errors.

Shewart added 18 commits October 2, 2026 14:33
- PreviewFrame gets a header toolbar: Preview | Code tabs (WAI-ARIA, arrow/Home/End keys), a copy button and a ⋯ menu with "Open in new tab", "Report a bug" and "Suggest something". Replaces the "View Code" fade overlay.
- Issue links are pre-filled with the example name and page URL; ShellDocsOptions.IssueTrackerUrl overrides the GitHubRepo default, and the items hide when neither is set.
- Stable example anchors: preview-N (page order), demo-{component}, example-{component}-{hash}; DemoPreview takes an optional Id.
- ComponentPreview renders through PreviewFrame; its own markup and CSS are removed.
- Static-host friendly: both panels are server-rendered, shelldocs.js switches tabs via [data-preview-tab] and opens the menu through the shared dropdown contract.
…er the circuit swaps the DOM

- shelldocs.js attached its delegated click handlers on DOMContentLoaded, which waits for module scripts such as the Shiki import, so early clicks on prerendered chrome ("View Code", tabs) were dropped. Handlers now attach as soon as the script runs.
- Interactive render replaces the prerendered DOM when the Blazor circuit starts, resetting a tab picked before then. The selected tab is remembered per page + frame id and re-applied to the replacement nodes.
…ild content

- Mask CommonMark code spans (any backtick run length, may wrap lines, never crosses a blank line) before scanning for component tags, so `<Button>` in prose stays code instead of becoming a component.
- Fences and code spans inside a component's child markup or attribute values are restored before that markup renders, instead of leaking SHELLDOCS_MASK_ tokens.
…p Docs aliases

- Built-in primitives were registered after consumer components, so ShellDocs' Card, Callout, Steps, … silently replaced a consumer library's component of the same name (e.g. ShellUI's Card). Built-ins now register first, so consumer registrations win.
- Every built-in is also registered as Docs{Name} (<DocsCard>, <DocsCallout>, …) so it stays reachable when shadowed.
- TypeRegistry.Collisions records re-pointed tags (TypeCollision); AddShellDocs logs them at startup — information for an overridden built-in, a warning for two consumer components.
- shelldocs init pinned scaffolded projects to a hard-coded ShellDocsVersion that had been stuck at 0.1.2-alpha. It now reads the CLI assembly's informational version (SourceLink "+sha" suffix stripped), which always matches the packages released alongside it.
- RELEASING.md: Directory.Build.props is the only version to bump.
…ithout a sidebar

- The hamburger flipped MobileNavState via @OnClick, so it was dead on static hosts, and on HomeLayout (no sidebar drawer) it only swapped its icon. Hamburgers now carry data-mobile-nav-toggle; shelldocs.js toggles [data-mobile-open] on the page shell and CSS slides in the docs sidebar or shows the home menu.
- DocsHeader.MobileMenu renders the primary nav (menu groups flattened) as a mobile menu; HomeLayout turns it on.
- The backdrop, Escape, picking a link, or an enhanced navigation closes it; the open state survives the circuit's DOM swap.
- MobileNavState stays registered but is no longer used by the built-in chrome.
The tiles used the --accent surface token (translucent grey) as the icon colour and the undefined --accent-soft as background; use --foreground on --muted.
…of replacing it

- highlightOne swapped the source <pre> for Shiki's output with replaceChild. Blazor still owned the original, so it kept updating a detached node: after client-side navigation the Code tab showed the previous page's source, and a <pre> already removed made the swap throw.
- The source <pre> now stays in place, marked [data-shiki="source"] and hidden by CSS; Shiki renders into a JS-owned [data-shiki-output] sibling, re-rendered when the source text changes and removed when its source is gone.
- A MutationObserver re-runs the pass (batched per frame) when Blazor edits or adds code.
- The scroll lock set overflow: hidden on the page shell, which made the shell the sticky mobile bar's scroll container: after scrolling, opening the drawer slid the bar out of view and the page showed through the strip above the drawer.
- Lock scrolling on <html> instead (mobile breakpoint only), so the viewport stays the sticky container.
- The mobile bar is exactly --header-height tall, matching where the drawer and backdrop start.
…sion

- On unversioned pages the sidebar fell back to the whole content tree, listing every version folder as a collapsible section next to the version selector that already covers that navigation.
- DocsVersionResolver.IsHiddenInSidebar hides version folders, and sections holding nothing but version folders; DocsSidebar and DocsSidebarNode skip them.
CodeGroup switched tabs through @OnClick state, so on a static build the strip did nothing. It now renders every panel server-side and uses the data-tabs contract in shelldocs.js: click and arrow/Home/End keys, SyncKey groups that switch together, and the choice saved in localStorage across pages.
General-purpose tabs for any content, on the same static-host contract as CodeGroup. Supports DefaultValue (by Label or Value), SyncKey groups and WAI-ARIA tab semantics. Available as DocsTabs/DocsTab when a consumer library shadows the names.
README and ARCHITECTURE rewritten to describe what's built; ROADMAP marks what shipped; DESIGN and TOKENS get status corrections; package descriptions list the real CLI commands and primitives. Example pages for Tabs, CodeBlock, TypeTable, ComponentPreview, Installation, Theming and Markdown syntax are corrected and get live previews.
…/shelldocs into feat/preview-toolbar

# Conflicts:
#	CHANGELOG.md
RELEASING describes the version check the release workflow runs before pushing. README lists --base-href, --spa-fallback and --site-url as the opt-in flags they are. Callout, Card and FileTree pages match the components: no false init warning, the variant aliases, a child-content preview, Card's IconSvg/External props and CardGrid's real column options.
@Shewart
Shewart merged commit 91255b8 into main Oct 2, 2026
1 check passed
@Shewart
Shewart deleted the feat/preview-toolbar branch October 2, 2026 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant