Page and PageHeader
The shell of a page and its header row - the title, a description, what sits beside the title, and the page's actions.
Page is the outer layer of the content of one route: it adds the page's padding and an equal
space between its blocks. Page is the first block: the page title as <h1>, a description,
something beside the title such as a badge, and the actions that belong to the whole page.
Participants
1,284Everyone in the scheme, active and deferred.
// apps/docs/examples/ui/page.tsx'use client';
import {PlusIcon} from 'lucide-react';
import {Page} from '@workspace/active-ui/components/composed/page';import {PageHeader} from '@workspace/active-ui/components/composed/page-header';import {Badge} from '@workspace/active-ui/components/primitives/badge';import {Button} from '@workspace/active-ui/components/primitives/button';
/** * The shell of a page with its header row: the title as `<h1>`, a badge * beside it, a description, and the page's actions, which move below the * heading on narrow screens. The page is fictitious and its buttons do * nothing. */export default function PageExample() { return ( <div className="w-full rounded-md border"> <Page> <PageHeader title="Participants" description="Everyone in the scheme, active and deferred." suffix={<Badge variant="secondary">1,284</Badge>} actions={ <> <Button variant="outline" size="sm"> Export </Button> <Button size="sm"> <PlusIcon aria-hidden /> Add a participant </Button> </> } /> <div className="text-muted-foreground rounded-md border border-dashed p-6 text-center text-sm"> The page content: a table, a form, cards. </div> </Page> </div> );}What the composition adds#
One rhythm.
Pagesetsspace-between blocks andy- 6 px-around them, so the header owns no outer margin and every step on the page is the same.2 py- 6 A header that adapts. Below the
smwidth the actions sit under the heading, fromsmon to its right; they wrap when they do not fit.Fixed sizes.
size="default"(text-title) for an application with a sidebar,3xl size="compact"(text-) for a mobile-first environment.2xl
Page sets no width: a block that needs one, such as a form, sets it on itself. The header has no
breadcrumbs, tabs or filters; tabs go below it as a sibling.
Usage#
import {Page} from '@workspace/active-ui/components/composed/page';import {PageHeader} from '@workspace/active-ui/components/composed/page-header';
<Page> <PageHeader title="Participants" description="Everyone in the scheme." actions={<Button size="sm">Add a participant</Button>} /> …</Page>;What your application provides#
The title and description, translated; the title is a plain string, so its accessible name stays predictable.
The actions, and the decision which ones the reader may use, for example with GuardedAction.
The width of the content blocks, and the outer padding of the route layout.
Accessibility#
The title is the page's only
<h1>. The example on this page adds a second<h1>to this documentation page; in an application there is one.The actions follow the heading in reading and tab order.
API#
Page#
Import from @workspace/
Props
- Type
ReactNode
The complete page content, in reading order. Usually a import('./ followed by the actual content, but a import('./ is not required: a page without a visible heading is a valid page.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Types
The props of Page, each described in its prop list on this page.
interface PageProps extends React.ComponentProps<'div'> {
children: React.ReactNode;
}PageHeader#
PageHeader
Props
- Type
string
The page title, as <h1>. Translated text; this component does not translate.
Deliberately a string and not a React: markup inside a heading makes the accessible name unpredictable. What belongs next to the title belongs in Page.
- Type
ReactNode
The actions that belong to the page as a whole: "New X", an export button, an administration or date picker.
From sm up they sit to the right of the heading, below that underneath it. Multiple actions go in as separate siblings (or in a fragment); the order stays with the caller.
Deliberately no overflow or collapse mechanism: the actions wrap onto a next line when they do not fit. Keep the row to one or two actions.
- Type
string
The line below the title. Optional: a page that explains itself through its title gets no second line. When omitted, no empty element is rendered.
- Type
PageHeader Size - Default
'default'
Typographic size. Default: "default".
- Type
ReactNode
Content directly next to the title, on the same line: a status badge, a help button, a small metadata marker.
Deliberately a free React and not a status or help prop: mapping a domain value to a tone belongs to the caller, the same boundary as with Status and Guarded.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Types
- Type
type PageHeader Size = 'default' | 'compact';
The typographic size of the header row.
"default"— for an application with a fixed sidebar on wide screens. Title attext-.3xl "compact"— for a mobile-first environment, where atext-title wraps over two or three lines on a phone. Title at3xl text-, description one size smaller.2xl
There is deliberately no third size and no free title.
The props of Page, each described in its prop list on this page.
interface PageHeaderProps extends Omit<
React.ComponentProps<'div'>,
'title'
> {
title: string;
description?: string;
suffix?: React.ReactNode;
actions?: React.ReactNode;
size?: PageHeaderSize;
}