Source: https://monarchui.dev/components/marketing-site-shell/

Patterns · Layout

# SiteHeader and SiteFooter

The frame of a public page: wordmark, navigation with disclosure panels, actions, and a footer of link columns.

@rookcom/monarch-react/marketing

Pattern

## Header and footer

## 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. `brand` is 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

```tsx
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-expanded` and `aria-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-canvas` at 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 `linkAs` so 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](https://monarchui.dev/components/marketing-hero/): Directly below the header.
- [Marketing sections](https://monarchui.dev/components/marketing-section-blocks/): The page body between header and footer.
- [Popover](https://monarchui.dev/components/popover/): The primitive behind group panels.

## Dependencies

| Kind | Depends on |
| --- | --- |
| npm packages | `@radix-ui/react-popover``react` |
| 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`

## All example code

### Header and footer

```tsx
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>
```
