Skip to content

Latest commit

 

History

History
268 lines (219 loc) · 15.3 KB

File metadata and controls

268 lines (219 loc) · 15.3 KB
title Subdomain nav bar
description Use the subdomain nav bar component for top level navigation for subdomain sites.
keywords
navigation
top level
show-tabs false
ready true
figma https://www.figma.com/file/BJ95AjraesmRCWsKA013GS/Primer-Brand?node-id=1024%3A32796
source https://github.com/primer/brand/blob/main/packages/react/src/SubdomainNavBar/SubdomainNavBar.tsx
storybook /brand/storybook/?path=/story/components-subdomainnavbar--playground
thumbnail /images/thumbnails/subdomain-nav-bar-thumbnail.png
thumbnail_darkMode /images/thumbnails/subdomain-nav-bar-thumbnail-dark.png

import {Label} from '@primer/react' import {SubdomainNavBarChildrenProp} from './react'

import {SubdomainNavBar} from '@primer/react-brand'

Examples

SubdomainNavBar is designed to fix to the top of the viewport.

Please refer to our Storybook examples to see the component in a full-screen browser as originally intended.

Basic

<div style={{width: '100%'}}>
  <SubdomainNavBar title="Subdomain" fixed={false}>
    <SubdomainNavBar.Link href="#">Collections</SubdomainNavBar.Link>
    <SubdomainNavBar.Link href="#">Topics</SubdomainNavBar.Link>
    <SubdomainNavBar.Link href="#">Social</SubdomainNavBar.Link>
    <SubdomainNavBar.PrimaryAction href="#">Primary CTA</SubdomainNavBar.PrimaryAction>
    <SubdomainNavBar.SecondaryAction href="#">Secondary CTA</SubdomainNavBar.SecondaryAction>
  </SubdomainNavBar>
</div>

Leading and trailing content

Use leadingComponent for content between the title and navigation links. Use trailingComponent for content after search and actions. On narrow viewports, both slots move into the menu while preserving that order. Provide accessible names for interactive controls passed to either slot.

const App = () => (
  <div style={{width: '100%'}}>
    <SubdomainNavBar
      title="Subdomain"
      fixed={false}
      leadingComponent={<Token>Leading</Token>}
      trailingComponent={<Token>Trailing</Token>}
      style={{borderBlockEndColor: 'var(--brand-color-border-default)'}}
    >
      <SubdomainNavBar.Link href="/en/get-started">Get started</SubdomainNavBar.Link>
      <SubdomainNavBar.Link href="/en/rest">REST API</SubdomainNavBar.Link>
    </SubdomainNavBar>
  </div>
)

render(<App />)

Search

SubdomainNavBar offers an optional search form control that supports both onSubmit and onChange; use onChange to display inline results. The placeholder labels the input in the opened dialog and defaults to Search {title}, or Search when no navigation title is available.

Users can press / to open the search dialog, or use keyboardShortcut to remap or disable the shortcut. For programmatic control with openSearch() and closeSearch(), see the Imperative Search API Storybook example.

const groupedResults = [
  {
    title: 'Recommended',
    results: [
      {
        title: 'Getting started with GitHub',
        description: 'Create an account and learn the basics.',
        url: '/en/get-started',
        date: '2026-07-01',
        category: 'Guide',
      },
    ],
  },
  {
    title: 'API reference',
    results: [
      {
        title: 'REST API documentation',
        description: 'Integrate with GitHub using the REST API.',
        url: 'https://docs.github.com/en/rest',
        date: '2026-07-01',
        category: 'Reference',
        isExternal: true,
      },
    ],
  },
]

const SearchNav = () => {
  const [searchTerm, setSearchTerm] = React.useState('')

  return (
    <div style={{width: '100%'}}>
      <SubdomainNavBar title="GitHub Docs" fixed={false} fullWidth>
        <SubdomainNavBar.Link href="/en/get-started">Get started</SubdomainNavBar.Link>
        <SubdomainNavBar.Search
          placeholder="Search GitHub Docs"
          searchTerm={searchTerm}
          searchResults={searchTerm ? groupedResults : []}
          onChange={event => setSearchTerm(event.currentTarget.value)}
          onSubmit={event => {
            event.preventDefault()
          }}
        />
      </SubdomainNavBar>
    </div>
  )
}

render(<SearchNav />)

Search results can be a flat list or grouped by title. Do not mix both formats in the same array.

Localized search

Use the labels prop to localize search text. Any labels you omit fall back to English.

const labels = {
  searchLabel: 'Buscar',
  closeLabel: 'Cerrar',
  resultsLabel: 'Resultados',
  searchResultsLabel: 'Resultados de búsqueda',
  formatSearchWithTitle: title => `Buscar en ${title}`,
  formatSearchTrigger: placeholder => `Abrir ${placeholder}`,
  formatResultsHeading: searchTerm => `Resultados para «${searchTerm}»`,
  formatResultsLabel: searchTerm => `Resultados para ${searchTerm}`,
  formatSuggestions: count => `${count} sugerencia${count === 1 ? '' : 's'}.`,
}

const searchProps = {
  labels,
  placeholder: 'Buscar documentación',
}

const LocalizedSearch = () => {
  const [searchTerm, setSearchTerm] = React.useState('')

  return (
    <div style={{width: '100%'}}>
      <SubdomainNavBar title="Documentación" fixed={false}>
        <SubdomainNavBar.Search
          {...searchProps}
          searchTerm={searchTerm}
          onChange={event => setSearchTerm(event.currentTarget.value)}
          onSubmit={event => event.preventDefault()}
        />
      </SubdomainNavBar>
    </div>
  )
}

render(<LocalizedSearch />)

Accessibility

  • Provide a concise, meaningful title. It labels the navigation and communicates the subdomain to assistive technologies.
  • When the menu opens on narrow viewports, hide the rest of the document from screen readers with inert or aria-hidden="true". Use onNarrowMenuToggle to track the menu state.
  • Ensure interactive content supplied through leadingComponent or trailingComponent has an accessible name and remains keyboard operable.
  • Choose a keyboardShortcut that does not conflict with browser, operating system, or application shortcuts. Always provide another visible way to open search.
  • For search, localize its visible text, accessible labels, result headings, and live-region announcements. Supplying only some labels values produces a mix of localized text and English defaults.

Component props

SubdomainNavBar Required

Name Type Default Description
children Valid child nodes
className string Sets a custom class on the root element
id string Sets a custom ID on the root element
style React.CSSProperties Forwards custom inline styles to the root element
fixed boolean true Fixes the navigation bar to the top of the viewport
fullWidth boolean false Allows the inner content to fill the available width
logoHref string https://github.com Changes the URL of the GitHub logo
title string Required subdomain name used visibly and by assistive technologies
titleHref string / Links the title to the subdomain root
leadingComponent React.ReactNode Content rendered after the title and before navigation links
trailingComponent React.ReactNode Content rendered after search and actions
ref React.Ref<SubdomainNavBarHandle> Ref to the root element with openSearch() and closeSearch() methods
onNarrowMenuToggle (isOpen: boolean) => void Called with the new state when the narrow menu opens or closes

SubdomainNavBarProps and SubdomainNavBarHandle are exported from @primer/react-brand.

SubdomainNavBar.Search

Name Type Default Description
onSubmit (event: FormEvent<HTMLFormElement>) => void Required search form submit handler
onChange (event: ChangeEvent<HTMLInputElement>) => void Required search input change handler
placeholder string Search {title} Text shown in the input trigger and opened search input
shortcutLabel string Shortcut value Visible input-trigger hint; pass an empty string to hide it
keyboardShortcut string | false / Global key or modifier combination that opens search; false disables it
labels Partial<SubdomainNavBarSearchLabels> English labels Overrides visible and accessible search text and formatting functions
searchResults SubdomainNavBarSearchResults Flat or explicitly grouped results
searchTerm string Current query used in result headings and accessible labels
className string Sets a custom class on the search trigger container
ref React.Ref<HTMLInputElement> Ref to the input inside the opened search dialog

SubdomainNavBarSearchProps and SubdomainNavBarSearchLabels are exported from @primer/react-brand.

Search labels

Field Type English default Purpose
searchLabel string Search Accessible label for the search input
closeLabel string Close Visible and accessible close action
resultsLabel string Results Accessible label for an untitled result group
searchResultsLabel string Search results Accessible label for grouped results without a query
formatSearchWithTitle (title: string) => string Search ${title} Formats the default placeholder and dialog label
formatSearchTrigger (placeholder: string) => string ${placeholder} search Formats the responsive search trigger's accessible label
formatResultsHeading (searchTerm: string) => string Results for “${searchTerm}” Formats the visible heading for ungrouped results
formatResultsLabel (searchTerm: string) => string Results for ${searchTerm} Formats the accessible label for grouped results
formatSuggestions (count: number) => string ${count} suggestions. Formats the polite live-region result-count announcement

Search result types

SubdomainNavBarSearchResultProps, SubdomainNavBarSearchResultGroupProps, and SubdomainNavBarSearchResults are exported from @primer/react-brand.

SubdomainNavBarSearchResultProps

Field Type Required Description
title string Yes Linked result title
description string Yes Result summary
url string Yes Link destination
date string Yes Displayed date string; format it for the user's locale before passing it
category string Optional metadata displayed after the date
group string Groups flat results under a shared heading
isExternal boolean Shows an external-link indicator for grouped results

SubdomainNavBarSearchResultGroupProps

Field Type Required Description
title string Yes Visible and accessible group name
results SubdomainNavBarSearchResultProps[] Yes Results in the group

SubdomainNavBar.Link renders an anchor link.

Name Type Default Description
children React.ReactNode Link content
className string Applies a custom class
href string Destination path for the anchor element
isExternal boolean false Renders an external-link icon after the link when true

Additional props are passed to the wrapping <li> element. See MDN for accepted list item attributes.