feat(shell): two homes — masthead follows brand_href, opt-in app_link topbar link
Merged
MH
3mo ago+189+189+012345678901234567890123456789-5-5-0123456789
Closes #62
Summary
DocsUI::Page's masthead "← Home" link hardcoded the host app's root_path route helper — the gem's only call site for it. On a docs site embedded in a bigger application, root_path resolves to the application root (often an authenticated dashboard, not the docs landing), so readers clicking Home were bounced off the docs entirely, and a site's only recourse was overriding the route helper in its own view layer.
This PR gives the chrome two config-driven homes:
- Docs home — the masthead link now follows the existing
config.brand_href(default"/"), the same knob the topbar and sidebar brand links already use, and is relabeled "← Docs home". A site that already setsc.brand_href = "/docs"gets the fix on upgrade with zero config change. - App home — a new opt-in
c.app_link = { href:, label: }(defaultnil→ nothing renders). When set, the topbar renders a labeled link back to the hosting app once, right after the brand. Normalized through the existingDocsKit::TopbarLinkvalue object (symbol- or string-keyed Hash, or aTopbarLink); external hrefs open in a new tab withrel=noopener, mirroringDocsUI::TopbarLinks.
Wired into the install path: the generated initializer documents the commented c.app_link example (docs-kit new runs the same generator). README documents both homes.
Backwards compatibility
app_linkunset → the topbar markup is byte-identical to before.brand_hrefdefault"/"→ the masthead points exactly whereroot_pathresolved on standalone sites; only the label changes ("← Home" → "← Docs home"), deliberately.- Only literal, already-emitted daisyUI class strings — no CSS rebuild or
@sourcechange needed. Phlex::Rails::Helpers::Routesstays included inPage— consuming sites call route helpers in#content.- Sites that worked around this by overriding
root_pathin their view layer can delete the override and, if they want the way back, setc.app_link.
Test plan
spec/docs_kit/configuration_spec.rb—app_linkdefaults to nil; Hash (symbol/string keys) normalizes toDocsKit::TopbarLink; an existingTopbarLinkpasses through.spec/docs_ui/shell_spec.rb— unset → no App Home link; set → labeled anchor after the brand anchor; external href →target="_blank"+noopener; relative href → neither.spec/docs_ui/page_spec.rb—#home_hrefdefaults to"/"and followsc.brand_href(child-process harness;Pagecan't load in the Rails-free suite).spec/generators/install_generator_spec.rb— the generated initializer contains the commented# c.app_link =example.bundle exec rspec: 795 examples, 0 failures, 94.87% line coverage.bundle exec rubocop: clean.
Deviations & judgment calls
- Judgment call:
bundle exec rubocopflaggedMetrics/ClassLengthonapp/components/docs_ui/shell.rb(105/100) after adding the ~10-line#app_home_linkmethod — Shell was already at the limit. Exemptedshell.rbin.rubocop.ymlalongsidelanding.rb, whose documented rationale (composite renderer of several sections, each a small focused method) applies verbatim. Alternatives rejected: compressing the method to dodge the metric (hurts readability), extracting a one-link component (over-engineering).