The first thing on a view: a title with an optional eyebrow, status tag and meta line, actions on the trailing side, a breadcrumb above and a tab row below. Use it once per screen, over a list, a record or a settings form, so every page opens the same way and can take focus after a view change.
The project page. heading is the title, tag sits beside it, meta under it. Secondary actions go in actions and the one accent action in primary, last, at the end of the row. tabs holds a sui-tabs whose sui-tab children are empty; the page draws the panel under the header and switches it on suiChange.
// setup(root): properties and events
setup(root) {
const panel = root.querySelector('#ph-panel');
const copy = ['Summary, milestones and the latest update.', 'Twelve open tasks, grouped by status.', 'Three project updates, newest first.'];
root.querySelector('#ph-tabs').addEventListener('suiActiveChange', (e) => { panel.textContent = copy[e.detail] || ''; });
}
Breadcrumb, back link and eyebrow
breadcrumb sits above the title and back draws an arrow named Back before it, for a record reached from a list; its click emits a cancelable suiBack first, so a host that navigates in memory can preventDefault. eyebrow is a short uppercase label over the title. heading-level changes the element only, not the size.
LRK-142Opened Aug 28 by Tom Gordon. Due Sep 12.Back goes to the task list here; the click is intercepted below.
<sui-page-header id="ph-record" heading="Raise the gateway quota" heading-level="2" back="#/tasks">
<sui-breadcrumb slot="breadcrumb" id="ph-crumbs"></sui-breadcrumb>
<span slot="eyebrow">LRK-142</span>
<sui-tag slot="tag" label="In review" severity="info" size="sm"></sui-tag>
<span slot="meta">Opened Aug 28 by Tom Gordon. Due Sep 12.</span>
<sui-copy-button slot="actions" value="https://larkspur.example/tasks/142" label="Copy link" copied-label="Copied" variant="outline"></sui-copy-button>
<sui-button slot="primary" variant="accent" icon="fa-regular fa-circle-check" label="Mark done"></sui-button>
</sui-page-header>
<span id="ph-record-log" style="display:block;margin-top:12px;font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Back goes to the task list here; the click is intercepted below.</span>
// setup(root): properties and events
setup(root) {
root.querySelector('#ph-crumbs').items = [
{ label: 'Tasks', href: '#/tasks' },
{ label: 'LRK-142' },
];
const log = root.querySelector('#ph-record-log');
root.querySelector('#ph-record').addEventListener('suiBack', (e) => { e.preventDefault(); log.textContent = 'suiBack was vetoed, so the page stayed put.'; });
root.querySelector('#ph-crumbs').addEventListener('click', (e) => { if (e.target.closest('a')) { e.preventDefault(); log.textContent = 'The breadcrumb link was intercepted the same way.'; } });
}
A title that is markup
Leave heading unset and fill the default slot when the title is more than text: here a sui-inplace, which takes the title font from the header, so the record renames in place at the page size. meta takes nodes as well as text.
LRK-142opened this Aug 28
<sui-page-header>
<span slot="eyebrow">LRK-142</span>
<sui-inplace value="Raise the gateway quota" placeholder="Untitled task" aria-label="Task title"></sui-inplace>
<sui-persona slot="meta" name="Tom Gordon" size="xs" weight="medium"></sui-persona>
<span slot="meta">opened this Aug 28</span>
<sui-icon-button slot="actions" variant="outline" icon="fa-solid fa-ellipsis" aria-label="More"></sui-icon-button>
</sui-page-header>
Narrow columns
Below 680px of its own width the header stacks: the actions drop under the title and align to the start. It measures the element, not the viewport, so a header inside a pane or a dialog stacks when the pane is narrow.
The title carries tabindex="-1", so it never sits in the tab order but can take focus. Call setFocus() after a view change and a screen reader announces the new page from its heading; the ring shows only for keyboard focus.
Four unread.
Press the button, or Tab to it and press Enter.
<div style="display:flex;flex-direction:column;gap:14px">
<sui-page-header id="ph-focus" heading="Inbox">
<span slot="meta">Four unread.</span>
</sui-page-header>
<div style="display:flex;align-items:center;gap:12px">
<sui-button id="ph-focus-btn" variant="outline" label="Focus the title"></sui-button>
<span id="ph-focus-log" style="font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Press the button, or Tab to it and press Enter.</span>
</div>
</div>
// setup(root): properties and events
setup(root) {
const head = root.querySelector('#ph-focus');
const log = root.querySelector('#ph-focus-log');
root.querySelector('#ph-focus-btn').addEventListener('click', async () => {
await head.setFocus();
log.textContent = document.activeElement && document.activeElement.classList.contains('title') ? 'The title has focus.' : 'Focus did not move.';
});
}
Keyboard
Key
Action
Tab
Moves through the back link when back is set, then the controls in the breadcrumb, actions, primary and tabs slots in document order. The title carries tabindex="-1", so it is never a tab stop.
Enter
On the back link, emits a cancelable suiBack and follows the href unless a listener cancels it.
setFocus()
Not a key: the method moves focus to the title so a screen reader announces the new page, and the ring shows only for keyboard focus.
API
<sui-page-header>
Properties
Property
Attribute
Type
Default
Description
back
back
stringstring | undefined
Href of a back control drawn before the title, for a record reached from a list.
heading
heading
stringstring | undefined
Title text, the string form. For markup, leave it unset and fill the default slot.
headingLevel
heading-level
SuiPageHeaderLevel1 | 2 | 3
1
Heading level of the title element, 1 to 3. The size does not change with it.
Events
Event
Detail
React
Vue
Description
suiBack
void
onSuiBack
@sui-back
Fires when the back control is clicked, before the browser follows back. Cancelable: preventDefault() keeps the page where it is, for a host that navigates in memory.
Methods
Method
Signature
Description
setFocus()
setFocus() => Promise<void>
Moves focus to the title, for a host that moves focus after a view change. It does not scroll: the header is the first thing in its view, and a frame embedded in a longer page must not drag that page to itself.
Slots
Slot
Description
(default)
The title as markup, an inplace editor or text with a glyph. Leave heading unset.
actions
Secondary actions on the trailing side, before the primary one.
breadcrumb
A sui-breadcrumb above the title.
eyebrow
Short uppercase label above the title: a record id, a section name.
meta
One line under the title: text, or nodes such as a persona and a date.
primary
The one accent action, last on the trailing side.
tabs
A tab row flush with the header's bottom edge, drawn over the header's own rule. Give it a sui-tabs whose sui-tab children are empty and draw the panels under the header.
tag
Status beside the title, typically a small sui-tag.
Types
SuiPageHeaderLeveltypeHeading level of the title: 1 on a page, 2 or 3 inside a region that already has one.
No members.
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.