Header
ImplementedStorefront site/dashboard header organism — 80px min-height, py-4 px-3 md:px-4 (16px vertical padding), native <header role="banner">. Left: logo slot plus optional title (24px/600) and subtitle. Right: searchSlot (ADR-047 — consumer ReactNode rendered between brand and actions, on every viewport; legacy raw <input> still renders when both showSearch and onSearch are set), categoryChipsSlot (SEARCH-03 — optional chip row rendered directly UNDER the search slot in the same middle column; consumer composition, no DS chip molecule), cityFilterSlot (SEARCH-05 — optional city filter rendered below the chips), responsive items with progressive disclosure (hideBelow items collapse into a "More" dropdown composed from the Menu molecule), rightActions icon buttons with optional count badges, theme toggle, and user profile chip. AdminHeader is the separate admin-chrome variant.
components/organisms/Header/Header.tsxPublic-facing site header with logo slot, optional title, responsive items, theme toggle, and user profile. D-HOME-P2c 2026-08-11 (logo-only branding), D-HOME-P4a 2026-08-11 (NavLink padding).
Header
Storefront organism (Family 7 — Tier 1)
Native header element with semantic banner role. Logo renders at the extreme LEFT (logo slot), optional title/subtitle next to it, then responsive items (nav links, language switcher, cart, login, theme toggle) on the right.
Usage
import { Header } from '@epasslive/design-system'
// Logo-only branding (recommended for public storefront)
<Header
ariaLabel="Site header"
logo={<Link href="/"><Logo size="md" /></Link>}
responsiveItems={[
{ id: 'nav', content: <NavLink href="/">Home</NavLink>, hideBelow: 'md' },
{ id: 'lang', content: <LanguageSwitcher />, hideBelow: 'md' },
{ id: 'theme', content: <ThemeToggle /> },
]}
onThemeToggle={toggleTheme}
themePressed={theme === 'dark'}
/>
// With title + subtitle
<Header
title="Dashboard"
subtitle="Manage your events"
onThemeToggle={toggleTheme}
themePressed={theme === 'dark'}
/>D-HOME-P2c changelog (2026-08-11)
- Added
logo?: React.ReactNodeprop — renders at extreme LEFT, before nav/lang/theme - Made
title?: stringoptional — no<h1>when omitted (logo-only branding) - DS-CORR-09-34 — Updated docs-nav.ts description: "Native action control with 4 variants and 3 sizes" → "Site header with logo slot..."
- D-HOME-P5s 2026-08-12 — Fixed JSX parse error: preview now passes valid Header props (
logo,title,responsiveItems) instead of Stepper props. Escaped<h1>as<code><h1></code>in changelog.
Accessibility
Native <header role="banner"> with aria-label. Logo link has focus-visible:ring-2 focus-visible:ring-ep-teal. Theme toggle has aria-pressed. Badge count and the non-link user chip carry role="group" (axe: aria-prohibited-attr). User-chip label prefix is localizable via userAriaLabelPrefix. Both the inline and collapsed search inputs have a visible focus-visible ring (WCAG 2.4.7).
Props
titlestringOptional site/page title. When omitted, no <h1> is rendered (use logo-only branding). D-HOME-P2c 2026-08-11.
subtitlestringOptional subtitle shown below title.
showSearchbooleantrueMaster switch for header search (default true, ADR-047). Gates searchSlot and the legacy built-in input (which still requires onSearch). Pass false to hide header search (e.g. /checkout).
searchSlotReact.ReactNodeConsumer search UI rendered between the brand block and the responsive-items/actions row, on every viewport. Renders when provided and showSearch is true (ADR-047). The DS owns placement only — no DS search component.
searchPlaceholderstringPlaceholder text for the search input.
onSearch(query: string) => voidSearch input change handler.
rightActionsHeaderAction[]Icon buttons on the right (e.g. notifications).
userHeaderUserProfileUser avatar + name chip. Renders as <a> if href is set, <span> otherwise.
onThemeToggle() => voidTheme toggle button. When provided, a sun/moon icon button appears.
themePressedbooleanfalsearia-pressed state for the theme toggle (true = dark mode active).
themeLabelstringToggle themeAccessible label for the theme toggle button.
ariaLabelstringStorefront headerAccessible label for the <header> element.
logoReact.ReactNodeBrand element rendered at the extreme LEFT of the header (e.g. logo). Use instead of title for logo-only branding. D-HOME-P2c 2026-08-11.
responsiveItemsResponsiveItem[]Items with breakpoint-based visibility (hideBelow or showBelow). Each has id, content, ariaLabel, hideBelow?, showBelow?, plus dropdown-rendering fields: icon?, label?, onSelect?, section? ("search" | "app" | "account" divider grouping), destructive?.
userAriaLabelPrefixstringAccount: Localizable prefix for the user-chip accessible label (English default). Pass a translated prefix (e.g. 'Compte : ') for FR pages.
moreMenuLabelstringMoreLocalizable text for the More collapse-dropdown trigger button.
moreMenuAriaLabelstringMore itemsLocalizable accessible label for the More trigger button.
moreMenuSectionLabelstringMore navigation itemsLocalizable accessible label for the More dropdown section.
moreMenuHideBelowBreakpoint ("sm" | "md" | "lg" | "xl")—Mobile overflow mode: suppresses the built-in More dropdown below the given breakpoint. Use when an external mobile drawer (e.g. DS MobileNav) already renders the collapsed items on small viewports. ADR-037.
classNamestringAdditional CSS classes merged onto the <header>.
idstringCustom id for the <header>.
Props
Header
titlestring—Optional site/page title — no <h1> is rendered when omitted or empty (logo-only branding, D-HOME-P2c 2026-08-11).
searchPlaceholderstring; onSearch?: (query: string) => void'Search'Synced from source — no interface JSDoc yet; document on `Header.tsx`.
rightActionsHeaderAction[]; user?: HeaderUserProfile—Synced from source — no interface JSDoc yet; document on `Header.tsx`.
onThemeToggle() => void; themePressed?: boolean; themeLabel?: string—Synced from source — no interface JSDoc yet; document on `Header.tsx`.
ariaLabelstring; className?: string; id?: string'Storefront header'Synced from source — no interface JSDoc yet; document on `Header.tsx`.
logoReact.ReactNode—Synced from source — no interface JSDoc yet; document on `Header.tsx`.
responsiveItemsResponsiveItem[]—Synced from source — no interface JSDoc yet; document on `Header.tsx`.
subtitlestring—Optional subtitle shown below the title (muted, truncated).
showSearchbooleantrueMaster switch for header search (default true, ADR-047). Gates the searchSlot ReactNode and the legacy built-in input (which still requires onSearch). Pass false to hide all header search (e.g. /checkout).
searchSlotReact.ReactNode—Search slot (ADR-047): consumer search UI rendered between the brand block and the responsive-items/actions row, on every viewport. Renders when provided AND showSearch is true. The DS owns placement only — the search input is a consumer responsibility (no DS SearchInput component, no barrel export).
categoryChipsSlotReact.ReactNode—SEARCH-03: optional category chip row rendered directly BELOW the search slot, inside the same flexible middle column. Renders when provided AND showSearch is true; absent keeps the SEARCH-02 DOM unchanged. The DS owns placement only — the storefront composes the DS FilterChipGroup molecule.
cityFilterSlotReact.ReactNode—SEARCH-05: optional city filter rendered BELOW the category chips in the same flexible middle column. Renders when provided AND showSearch is true. Placement only — the storefront composes the DS FilterChipGroup molecule.
onSearch(query: string) => void—Search input change handler (fires on every keystroke).
userHeaderUserProfile—User chip: `{ name, initials, href? }`. Renders as `<a>` when `href` is set, `<span>` (role=group) otherwise.
themePressedbooleanfalse`aria-pressed` state for the theme toggle (true = dark mode active).
themeLabelstring'Toggle theme'Accessible label for the theme toggle button.
classNamestring—Additional CSS classes merged onto the `<header>`.
idstringheader-${useId()}Custom id for the `<header>` element; auto-generated when omitted.
userAriaLabelPrefixstring'Account: 'Localizable prefix for the user-chip accessible label (English default). Pass a translated prefix for FR pages.
moreMenuLabelstring'More'Localizable text for the More collapse-dropdown trigger button (English default).
moreMenuAriaLabelstring'More items'Localizable accessible label for the More trigger button (English default).
moreMenuSectionLabelstring'More navigation items'Localizable accessible label for the More dropdown section (English default).
moreMenuHideBelowBreakpoint—Mobile overflow mode (ADR-037): suppresses the built-in More dropdown below the given breakpoint. Use when an external mobile drawer (e.g. DS MobileNav) already renders the collapsed items on small viewports.
<Header />Accessibility
Type
1 ruleARIA
1 ruleUsage
Import
import { Header } from "@epasslive/design-system"Example 1
<Header logo={<Logo />} title="My account" responsiveItems={[{ id: 'nav', content: <NavLink href="/">Home</NavLink>, hideBelow: 'md' }]} onThemeToggle={toggle} themePressed={isDark} />Anti-patterns
— Do not fetch data directly in organisms
— Avoid tight coupling to specific data sources