Passer au contenu principal

Header

Implemented

Storefront 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.

Categoryorganisms
Sourcecomponents/organisms/Header/Header.tsx
AI HintUse for complex UI sections. Compose molecules and atoms into page sections. ADR-047: pass searchSlot (ReactNode) for sticky site search rendered between brand and actions on every viewport; showSearch (default true) is the kill-switch — set false on distraction-free flows like /checkout. No DS search component: the slot content is a consumer responsibility.

Public-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.ReactNode prop — renders at extreme LEFT, before nav/lang/theme
  • Made title?: string optional — 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

Prop
Type
Default
Description
title
string
—

Optional site/page title. When omitted, no <h1> is rendered (use logo-only branding). D-HOME-P2c 2026-08-11.

subtitle
string
—

Optional subtitle shown below title.

showSearch
boolean
true

Master 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).

searchSlot
React.ReactNode
—

Consumer 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.

searchPlaceholder
string
—

Placeholder text for the search input.

onSearch
(query: string) => void
—

Search input change handler.

rightActions
HeaderAction[]
—

Icon buttons on the right (e.g. notifications).

user
HeaderUserProfile
—

User avatar + name chip. Renders as <a> if href is set, <span> otherwise.

onThemeToggle
() => void
—

Theme toggle button. When provided, a sun/moon icon button appears.

themePressed
boolean
false

aria-pressed state for the theme toggle (true = dark mode active).

themeLabel
string
Toggle theme

Accessible label for the theme toggle button.

ariaLabel
string
Storefront header

Accessible label for the <header> element.

logo
React.ReactNode
—

Brand 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.

responsiveItems
ResponsiveItem[]
—

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?.

userAriaLabelPrefix
string
Account:

Localizable prefix for the user-chip accessible label (English default). Pass a translated prefix (e.g. 'Compte : ') for FR pages.

moreMenuLabel
string
More

Localizable text for the More collapse-dropdown trigger button.

moreMenuAriaLabel
string
More items

Localizable accessible label for the More trigger button.

moreMenuSectionLabel
string
More navigation items

Localizable accessible label for the More dropdown section.

moreMenuHideBelow
Breakpoint ("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.

className
string
—

Additional CSS classes merged onto the <header>.

id
string
—

Custom id for the <header>.

Props

Preview

Header

Prop
Type
Required
Default
Description
title
string
Optional
—

Optional site/page title — no <h1> is rendered when omitted or empty (logo-only branding, D-HOME-P2c 2026-08-11).

searchPlaceholder
string; onSearch?: (query: string) => void
Optional
'Search'

Synced from source — no interface JSDoc yet; document on `Header.tsx`.

rightActions
HeaderAction[]; user?: HeaderUserProfile
Optional
—

Synced from source — no interface JSDoc yet; document on `Header.tsx`.

onThemeToggle
() => void; themePressed?: boolean; themeLabel?: string
Optional
—

Synced from source — no interface JSDoc yet; document on `Header.tsx`.

ariaLabel
string; className?: string; id?: string
Optional
'Storefront header'

Synced from source — no interface JSDoc yet; document on `Header.tsx`.

logo
React.ReactNode
Optional
—

Synced from source — no interface JSDoc yet; document on `Header.tsx`.

responsiveItems
ResponsiveItem[]
Optional
—

Synced from source — no interface JSDoc yet; document on `Header.tsx`.

subtitle
string
Optional
—

Optional subtitle shown below the title (muted, truncated).

showSearch
boolean
Optional
true

Master 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).

searchSlot
React.ReactNode
Optional
—

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).

categoryChipsSlot
React.ReactNode
Optional
—

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.

cityFilterSlot
React.ReactNode
Optional
—

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
Optional
—

Search input change handler (fires on every keystroke).

user
HeaderUserProfile
Optional
—

User chip: `{ name, initials, href? }`. Renders as `<a>` when `href` is set, `<span>` (role=group) otherwise.

themePressed
boolean
Optional
false

`aria-pressed` state for the theme toggle (true = dark mode active).

themeLabel
string
Optional
'Toggle theme'

Accessible label for the theme toggle button.

className
string
Optional
—

Additional CSS classes merged onto the `<header>`.

id
string
Optional
header-${useId()}

Custom id for the `<header>` element; auto-generated when omitted.

userAriaLabelPrefix
string
Optional
'Account: '

Localizable prefix for the user-chip accessible label (English default). Pass a translated prefix for FR pages.

moreMenuLabel
string
Optional
'More'

Localizable text for the More collapse-dropdown trigger button (English default).

moreMenuAriaLabel
string
Optional
'More items'

Localizable accessible label for the More trigger button (English default).

moreMenuSectionLabel
string
Optional
'More navigation items'

Localizable accessible label for the More dropdown section (English default).

moreMenuHideBelow
Breakpoint
Optional
—

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.

Quick use:<Header />

Accessibility

ARIA rolebanner

Type

1 rule

DS ad-hoc 2026-08-11 (v2): storefront logo-only branding

logo prop renders brand at extreme LEFT of header (use instead of title for logo-only branding)

ARIA

1 rule

WCAG 1.3.1

Must be <header role='banner'>

Usage

Import

tsxSnippet
import { Header } from "@epasslive/design-system"

Example 1

tsxSnippet
<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

Design System v4.1.0 | ePassLive