Skip to content
SuperCoach

Components · Navigation

Navigation menu

Beta

Top-level site navigation with submenus.

When to use

  • For the top navigation of public, marketing-style pages: the SuperCoach website, the help center, a coach's public profile and packages.
  • When a few top-level sections each have a handful of pages that benefit from a short description: Getting started, Features.

coach-admin itself doesn't need it. The app's main navigation is the Sidebar, and in-page views use Tabs.

When not to use

  • For coach-admin's main navigation: use the Sidebar.
  • For a list of actions on an item (Edit, Duplicate, Archive): use a dropdown menu. Navigation menu items go to pages; they don't act.
  • For more than about 5 top-level items, or deep trees: use a sidebar, or a page that lists the sections.
  • On mobile: the bar doesn't fit. Use a Sheet with the same links.

Anatomy

  1. 1. Navigation menu: a nav landmark around a list; give it an aria-label
  2. 2. Trigger: a button that opens a submenu; the chevron turns when open
  3. 3. Link: a top-level page with no submenu, styled like a trigger

Open a trigger to see the rest: the content with links (a title and an optional one-line description each), and the viewport, the popover-colored panel that holds the open content. With the viewport (the default) one panel is shared and resizes as the coach moves between triggers; with viewport={false} each content opens in its own panel under its trigger. An optional indicator (NavigationMenuIndicator) points at the open trigger.

Variants

VariantUse for
With viewport (default)Several submenus of different sizes. The shared panel animates between them, sliding in from the side the coach moved toward.
Without viewport (viewport={false})One or two small submenus, or when the panel must sit right under its trigger.
Link onlyA top-level page with no submenu ("Pricing"). Use NavigationMenuLink with navigationMenuTriggerStyle().

States

StateWhat changesToken
RestPage backgroundbg-background
Hover, focusAccent fillhover:bg-accent, focus:bg-accent, text-accent-foreground
OpenLighter accent fill; chevron turns 180°data-[state=open]:bg-accent/50, duration-(--duration-slow)
Current page (active)Lighter accent fill, aria-current="page"data-[active=true]:bg-accent/50
Focus-visibleRingring-ring/50, 3px
DisabledHalf opacityopacity-(--opacity-disabled)
PanelPopover surface with border and shadow, on the dropdown layerbg-popover, text-popover-foreground, border, shadow, z-(--z-dropdown)

"Pricing" in the first preview is marked as the current page with active.

Usage guidelines

  • 3 to 5 top-level items. Each submenu has 2 to 6 links; more than that wants its own page.
  • Mark the section of the current page with active, so it is visible and announced.
  • Every trigger opens a submenu, and every submenu link goes to a page. Don't put buttons, forms or search inside a submenu.
  • Submenus open on hover and on click. Don't rely on hover alone for anything important; touch screens and keyboards don't hover.
Do.A few top-level sections. Detail lives in their submenus.
Don't.Every page at the top level. It wraps, and nothing stands out.

Content guidelines

  • Top-level labels are one or two words, nouns, sentence case: "Getting started", "Features", "Pricing".
  • Link titles name the page; the description says what the coach finds there, in one short sentence: "Packages, invoices and payouts."
  • Don't repeat the section in each link: under "Features", write "Programs", not "Programs feature".
  • Arabic labels are short nouns too: "البدء"، "المزايا"، "الأسعار".

Accessibility

KeyDoes
TabMoves through the triggers and links, and into an open submenu
Enter / SpaceOpens or closes the submenu of the focused trigger; opens a focused link
Arrow downFrom an open trigger, moves into its submenu
Arrow left / rightMoves between top-level items. Reversed in RTL
Home / EndFirst / last top-level item
EscapeCloses the submenu and returns focus to its trigger
  • Rendered as a nav landmark with a list. Name it with aria-label ("Help center"), because a page often has more than one nav.
  • Triggers are buttons with aria-expanded and aria-controls: "Features, collapsed, button".
  • Links marked active get aria-current="page": "Pricing, current page, link".
  • The submenu is not a menu role: it's a group of ordinary links, so screen readers keep their normal link navigation.
  • Opening on hover waits 200ms, so moving the pointer across the bar doesn't flash panels open.

RTL

The bar reads from right to left, and arrow keys follow the reading order (the site provides Radix's DirectionProvider). The shared viewport sits at the start edge. Content slides in from the side the coach moved toward, which flips in RTL: the component has rtl: variants for each data-motion direction. The trigger chevron points down and does not mirror.

Tokens used

Read from components/ui/navigation-menu.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.

Semantic color tokens used by this component
TokenUtilitiesSuperCoachCoach
--accentbg-accent bg-accent/50brand-50orange-50
--accent-foregroundtext-accent-foregroundbrand-700orange-700
--backgroundbg-backgroundwhitewhite
--borderbg-borderneutral-200neutral-200
--muted-foregroundtext-muted-foregroundneutral-600neutral-600
--popoverbg-popoverwhitewhite
--popover-foregroundtext-popover-foregroundneutral-950neutral-950
--ringring-ring/50brand-600orange-500
  • Layerz-(--z-dropdown)
  • Layerz-(--z-raised)
  • Motionduration-(--duration-base)
  • Motionduration-(--duration-slow)
  • Opacityopacity-(--opacity-disabled)
  • Radiusrounded-md
  • Radiusrounded-sm rounded-ss-sm
  • Shadowshadow-md
  • Typefont-medium
  • Typetext-sm

Props

<NavigationMenu>

Also takes every prop of Radix NavigationMenu.Root

NavigationMenu props
PropTypeDefault
viewport?booleantrue

<NavigationMenuTrigger>

Also takes every prop of Radix NavigationMenu.Trigger

No props of its own.

<NavigationMenuContent>

Also takes every prop of Radix NavigationMenu.Content

No props of its own.

Also takes every prop of Radix NavigationMenu.Link

No props of its own.

<NavigationMenuIndicator>

Also takes every prop of Radix NavigationMenu.Indicator

No props of its own.

Replaces in coach-admin

From the read-only audit of coach-admin: 66 style values, 72 uses.

coach-admin's header is CoreUI's .navbar (brand, toggler, language switch and a banner). It is an app header, not a navigation menu: when it is rebuilt, its links belong in the Sidebar and its account actions in a dropdown menu. src/views/Base/Navbars is a CoreUI demo page (DECISIONS #10).

Classes and selectors

  • .navbar-brand12
  • .navbar-toggler5
  • .navbar .rtl3
  • .nav-dropdown.open3
  • .nav-dropdown-items2
  • .navbar-divider1
  • .navbar-toggler-icon1
  • .navbar-nav .dropdown-item img, .exercises-page .view-action1
  • .navbar-collapse li1
  • .navbar i1
  • .navbar-nav:has(.language-dropdown)1
  • .navbar-collapse .form-inline1

Files

  • src/components/Header/header-banner.scss30
  • src/components/Header/systemColorsConfig.js5
  • src/components/Header/ChangeLang.css3
  • src/views/Base/Navbars/Navbars.js1

The inventory lists the first 12 locations of each value, so file counts are a lower bound.

SCSS variables in these styles

  • $navbar-active-color→ nearest neutral-800 (no semantic token)
  • $navbar-brand-widthnot a color: spacing, size or layout
  • $navbar-brand-bgnot a color: spacing, size or layout
  • $navbar-color→ nearest neutral-600 (no semantic token)
  • $navbar-brand-logonot a color: spacing, size or layout
  • $navbar-brand-minimized-bgnot a color: spacing, size or layout
  • $navbar-brand-minimized-logonot a color: spacing, size or layout
  • $navbar-toggler-iconnot a color: spacing, size or layout
  • $sidebar-nav-dropdown-bgnot a color: spacing, size or layout
  • $navbar-padding-ynot a color: spacing, size or layout
  • $navbar-padding-xnot a color: spacing, size or layout
  • $navbar-toggler-padding-ynot a color: spacing, size or layout

Sidebar, Tabs, Dropdown menu, Breadcrumb, Sheet.