Page Header
Page-level header with title band, optional navigation, supporting content, and an inline expandable region.
2520-03
Installation
The components are exported from @by/experience-system. Add the package with your package manager:
pnpm add @by/experience-systemIn 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
Navigation
Basic header with a leading back button in the navigation slot.
2520-03
Complex
Full header with navigation, icon, selectable title, badges, breadcrumbs, description, expandable content, and page content below.
2520-03
Equipment list
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
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.
| Prop | Type | Default |
|---|---|---|
variant | 'default' | 'sticky' | 'default' |
expanded | boolean | — |
defaultExpanded | boolean | false |
onExpandedChange | (expanded: boolean) => void | — |
className | string | — |
| Data attribute | Values |
|---|---|
data-slot | page-header |
data-variant | default, sticky |
data-expanded | Present 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 attribute | Values |
|---|---|
data-slot | page-header-main |
Also accepts standard div attributes.
PageHeaderTitleBar
Groups navigation, title row, and actions for the title band. Uses display: contents.
| Data attribute | Values |
|---|---|
data-slot | page-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 attribute | Values |
|---|---|
data-slot | page-header-navigation |
Also accepts standard div attributes.
PageHeaderBackButton
Icon button for back/up navigation. No routing behavior built in.
| Prop | Type | Default |
|---|---|---|
onClick | React.MouseEventHandler<HTMLButtonElement> | required |
label | string | "Go back" |
| Data attribute | Values |
|---|---|
data-slot | page-header-back-button |
Also accepts Button props except onClick and children.
PageHeaderContent
Supporting content below the title bar: breadcrumbs, descriptions, stacked context.
| Data attribute | Values |
|---|---|
data-slot | page-header-content |
Also accepts standard div attributes.
PageHeaderTitleRow
Horizontal row for the title group and metadata.
| Data attribute | Values |
|---|---|
data-slot | page-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.
| Prop | Type | Default |
|---|---|---|
children | React.ReactNode | — |
dropdownTrigger | React.ReactNode | — |
wrap | boolean | false |
titleLabelProps | Omit<PageHeaderTitleLabelProps, 'asChild' | 'children'> | — |
className | string | — |
| Data attribute | Values |
|---|---|
data-slot | page-header-title |
Also accepts standard div attributes.
PageHeaderTitleIcon
Optional leading icon beside the page title label (20×20).
| Data attribute | Values |
|---|---|
data-slot | page-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.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
truncate | boolean | true |
| Data attribute | Values |
|---|---|
data-slot | page-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 attribute | Values |
|---|---|
data-slot | page-header-title-trigger |
Also accepts standard button attributes.
PageHeaderMeta
Slot next to the title for badges, chips, or compact data-display elements.
| Data attribute | Values |
|---|---|
data-slot | page-header-meta |
Also accepts standard div attributes.
PageHeaderDescription
Optional supporting text under the title row.
| Data attribute | Values |
|---|---|
data-slot | page-header-description |
Also accepts standard p attributes.
PageHeaderActions
Trailing action area for page-level commands.
| Data attribute | Values |
|---|---|
data-slot | page-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 attribute | Values |
|---|---|
data-slot | page-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.
| Prop | Type | Default |
|---|---|---|
expandLabel | string | "Expand section" |
collapseLabel | string | "Collapse section" |
| Data attribute | Values |
|---|---|
data-slot | page-header-expand-trigger |
Also accepts Button props except children.
PageHeaderExpandableContent
Optional collapsible region below the main header row. Uses Radix CollapsibleContent.
| Data attribute | Values |
|---|---|
data-slot | page-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.