Skip to content

feat(nav): collapse 11 flat links into 4 hover/focus dropdown groups - #133

Merged
eaitbrahim merged 1 commit into
mainfrom
feat/nav-submenus
Aug 29, 2026
Merged

feat(nav): collapse 11 flat links into 4 hover/focus dropdown groups#133
eaitbrahim merged 1 commit into
mainfrom
feat/nav-submenus

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

Closes #131

What

  • Desktop nav: 4 groups, one row. The eleven flat links became four top-level groups — Product (features, install, assistant, roadmap), Docs (docs, changelog), Community (news, community), Company (compliance, about) — each opening a dropdown on hover/focus-within. This is the language switcher's .locale-menu pattern lifted verbatim: the .nav-group wrapper owns hover/focus-within, the panel is always in the DOM and only opacity-gated, so its links keep their tab stops whether or not it is showing. Zero JS for open/close.
  • Escape. The one dismissal gesture CSS cannot see. A single delegated keydown listener (the theme toggle's script pattern) blurs the focused item so :focus-within lets go and the panel folds.
  • Compare retired from the nav. The page stays live at /compare/ (sitemap unchanged, page still built ×3 locales) — it just has no inbound nav link anymore, per the issue.
  • Mobile unchanged in mechanics. The checkbox hamburger keeps its toggle; the panel now lists all ten items under uppercase group headings (the trigger degrades to a non-interactive label there).

Decisions worth reviewing

  • aria-haspopup="true" on triggers, no aria-expanded — it could only ever track half the truth (hover opens the panel without any event a script could hear), and the submenu links are never removed from the accessibility tree, so nothing is hidden from SR users either way.
  • Triggers are real <button>s: clicking one focuses it, which opens the panel via focus-within — so the control is honest on desktop. In the mobile panel they stay in the tab order as heading-like stops (CSS cannot remove an element from the tab order); all links remain fully reachable.
  • nav.compare strings deleted from src/i18n/ui.ts ×3; grep confirms zero remaining consumers. Compare page prose in src/i18n/pages/compare.ts is untouched.
  • Group labels added to ui.ts in the same register as the existing nav strings: Product/Produit/المنتج, Docs/Docs/الوثائق, Community/Communauté/المجتمع, Company/Entreprise/الشركة.

Verification

  • npx astro check (cache cleared first): 0 errors, 0 warnings (4 pre-existing hints in unrelated files).
  • npm run build: 70 pages, compare built in en/ar/fr, sitemap still lists /en/compare/.
  • puppeteer-core against astro preview23/23 checks passed:
    • /fr/ @1280 and @1024: nav is ONE line (site-nav h=36px = single trigger row, all 4 trigger tops identical); also confirmed @1024 for /en/ (36px) and /ar/ (39px, RTL).
    • Hover opens the Product submenu (opacity 0→1 after 300ms); pointer-out closes it.
    • Keyboard: focusing the Docs trigger opens its panel; Tab lands on the first submenu link (Documentation/fr/docs/); Escape returns focus to body and the panel folds to opacity 0.
    • 390px ×3 locales: hamburger panel displays, 4 group headings rendered in the right language, all 10 links present and zero /compare hrefs, scrollWidth == clientWidth with the panel both closed and open.
    • /en/compare/ → 200.

The flat nav wrapped to two lines at desktop widths. Four top-level
groups now own dropdown submenus (Product, Docs, Community, Company)
built on the language switcher's pattern: the .nav-group wrapper owns
hover/focus-within, the panel is opacity-gated so its links keep their
tab stops, and a single delegated Escape listener (the theme toggle's
script pattern) covers the one dismissal gesture CSS cannot see.

Compare leaves the nav per #131 — the page stays live at /compare/ for
organic traffic; nothing else in the chrome links to it. The hamburger
panel below the md breakpoint keeps its mechanics and lists all ten
items under their group headings.

Closes #131
@sonarqubecloud

Copy link
Copy Markdown

@eaitbrahim
eaitbrahim merged commit 69dd967 into main Aug 29, 2026
2 checks passed
@eaitbrahim
eaitbrahim deleted the feat/nav-submenus branch August 29, 2026 06:30
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.

Header: 11 items wrap to two lines — reorganize into menu + submenus; retire Compare from nav

1 participant