Skip to content

Desktop nav dropdowns (Product, Resources) are unreachable by keyboard #1

Description

@boluwacodes

Where: src/components/layout/navbar.tsx, desktop nav block (the <nav className="hidden items-stretch lg:flex" ...> element, roughly lines 120–161).

What: The "Product" and "Resources" items in the primary nav render as a <button type="button"> inside a wrapper <div onMouseEnter={() => setOpenMenu(item.label)}>. The submenu (with links like Features, Pricing, "How it works", Documentation, Developers, Blog) is opened purely by onMouseEnter on that wrapper div and closed by onMouseLeave on the parent <nav>. The trigger <button> itself has:

  • no onClick handler
  • no onFocus handler
  • no onKeyDown handler
  • no aria-expanded / aria-haspopup attributes
<button
  type="button"
  className={cn(
    'flex items-center border-l border-border px-4 text-sm font-medium uppercase tracking-wide text-foreground/80 transition-colors hover:bg-secondary hover:text-foreground',
    openMenu === item.label && 'bg-secondary text-foreground',
  )}
>
  {item.label}
</button>

Why it's a problem: A keyboard-only user (or a screen-reader user tabbing through the page) who reaches the "Product" or "Resources" button has no way to open the dropdown — pressing Enter/Space does nothing because there's no onClick, and there is no way to trigger a hover state without a pointer. This makes every link inside those two dropdowns (Features, "How it works", Pricing, Documentation, Developers, Blog) completely unreachable from the primary navigation via keyboard — Tab just skips from "Product" straight to "Resources"/"About"/"Contact". Those pages are still reachable via the footer, but the primary nav — the thing sighted mouse users actually use — is a dead end for keyboard navigation.

This also directly contradicts this repo's own documentation. README.md, under "Accessibility and performance", states:

Interactive pieces like the FAQ accordion and the navigation menu are built on accessible primitives with correct keyboard navigation.

The FAQ accordion (built on Radix UI's Accordion primitive, see src/components/ui/accordion.tsx) is fine — but the nav menu is a bespoke implementation with none of the keyboard affordances Radix would have given it.

Repro:

  1. Load any page at desktop width (≥1024px, the lg breakpoint).
  2. Click into the page, then press Tab repeatedly until focus reaches the "Product" button in the header.
  3. Press Enter or Space.
  4. Nothing happens — the dropdown never opens, and the links inside it are never reachable by keyboard.

Suggested fix direction: give the trigger <button> an onClick that toggles openMenu, an onFocus that opens it, aria-expanded={openMenu === item.label} and aria-haspopup="true", plus a way to close on blur/Escape (e.g. an onBlur on the wrapping div that checks e.relatedTarget isn't still inside it).

Labels: bug, accessibility

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    accessibilityBarrier affecting people with disabilitiesbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions