Patterns · Layout
SiteHeader and SiteFooter
The frame of a public page: wordmark, navigation with disclosure panels, actions, and a footer of link columns.
Header and footer
import { Button } from '@rookcom/monarch-react';
import { SiteFooter, SiteHeader } from '@rookcom/monarch-react/marketing';
<div>
<SiteHeader
sticky={false}
brand={<a href="#/components/marketing-site-shell">Rook Example</a>}
nav={[
{
label: 'Product',
items: [
{
label: 'Editor',
href: '#/components/marketing-site-shell',
description: 'Pages and blocks',
},
{
label: 'Search',
href: '#/components/marketing-site-shell',
description: 'Find any page',
},
],
},
{ label: 'Pricing', href: '#/components/marketing-site-shell' },
]}
actions={
<>
<Button variant="ghost" size="sm">
Log in
</Button>
<Button variant="primary" size="sm">
Start free
</Button>
</>
}
/>
<SiteFooter
columns={[
{
title: 'Product',
links: [{ label: 'Editor', href: '#/components/marketing-site-shell' }],
},
{
title: 'Company',
links: [{ label: 'About Rook', href: '#/components/marketing-site-shell' }],
},
]}
legal="© 2026 Rook"
legalLinks={[{ label: 'Privacy', href: '#/components/marketing-site-shell' }]}
/>
</div>Usage examples
The example at the top of the page is the only one for this component.
Purpose
SiteHeader and SiteFooter give every public site the same navigation model and landmarks. Import from @rookcom/monarch-react/marketing.
Use when
- Product sites, launch pages, docs landing pages and other public pages.
Avoid when
- Signed-in app screens: use the app shell (
RookRail, from@rookcom/monarch-react/shell). - Dialog-like flows such as sign-in, where navigation would distract.
Design principles
- Quiet chrome: a translucent canvas bar with a hairline border, muted links that darken on hover; the wordmark and one primary action carry the brand.
- Group items open a panel of links with descriptions, not an application menu: they are navigation, so they stay links.
- No artwork ships in the package.
brandis a slot for the product wordmark from your brand kit. - Footer column titles are real headings and links meet the 24px target size.
API reference
import { SiteFooter, SiteHeader } from '@rookcom/monarch-react/marketing';| Export | Kind | Rendering | Root class |
|---|---|---|---|
SiteFooter | component | server-safe | .mn-site-footer |
SiteHeader | component | client | .mn-site-menu- |
nav takes SiteLink (label, href, description?, current?, external?) and SiteNavGroup (label, items).
linkAs renders every link with your router (for example Next.js Link); it receives href, className, aria-current, and target/rel for external links.
Group panels use Radix Popover, portalled to the body.
Generated from the TypeScript declarations of packages/react/src/patterns/layout/marketing-site-shell.
Properties
SiteFooter
Site footer: brand, link columns with real headings, and a legal row. Every link has at least a 24px target (WCAG 2.5.8). Server-component safe.
| Prop | Type | Description |
|---|---|---|
brand | ReactNode | Wordmark (link home). |
children | ReactNode | |
className | string | |
columns | SiteFooterColumn[] | |
description | ReactNode | One sentence about the product or company. |
headingAs | HeadingLevel | Heading element for column titles. |
id | string | |
legal | ReactNode | Copyright and company line. |
legalLinks | SiteLink[] | Policy links beside the legal line. |
linkAs | LinkComponent | Router link component. Default `a`. |
meta | ReactNode | Extra content on the trailing edge of the bottom row (language switcher, status). |
navLabel | string | Accessible name of the footer navigation. |
SiteHeader
Site header for marketing and public pages: wordmark, primary navigation with disclosure menus, and actions. Under 768px the navigation collapses into a menu button (`aria-expanded`), closed with Escape.
| Prop | Type | Description |
|---|---|---|
brand required | ReactNode | Product wordmark, normally a link home: `<a href="/"><img alt="Rook Dossier" …/></a>`. Monarch ships no artwork; use the product's logo from the Rook brand kit. |
actions | ReactNode | Calls to action on the trailing edge, e.g. "Log in" and one primary Button. |
children | ReactNode | |
className | string | |
id | string | |
linkAs | LinkComponent | Router link component for nav links (e.g. Next.js Link). Default `a`. |
menuLabels | { open: string; close: string; } | Labels for the mobile menu toggle. |
nav | SiteNavItem[] | Top-level links and groups. Groups open a disclosure panel of links. |
navLabel | string | Accessible name of the navigation landmark. |
sticky | boolean | Stick to the top while scrolling. Default true. |
Variants
| Prop | Values | Description |
|---|---|---|
sticky (SiteHeader) | 'true''false' | Stick to the top while scrolling (default true). |
headingAs (SiteFooter) | 'h2''h3''h4' | Heading level of the column titles. |
States
| State | Exposed as | Behaviour |
|---|---|---|
| Current page | aria-current="page" | Set current on a link; it renders in the default text colour. |
| Group open | aria-expanded="true" | Trigger tinted, chevron rotated, panel shown. |
| Mobile menu open | aria-expanded="true" (toggle) | Below 768px the toggle shows a close icon and the panel lists every link. |
Interaction behaviour
- Clicking a group trigger opens its panel; clicking outside, Escape or choosing a link closes it.
- Below 768px, links and actions move into a disclosure panel under the bar; Escape closes it and returns focus to the toggle.
Keyboard support
| Keys | Action |
|---|---|
| Tab | Moves through wordmark, links, group triggers and actions. |
| Enter / Space | Opens a group panel or the mobile menu. |
| Escape | Closes the open panel and returns focus to its trigger. |
Accessibility
- Role
- banner and contentinfo landmarks, each with a labelled navigation
- Accessible name
navLabel(default "Main" in the header, "Footer" in the footer).
- The mobile toggle names its action ("Open menu" / "Close menu") and has
aria-expandedandaria-controls. - External links get target and rel attributes and a visually hidden "(opens in a new tab)".
- Header targets are at least 36px tall, mobile panel links 44px, footer links 32px (WCAG 2.5.8 needs 24px).
Responsive behaviour
- From 768px: inline navigation and actions. Below: wordmark plus a 44px menu toggle.
- Footer: brand above the columns until 1024px, beside them after; columns go from two to auto-fit.
Theme support
- All colours are semantic tokens; the bar is
--mn-color-bg-canvasat 86% with a backdrop blur. - Works unchanged in light, dark and more-contrast themes and every product accent.
Do and don't
Do
- Use the product wordmark from the brand kit as
brand, linked home, with the product name as alt text. - Keep actions to "Log in" (ghost) and one primary.
- Pass
linkAsso navigation uses client-side routing.
Don't
- Do not put application menus (actions, checkboxes) in nav groups.
- Do not add banners, crowns, gold or decorative artwork to the bar.
- Do not list pages that do not exist yet.
Related components
- MarketingHero: Directly below the header.
- Marketing sections: The page body between header and footer.
- Popover: The primitive behind group panels.
Dependencies
| Kind | Depends on |
|---|---|
| npm packages | @radix-ui/react-popoverreact |
| Monarch components | None |
Testing coverage
- Group triggers open a panel of links; current page is marked.
- Mobile toggle has aria-expanded, closes on Escape and restores focus.
- Footer column titles are headings; external links announce the new tab.
- Landmarks are present with no axe violations; renders on the server.
| Check | Covered |
|---|---|
| Axe in jsdom | Yes |
| Server rendering | Yes |
| Browser suites | Visual baselines and three-browser axe: /__marketing |
Tests: packages/react/src/patterns/layout/marketing-site-shell