Experience System

Page Header

Page-level header with title band, optional navigation, supporting content, and an inline expandable region.

2520-03

EmptyMissing
Page content

Installation

The components are exported from @by/experience-system. Add the package with your package manager:

pnpm add @by/experience-system

In this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.

Composition

Use the following composition to build a PageHeaderRoot:

PageHeaderRoot
├── PageHeaderMain
│   ├── PageHeaderTitleBar
│   │   ├── PageHeaderNavigation (optional)
│   │   │   └── PageHeaderBackButton (optional)
│   │   ├── PageHeaderTitleRow
│   │   │   ├── PageHeaderTitle
│   │   │   │   ├── string title
│   │   │   │   └── dropdownTrigger: PageHeaderTitleTrigger (optional)
│   │   │   └── PageHeaderMeta (optional)
│   │   ├── PageHeaderActions (optional)
│   │   └── PageHeaderExpandSlot (optional)
│   │       └── PageHeaderExpandTrigger
│   └── PageHeaderContent (optional)
└── PageHeaderExpandableContent (optional)

PageHeaderTitleBar groups the title row, actions, metadata overflow, and optional expand slot. PageHeaderNavigation is absolutely positioned 10px outside the component start edge and does not consume grid space, so the title row aligns with page content padding in both LTR and RTL. Place breadcrumbs, descriptions, and stacked context in PageHeaderContent below the title bar — it shares the same leading inset as the title row. Put PageHeaderExpandTrigger in PageHeaderActions for simple layouts, or in PageHeaderExpandSlot when responsive actions can wrap below the title row. Inline expansion uses Radix Collapsible wired through the root PageHeaderRoot API.

For most headers, pass the title as string children to PageHeaderTitle. It renders the title label for you and can keep a dropdownTrigger attached to the last title word when wrapping. In string-title mode, titleLabelProps supports PageHeaderTitleLabel attributes except asChild and children. Use PageHeaderTitleLabel directly only when manually composing the title internals, such as adding PageHeaderTitleIcon, custom markup, or asChild behavior.

Usage

import {
  PageHeaderRoot,
  PageHeaderActions,
  PageHeaderMain,
  PageHeaderTitle,
  PageHeaderTitleBar,
  PageHeaderTitleRow,
} from '@by/experience-system';

PageHeaderRoot and its parts are client components ('use client'). Use them inside a Client Component or a dynamic import when using the Next.js App Router.

<PageHeaderRoot>
  <PageHeaderMain>
    <PageHeaderTitleBar>
      <PageHeaderTitleRow>
        <PageHeaderTitle>Orders</PageHeaderTitle>
      </PageHeaderTitleRow>
      <PageHeaderActions>{/* page-level commands */}</PageHeaderActions>
    </PageHeaderTitleBar>
  </PageHeaderMain>
</PageHeaderRoot>

Selectable titles keep the dropdown menu composition outside the title primitive while passing the trigger node into PageHeaderTitle:

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuTrigger,
  PageHeaderTitle,
  PageHeaderTitleTrigger,
} from '@by/experience-system';

<DropdownMenu>
  <PageHeaderTitle
    dropdownTrigger={
      <DropdownMenuTrigger asChild>
        <PageHeaderTitleTrigger aria-label="Select title">{/* icon */}</PageHeaderTitleTrigger>
      </DropdownMenuTrigger>
    }
  >
    Orders
  </PageHeaderTitle>
  <DropdownMenuContent>{/* title options */}</DropdownMenuContent>
</DropdownMenu>;

Examples

Basic

Title label with a selectable menu trigger, metadata badges, trailing actions, and page content below the header.

2520-03

EmptyMissing
Page content

Basic header with a leading back button in the navigation slot.

2520-03

EmptyMissing
Page content

Complex

Full header with navigation, icon, selectable title, badges, breadcrumbs, description, expandable content, and page content below.

2520-03

EmptyMissing

Equipment list

Expandable content
Page content

Responsive

Responsive header behavior with pinned navigation and expand controls, toolbar overflow, metadata wrapping, and title wrapping with the dropdown trigger kept on the last word.

Overview

EmptyMissing
Expandable content
Page content
Drag handle to resize header width

API Reference

Subsection titles name the exports from @by/experience-system. These are design-system layout primitives (not Radix wrappers), except where noted for collapsible behavior.

PageHeaderRoot

Root page-level header. Owns border, surface styling, and optional inline expand/collapse via Collapsible.

PropTypeDefault
variant'default' | 'sticky''default'
expandedboolean
defaultExpandedbooleanfalse
onExpandedChange(expanded: boolean) => void
classNamestring
Data attributeValues
data-slotpage-header
data-variantdefault, sticky
data-expandedPresent when expanded

Also accepts standard header attributes.

PageHeaderMain

Required top row container. Two-column grid (title band | actions) with ps-scaled-3 leading inset so the title row aligns with page content padding.

Data attributeValues
data-slotpage-header-main

Also accepts standard div attributes.

PageHeaderTitleBar

Groups navigation, title row, and actions for the title band. Uses display: contents.

Data attributeValues
data-slotpage-header-title-bar

Also accepts standard div attributes.

PageHeaderNavigation

Optional leading navigation slot for back buttons or custom controls. Absolutely positioned 10px outside the component start edge (-start-scaled-2.5) so it does not shift the title column in LTR or RTL.

Data attributeValues
data-slotpage-header-navigation

Also accepts standard div attributes.

PageHeaderBackButton

Icon button for back/up navigation. No routing behavior built in.

PropTypeDefault
onClickReact.MouseEventHandler<HTMLButtonElement>required
labelstring"Go back"
Data attributeValues
data-slotpage-header-back-button

Also accepts Button props except onClick and children.

PageHeaderContent

Supporting content below the title bar: breadcrumbs, descriptions, stacked context.

Data attributeValues
data-slotpage-header-content

Also accepts standard div attributes.

PageHeaderTitleRow

Horizontal row for the title group and metadata.

Data attributeValues
data-slotpage-header-title-row

Also accepts standard div attributes.

PageHeaderTitle

Preferred title primitive. Pass string children for the default responsive title label. Use dropdownTrigger for a consumer-owned menu trigger; when wrap is true, the trigger stays with the last word of the title instead of orphaning onto its own line.

PropTypeDefault
childrenReact.ReactNode
dropdownTriggerReact.ReactNode
wrapbooleanfalse
titleLabelPropsOmit<PageHeaderTitleLabelProps, 'asChild' | 'children'>
classNamestring
Data attributeValues
data-slotpage-header-title

Also accepts standard div attributes.

PageHeaderTitleIcon

Optional leading icon beside the page title label (20×20).

Data attributeValues
data-slotpage-header-title-icon

Also accepts standard div attributes.

PageHeaderTitleLabel

Lower-level title text primitive for manual composition. Prefer string children on PageHeaderTitle for standard headers. Use PageHeaderTitleLabel directly when you need PageHeaderTitleIcon, custom label markup, or asChild. It renders h4 by default and h5 when PageHeaderMain is compact.

PropTypeDefault
asChildbooleanfalse
truncatebooleantrue
Data attributeValues
data-slotpage-header-title-label

Also accepts standard h4 attributes (or child element props when asChild).

PageHeaderTitleTrigger

Icon-only trigger beside PageHeaderTitleLabel for menus or selection. Keep the label outside the trigger. Provide an accessible name (for example aria-label="Select title").

Data attributeValues
data-slotpage-header-title-trigger

Also accepts standard button attributes.

PageHeaderMeta

Slot next to the title for badges, chips, or compact data-display elements.

Data attributeValues
data-slotpage-header-meta

Also accepts standard div attributes.

PageHeaderDescription

Optional supporting text under the title row.

Data attributeValues
data-slotpage-header-description

Also accepts standard p attributes.

PageHeaderActions

Trailing action area for page-level commands.

Data attributeValues
data-slotpage-header-actions

Also accepts standard div attributes.

PageHeaderExpandSlot

Optional pinned slot for PageHeaderExpandTrigger when responsive actions can wrap below the title row. Keeps the expand control in the top row while the toolbar or actions move.

Data attributeValues
data-slotpage-header-expand-slot

Also accepts standard div attributes.

PageHeaderExpandTrigger

Icon button that toggles the expandable region. Place inside PageHeaderActions for simple layouts, or inside PageHeaderExpandSlot when actions can wrap responsively. Uses Radix CollapsibleTrigger.

PropTypeDefault
expandLabelstring"Expand section"
collapseLabelstring"Collapse section"
Data attributeValues
data-slotpage-header-expand-trigger

Also accepts Button props except children.

PageHeaderExpandableContent

Optional collapsible region below the main header row. Uses Radix CollapsibleContent.

Data attributeValues
data-slotpage-header-expandable-content

Also accepts standard div attributes.

Accessibility

PageHeaderRoot renders a header landmark (banner role). String children on PageHeaderTitle render the semantic title label for you; PageHeaderTitleLabel renders h4 or h5 depending on the compact state of PageHeaderMain. PageHeaderBackButton exposes an accessible name through aria-label (default Go back). PageHeaderTitleTrigger must have an accessible name when used as a dropdown or selection trigger. PageHeaderExpandTrigger provides screen-reader-only expand/collapse labels via expandLabel and collapseLabel. Mark decorative icons aria-hidden="true". For expand/collapse keyboard behavior, see Radix Collapsible — accessibility.

Source in the repo: packages/experience-system/src/components/PageHeader/PageHeader.tsx. Agent-oriented contracts: packages/experience-system/src/components/PageHeader/PageHeader.instructions.md.