feat(sidebar): flatten the top-level nav heading
Merged
MH
3mo ago+180+180+012345678901234567890123456789-19-19-01234567890123456789
Closes #65
Summary
The sidebar rendered its top-level heading as a collapsible <details> wrapping every subgroup, so a one-registry site (every current consuming site) got a redundant chevroned "DOCUMENTATION" level and one extra indent on the whole nav.
Now subgroups are the top level of the menu:
- One non-empty heading → the heading is not rendered at all; "Getting started", "REST API", … sit directly in the menu.
- Several headings → each renders as a static daisyUI
menu-titlelabel withmt-4 first:mt-0breathing room — no fold; only subgroups collapse. - Landing doc index gets the same rule: the per-group
h3is skipped when there is exactly one heading, fixing the stacked "DOCUMENTATION / DOCUMENTATION" duplicate under the hero.
Intentionally unconditional (settled in the plan interview): no config knob — all consuming sites get the flattened chrome on upgrade.
What did NOT change
nav_groupskeeps its{ "Heading" => { "Subgroup" => [NavItem] } }shape — explicitc.navlambdas work verbatim.- No JS change: docs-nav keys collapse persistence by summary text, so the removed top-level
<details>just orphans one harmless localStorage key. - No CSS-contract change:
menu-titlewas already@source inline'd in the generated stylesheet, and the new utilities are literals in gem Ruby scanned by thebin/build-cssglobs.
Test Coverage
spec/docs_ui/sidebar_spec.rb— single heading dropped; subgroups render as top-level<details open>; multiple headings render asmenu-title<li>s (never<summary>s) with the spacing classes; empty headings excluded from the count; every<details>staysopen(JS-off regression guard).spec/docs_ui/landing_spec.rb(new) — single heading: "Documentation" appears once, noh3; multiple headings: bothh3labels render.
Verification
-
bundle exec rspec— 806 examples, 0 failures (94.0% line coverage) -
bundle exec rubocop— no offenses - CSS contract checked by inspection — no new
@sourceneeded
Deviations & judgment calls
- Sidebar single-heading count: an explicit
c.navlambda can contain empty headings (e.g.{ "Docs" => {…}, "Empty" => {} }), which the registry-derived path never produces. Empty headings are excluded from the count, so one real + one empty heading still gets the single-heading rule (heading dropped). Covered by a spec. - Landing spacing: when the per-group
h3is skipped, the columnulalso drops itsmt-3top margin — otherwise the links float an extra 12px below theh2for no reason. Both class lists stay fully literal for the Tailwind scanner. - Discovery: the plan's prediction held —
menu-titleand all utilities were already covered by the generated CSS contract, so no generator/template change was needed.