Components / More
SiteHeader
The top bar of a website that scrolls as a document: a skip link, the brand, the site navigation and actions. It sticks to the top of the window, and on narrow screens the navigation moves into a menu sheet.
When to useLink to "When to use"
- Marketing and documentation sites built with Astro or React, where the window scrolls the whole page.
Use something else when:
- you are building an app with a side navigation and its own scrolling content area: AppShell
- you need the top of a page's content (title, description, actions): PageHeader
UsageLink to "Usage"
import { Button, SiteHeader, ThemeToggle } from "@arshad-shah/cynosure";
<SiteHeader
brand="Acme"
nav={[
{ label: "Docs", href: "/docs", current: true },
{ label: "Blog", href: "/blog" },
]}
actions={<><ThemeToggle /><Button href="/sign-in">Sign in</Button></>}
/>
<main id="main">…</main>In Astro, render it as a React island with client:load (or client:visible) so the menu button can open the sheet. Without hydration the bar, the links and the skip link still work; only the menu does not open.
Narrow screensLink to "Narrow screens"
Below collapseBelow (the header's own width: sm 40rem, md 48rem, lg 64rem) the links move into a sheet opened from a menu button. The actions stay in the bar.
StickyLink to "Sticky"
By default the header stays at the top while the page scrolls, over a blurred view of the page. sticky={false} lets it scroll away.
PropsLink to "Props"
| Prop | What it does | Type | Default |
|---|---|---|---|
brand | The logo or the site's name, at the inline start. Give a logo image its text alternative. | ReactNode | |
brandHref | Where the brand links to. false shows the brand without a link. Default "/". | string | false | "/" |
nav | The site navigation, as data. Each link is a real link; the current one is marked for assistive technology. | SiteHeaderLink[] | |
actions | Controls at the inline end, such as a ThemeToggle, a search button or a sign-in Button. They stay in the bar. | ReactNode | |
sticky | Keep the bar at the top of the window while the page scrolls, over a blurred view of the page. Default true. | boolean | true |
skipLink | Render a SkipLink before the bar, the first stop of the Tab order. Default true. | boolean | true |
skipTo | Where the skip link goes: # and the id of the page's main content. Default "#main". | string | "#main" |
collapseBelow | Width of the header below which the navigation moves into a menu opened from a button: sm 40rem, md 48rem, lg 64rem. CSS only, so the right layout shows before any script runs. Default "md". | "sm" | "md" | "lg" | "md" |
size | Widest the bar's content gets: the size of its Container, to line up with the page. Default "lg". | "sm" | "md" | "lg" | "full" | "xl" | "lg" |
labels | Replace the built-in English text: the landmark name, the menu button, the menu title and the skip link. | Partial<SiteHeaderLabels> | |
id | Set on the header element. | string | |
className | Added to the header element, for layout. | string | |
style | Layout only. Restyle through --cy-site-header-* tokens. | CSSProperties |
Generated from the type definitions in @arshad-shah/cynosure 0.5.0.
Behaviour and accessibilityLink to "Behaviour and accessibility"
| Input | Result |
|---|---|
| Tab | Skip link, brand, navigation links, actions, then the page |
| Enter on the skip link | Focus moves to the main content |
| Enter, Space, click on the menu button | Opens the menu sheet; focus moves into it |
| Escape | Closes the sheet; focus returns to the menu button |
| Choosing a link in the sheet | Closes the sheet; the browser follows the link |
- Landmarks: the
headeris the banner landmark at the top level of the page. The links are a list in anavnamed "Main" (labels.nav), in the bar and in the sheet. - Current page: the item with
currentgetsaria-current="page"and a highlight. - Skip link: a SkipLink to
skipTo(#main) is rendered before the header.skipLink={false}leaves it out, for a page that has its own. - Menu button: an IconButton with
aria-expanded. The sheet is a Sheet titled "Menu" (labels.menu), and its links are a SideNav. - No script needed for the layout: the switch to the menu is a container query, so a server-rendered page shows the right layout at once.
- Right to left: the brand starts at the right.
TouchLink to "Touch"
The brand, the links and the menu button have hit areas of at least 24px, and 44px on coarse pointers. The links in the menu sheet are 44px tall.
ThemingLink to "Theming"
| Token | What it sets | Default |
|---|---|---|
--cy-site-header-height | Least height of the bar | --cy-control-height-lg plus twice --cy-space-5 |
--cy-site-header-background | Background of the bar | --cy-color-bg |
--cy-site-header-border | Hairline under the bar | --cy-color-line |
--cy-site-header-blur | Blur of the page behind a sticky bar | 12px |
--cy-site-header-link-color | Navigation links | --cy-color-muted |
--cy-site-header-link-current-color | Current and hovered link | --cy-color-ink |
--cy-site-header-link-highlight | Background of the current and hovered link | --cy-color-soft |
createTheme({ components: { siteHeader: { blur: "0px", linkCurrentColor: "#c2410c" } } });The breakpoints of collapseBelow are fixed, because a container query cannot read a token. className and style are for layout only.
RelatedLink to "Related"
SkipLink · SiteFooter · Section · Container · AppShell · ThemeToggle
These examples run Cynosure 0.5.0 (commit 50ce30b), the version on npm.