| title | Subdomain nav bar | ||
|---|---|---|---|
| description | Use the subdomain nav bar component for top level navigation for subdomain sites. | ||
| keywords |
|
||
| 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'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.
<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>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 />)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.
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 />)- 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
inertoraria-hidden="true". UseonNarrowMenuToggleto track the menu state. - Ensure interactive content supplied through
leadingComponentortrailingComponenthas an accessible name and remains keyboard operable. - Choose a
keyboardShortcutthat 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
labelsvalues produces a mix of localized text and English defaults.
| 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.
| 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.
| 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 |
SubdomainNavBarSearchResultProps, SubdomainNavBarSearchResultGroupProps, and SubdomainNavBarSearchResults are exported from @primer/react-brand.
| 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 |
| 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.