Header
The top bar of every product: identity, search, language and the user's own controls. Three variants — two desktop, one mobile — and a product uses exactly one of them.
Type: Desktop 1
The full bar — utility strip ("Report an issue", Cymraeg), logo, search,
notification and avatar. The default variant, for products with no sidebar of their own. Code
value desktop.
<header class="sr-header">
<div class="sr-header__utility">…</div>
<div class="sr-header__main">
<span class="sr-header__logo">…</span>
<div class="sr-header__search">…</div>
<div class="sr-header__actions">…</div>
</div>
</header>
Type: Desktop 2
A single 80px bar, which pairs with the sidebar Navigation. It carries no logo,
because the sidebar does — and it is 64px so its bottom rule continues the sidebar's. Code value
desktop-2.
<header class="sr-header sr-header--bar">
<div class="sr-header__main">
<div class="sr-header__search">…</div>
<div class="sr-header__cluster">…</div>
</div>
</header>
Type: Mobile
A compact 56px bar: hamburger, logo, and a reduced action cluster. No utility strip
and no search field; showMenu centres the logo between the hamburger and the actions,
matching Mobile 1. This is the only variant MAUI renders — MAUI is mobile only (phone, tablet), so
Desktop 1 and Desktop 2 have no MAUI equivalent (see foundations/grid-and-layout.md). Code value
mobile.
<header class="sr-header sr-header--mobile sr-header--centered">
<div class="sr-header__main">
<button class="sr-header__menu">…</button>
<span class="sr-header__logo">…</span>
<div class="sr-header__actions">…</div>
</div>
</header>
The bar across the top of every screen: where staff search, switch language, see notifications, and confirm who they are signed in as.
When to use
- On every screen in an application. The header is persistent chrome, not page content.
- Use
desktop-2(the single bar) whenever the sidebarNavigationis present, the sidebar carries the brand lockup, so the header must not repeat it. - Use
desktop(utility strip + main bar) only where there is no sidebar and the header carries the brand.
When not to use
- Not for page-level actions. Those belong in the page, next to what they act on.
- Not as a place to put screen navigation, that is
Navigation's job.
How it works
| Variant | Height | Contains |
|---|---|---|
desktop | 40px utility + 64px main | Report an issue, language toggle, logo, search, notification, avatar |
desktop-2 | 64px | Search, org switcher, language toggle, notification, avatar. No logo |
mobile | 56px | Optional hamburger, symbol logo, notification, avatar. No inline search |
desktop-2is 64px to match the sidebar's logo block, so the two bottom rules form one continuous line across the top of the app. If either changes, both must.- Search sits with the utility cluster on the right, not pushed to the far left, they read as one group of tools rather than two unrelated ones.
- The org switcher renders only when there is an org to switch. Passing an empty value must not leave a chevron that opens nothing.
Do and don't
- Do keep the header on every screen of an application, including error and empty states.
- Do let the search field flex below 1024px rather than holding a fixed width.
- Don't add product-specific actions to the header. It is shared chrome; anything added here appears in every product that uses it.
- Don't rely on the avatar alone to convey who is signed in, it carries initials, not identity.
Accessibility
- Renders a real
<header>landmark. There is one per page. - Notification and avatar controls are named by what they do, not what they look like.
- The language toggle keeps its globe icon at every breakpoint; only the word is dropped on small screens, because the icon is the recognisable part.
- Search is a labelled field. Where the design shows no visible label, use
hideLabel, a placeholder is not an accessible name and disappears on typing. - Focus ring is the SR cyan ring on every control.
Content
- "Cymraeg" is never translated, it is the label for switching to Welsh, and it stays in Welsh whichever language the interface is in.
- Keep the search placeholder to what can be searched, not an instruction ("Type here to begin search", not "Search").
Accessibility requirements
| Requirement | WCAG SC | How Single Record meets it | Test method |
|---|---|---|---|
| One header landmark per page | 1.3.1 | Renders a real <header> element; products must not nest a second. | Landmark review |
| Icon-only controls are named | 4.1.2 | Notification and avatar controls carry an accessible name describing the action, not the glyph. | Screen reader announce |
| Search field has a label | 3.3.2 | A real label, visually hidden via hideLabel where the design shows none — a placeholder is not an accessible name and disappears on typing. | Screen reader, type into field |
| Language toggle survives narrow viewports | 1.4.10 | Below 768px the word is dropped but the globe icon remains, so the control stays recognisable rather than becoming an empty button. | Resize to 390px |
| Focus visible | 2.4.7 | SR cyan ring on every control, offset from the bar edge so it is not clipped. | Keyboard tab |