UpNext / Page Header
Page Header
<PageHeader />NewA fixed 44px title bar for the top of a page or a major panel. A leading semantic icon and the heading sit on the left; call-to-action buttons sit on the right and vary — or disappear — per page. Declare the CTAs with the actions array and every button renders through the Button primitive, or drop in anything custom via children. Built entirely from UpNext Icon and Button primitives and semantic tokens — no raw color, font, or one-off pixel value.
Variant explorer
Change the leading icon, the trailing action set, and the divider. The 44px height is fixed: the heading truncates and the actions reflow rather than growing the row.
Cross the leading icon, the trailing action set, and the optional divider. The bar keeps its 44px height in every combination — the heading truncates and the actions reflow rather than growing the row.
Leading icon
Actions
Divider
Recruits
<PageHeadertitle="Recruits"icon="user.group"actions={[{ key: "filter", label: "Filter", icon: "action.filter", variant: "ghost" },{ key: "add", label: "Add recruit", icon: "action.add", variant: "primary" },]}/>
Inspector
Edit one prop at a time and see the token chain resolve. The preview re-renders, the code panel updates, and the resolves-to column shows every Tailwind class → CSS variable → final value.
Preview
Recruits
Code
import { PageHeader } from "@/components/upnext";<PageHeadertitle="Recruits"icon="user.group"actions={[{"key":"filter","label":"Filter","icon":"action.filter","variant":"ghost"},{"key":"add","label":"Add recruit","icon":"action.add","variant":"primary"}]}/>
Patterns
From a bare title to a full toolbar. Actions are declarative and data-driven, so a page passes a different array — or none — and the bar reflows. Icon-only actions (the overflow example) require an aria-label. Need something the array cannot express? The children escape hatch accepts any node, rendered after the declarative actions.
Roster
<PageHeader title="Roster" icon="user.group" />
Composition
The header owns its 44px row; the parent owns the surrounding surface and content. Give the header the same horizontal padding as the body (here px-4) so its content lines up with the content below while the divider still spans the full width. Keep the heading level honest to the outline — headingLevel defaults to 1 and should be lowered when the bar nests under an existing heading.
Recruits
- Marcus BradleyRB · 6′2″
- Avery WilliamsWR · 5′11″
- Riley SandersQB · 6′3″
<div className="overflow-hidden rounded-xl border border-border bg-card">{/* Give the header the body's horizontal padding (px-4) so content alignswhile the divider still spans the full width. */}<PageHeadertitle="Recruits"icon="user.group"dividerclassName="px-4"actions={[{ key: "filter", label: "Filter", icon: "action.filter", variant: "ghost" },{ key: "add", label: "Add recruit", icon: "action.add", variant: "primary" },]}/><ul className="px-4 py-1.5">{/* roster rows */}</ul></div>
Source
The component composes the public Icon and Button primitives with semantic text, border, and icon-tone tokens. Actions are a typed PageHeaderAction[] so button treatment stays consistent; the meta documents every prop, its control, generated JSX, and token resolution.