Prepared Docs

Prepared Docs

⌘K

    Loading navigation…

User

  1. Components
  2. Navbar
  3. Accessibility

Navbar

Accessibility

Navbar from @prepared911/ui-core provides a named application navigation landmark and composes link-based destinations with menu-based overflow and app switching. The component handles landmark, measurement, and menu primitives; your job is to supply meaningful localized names, accurate route state, and accessible custom content.

What the component handles

  • Navigation landmark. The root exposes role="navigation" with the required ariaLabel. Nested TabNav roots used for destinations and overflow measurement are not additional landmarks.
  • Link semantics. Primary destinations use TabNavItem, preserving native link focus, activation, modifier-click, and current-route semantics.
  • Responsive measurement. The duplicate measurement row is aria-hidden, so assistive technology encounters only the interactive destinations.
  • Overflow access. Hidden destinations move into a keyboard-operable labeled More menu instead of disappearing. The menu opens on click by default. Hover-open is opt-in.
  • Logo semantics. A logo brand with ariaLabel exposes role="img" and the supplied accessible name.
  • App selection. Multi-app destinations use radio-menu semantics, including the current checked item.
  • Label in name. The app-switcher trigger combines the visible current app name with appMenuLabel. Account triggers composed in NavbarEnd must include the visible account name in their accessible name.

What you must provide

  • A landmark name. Set Navbar ariaLabel to the product or navigation region, such as "Dispatch" or "Supervisor Hub." If a page has multiple navigation landmarks, give each a distinct name.
  • A logo name. Set NavbarBrand ariaLabel whenever variant="logo". Name the product, not the image file or visual treatment.
  • Localized controls. Localize destination and app labels, overflowMenuLabel, appMenuLabel, account controls, and icon-only action names.
  • Accurate active state. Keep currentPath synchronized with the router. Add extraRouteMatchers when nested routes belong to one destination.
  • Meaningful app-switcher language. Use an action phrase such as "Switch app" for appMenuLabel. Do not repeat the current app name in that prop; the component combines them.
  • Accessible custom renderers. A custom renderTab replaces the complete interactive link in the visible row, so it must implement native link focus and activation, routing, current-state, modifier-click, and keyboard semantics. Use renderMeasurementTab for a single width-matched, non-interactive measurement element; it does not need to be an anchor. A custom renderOverflowMenuItem must return a focusable menu item that calls the supplied onSelect from the in-menu row for destination activation and communicates the supplied active state. If that row opens secondary UI in a portal, call onInteractingChange(true) while pointer or focus remains in the row or portaled UI, call onInteractingChange(false) when the interaction ends and during unmount cleanup, and do not call onSelect from portaled close actions. Interaction ending alone does not dismiss More. Outside events are suppressed while interaction is active; onSelect, Escape, or a deferred hover dismiss closes the menu.
  • Named trailing actions. Every icon-only action in NavbarEnd needs a tooltip or accessible name that states its action.
  • Named account triggers. If you compose an account menu, include the visible name in the accessible name. Treat the chevron as decorative by omitting its title. Click-open is the default; hover-open is opt-in.

Keyboard behavior

  • Tab / Shift+Tab move through primary links, app-switcher and overflow triggers, and trailing actions in document order.
  • Enter activates a focused destination link.
  • Middle-click or Cmd/Ctrl+click opens a destination in a new tab when app routing preserves native link behavior.
  • Enter / Space open the app-switcher and overflow menus. Overflow opens on click by default; hover-open is opt-in.
  • Arrow keys move among menu items.
  • Enter / Space select the focused app or overflow destination.
  • Escape closes an open menu and returns focus to its trigger, including when a custom overflow row is interacting with portaled UI.

Semantics and roles

  • The Navbar root is a named navigation landmark.
  • Nested destination TabNav roots are presentation-only so they do not split that landmark.
  • Primary destinations are links, not ARIA tabs. The active route is exposed as the current destination by the underlying TabNav.
  • A labeled logo brand is one named image. Decorative details inside it do not need separate names.
  • The app-switcher trigger is a button followed by a menu of menuitemradio choices.
  • The overflow trigger is a labeled button with a decorative chevron, followed by menu items for destinations that do not fit inline. A hidden current destination uses aria-current="page" on its menu row.
  • An account trigger is app-owned. Visible name plus a decorative rotating chevron is the recommended composition; it is not a Navbar primitive. Truncate the visible name only after --pr-navbar-account-name-max-width (12rem default); keep the full name in the accessible name.
  • NavbarGroup is visual grouping only. If an action cluster needs a group name, provide it through the interactive controls or a higher-level labeled pattern.

Focus and responsive behavior

When resizing moves destinations between the inline row and overflow menu, the destination remains reachable. Avoid changing width while a person is interacting with the Navbar unless the viewport or surrounding content genuinely changed. After route navigation, move focus to the new page heading or main content according to the app routing policy; do not leave focus in global chrome indefinitely.

When app selection replaces the destination model, update the route to a valid destination in the selected app. Keep focus on the switcher trigger after the menu closes, then let subsequent navigation follow the app focus policy.

Known caveats

  • Multiple landmarks. A Sidebar and Navbar can both be navigation landmarks. Distinct labels are required so screen-reader users can tell them apart.
  • Custom tabs. renderTab replaces TabNavItem in the visible row only. Keep that output semantically equivalent to a current-aware destination link. Measurement uses renderMeasurementTab or an inert default TabNavItem and reads every list child, so a non-anchor stand-in still occupies a slot. Do not put interactive side effects in the measurement renderer.
  • Custom overflow rows. Returning plain visual content instead of a menu item removes keyboard and menu semantics. Portaled secondary UI must call onInteractingChange(true) while engaged and false when the interaction ends and during unmount cleanup; every true call must be balanced so the menu cannot remain retained. Wire onSelect to the in-menu destination row only; Navbar dismisses More when onSelect runs.
  • Action-like destinations. Do not use onClickReplacesNavigation to turn primary navigation into an unrelated command. Put actions in NavbarEnd or a menu.
  • Disabled apps. If a disabled app remains visible, explain why it is unavailable through surrounding product guidance rather than relying on disabled styling alone.

Related accessibility pages

  • Tab nav accessibility for route-link behavior.
  • Menu accessibility for app-switcher and overflow keyboard behavior.
  • Sidebar accessibility for coordinating multiple navigation landmarks.
  • Icon button accessibility for trailing actions.

Previous

Navbar / API and Development

Next

Pagination / Usage

On this page

What the component handles
What you must provide
Keyboard behavior
Semantics and roles
Focus and responsive behavior
Known caveats
Related accessibility pages