UpNext / Page Header

Page Header

<PageHeader />New

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

import { PageHeader } from "@/components/upnext";

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

<PageHeader
title="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";
<PageHeader
title="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 aligns
while the divider still spans the full width. */}
<PageHeader
title="Recruits"
icon="user.group"
divider
className="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.