When to use it
Every screen inside the app shell uses Page. It is not optional; it provides the consistent title, navigation, and layout frame users expect on every screen.
Use when:
- You are designing any screen in the main content area of the app
- The screen has a title, optional tabs, and page-level actions
- Content needs to scroll within the standard app chrome
Don't use when:
- You are designing a modal, drawer, or overlay; those are separate surfaces
- You are embedding Page inside another Page; pages do not nest
- The screen lives outside the app shell entirely (e.g. onboarding, login)
Structure
Page has two top-level regions. What you place in each depends on the layout you choose.
|
Region |
Role |
Required? |
Notes |
|---|---|---|---|
|
Header |
Title, optional tabs, optional actions, optional alert and promo rows |
Yes |
Always renders except in subpage / noHeader mode, where it collapses and the title moves to the topbar breadcrumb |
|
Content area |
The screen's main content |
Yes |
Shape of content depends on layout; see Layouts below |
Header slots
|
Slot |
What it holds |
Notes |
|---|---|---|
|
Title |
The screen's H1 |
Always required |
|
Pill |
Status badge or count beside the title |
Optional; use only for contextual status about the whole screen, not for decoration |
|
Tabs |
Parallel views of the same content |
Optional; see Tabs section below |
|
Actions |
Page-level buttons |
Optional; typically a primary + secondary pair |
|
Alert |
A banner for time-sensitive messages or page-scope errors |
Optional; renders below tabs at wide viewports, below stacked tabs at narrow |
|
Promo |
An upsell or contextual announcement |
Optional; renders below the alert row; don't show both simultaneously without a strong reason |
Layouts
Layout controls how wide the content gets and how the screen scrolls.
Columns (default)
Content centers in a capped, readable column. The full page scrolls. Right choice for most screens.
Use when:
- The screen contains readable text, forms, or cards users scan top to bottom
- The screen is a dashboard, settings page, or any content-driven page
- You are composing content from stacked Page.Card blocks
Common mistake: Choosing full layout because it "fills the screen." A centered column reduces line length and makes content easier to scan; don't override it without a clear reason.
Full
Content spans edge to edge inside the content frame. The page scrolls until the header disappears; then the content frame scrolls internally.
Use when:
- The screen contains a data table, shift grid, calendar, or any view where cutting off horizontal space loses meaning
- The screen needs a sticky toolbar that persists while users scroll the content below it
Full, no header
The content frame fills the viewport immediately; the page itself does not scroll. The title moves into the topbar breadcrumb.
Use when:
- Content inside the frame needs to own its own scroll from the first pixel (e.g. Shifts schedule grid)
- The title is already conveyed by the breadcrumb chain
Subpage
Shorthand for the full-with-no-header layout used on detail or drilldown screens. The title is replaced entirely by a breadcrumb chain in the topbar.
Use when:
- The screen is a detail view reached by drilling into a list (e.g. a single employee's record, a specific timesheet)
- You need to show the path back to the parent screen in the topbar
Every subpage requires a breadcrumb. Without one, users lose their location entirely; the topbar is the only place context appears in this mode.
Mixed-layout tabs
A tab can switch the page between columns and full layout. The layout transitions on tab swap.
Use when:
- One tab needs a data-dense full-width view (e.g. a schedule grid) while its siblings are content-column pages
Composing the content area
Columns layout: Page.Main, Page.Aside, and Page.Card
Stack Page.Card blocks inside Page.Main to build the content column.
Add Page.Aside alongside Page.Main when the screen has supporting content. The pair forms a two-column layout (main takes roughly two-thirds, aside one-third) on wide screens and stacks on narrow.
Page.Aside is for supporting content only: summary stats, related metadata, contextual shortcuts. If the content is required for the primary task, it belongs in the main column. Aside content is visually secondary and is frequently missed when it carries critical information.
Page.Card groups related content into discrete sections. Each card is a bordered, padded block with an optional title and subtitle. Stack multiple cards when a screen has distinct information clusters users need to scan independently. Don't split a single coherent section across multiple cards just to add visual weight.
Full layout: place content directly
Pass content directly as Page children; no Page.Main or Page.Card wrapper. The content manages its own internal padding and layout.
Toolbar
A sticky toolbar sits at the top of the content frame and stays visible while users scroll content below it.
Use a toolbar when:
- Users need persistent access to filters, scope selectors, or bulk-action controls while scrolling a long list or grid
- The screen is a data-dense full-width view (timesheets, schedule, reporting)
Don't use a toolbar when:
- The screen is a content or settings page; page-level actions belong in the header
- The toolbar would duplicate actions already in the header; don't show the same action in two places
Page.Toolbar has five zones. Compose them left to right:
|
Zone |
What goes here |
Examples |
|---|---|---|
|
Back |
Back button for stepper flows |
Back button |
|
Filters |
Controls that narrow the dataset |
Filter chips, search field |
|
Scope |
What the page is currently viewing |
Date range stepper, person selector, location picker |
|
View options |
Presentation changes |
Column toggle, density control |
|
Actions |
Operations on the content |
Publish, export, add new |
Right rail (side panel)
A side panel opens on the right side of the content frame. When open, the main content and panel share the frame side by side.
Use the side panel when:
- A selected record needs detail displayed alongside the list without navigating away
- The detail is substantial enough to need its own panel but not complex enough to warrant a full drilldown page
Don't use the side panel as a catch-all detail view. If the detail requires its own tabs, multiple sections, or its own primary actions, use a subpage instead.
Design both the closed and open states. The main content column changes width when the panel opens; a layout that only accounts for one state will break in the other.
Tabs
Tabs divide a page into parallel views of the same content type.
Use tabs when:
- A screen shows the same kind of content filtered multiple ways (e.g. All shifts / Open shifts / My shifts)
- The user switches frequently between views without leaving the page
Don't use tabs when:
- The sections contain fundamentally different types of content; use separate pages instead
- There are so many tabs they can't be scanned at a glance; consider a different navigation strategy
- The user needs to compare content across sections simultaneously; tabs hide what they don't show
What to design for
|
Scenario |
What the user sees |
Design consideration |
|---|---|---|
|
No content / first use |
Empty content area |
Design an empty state with a clear first action; don't leave a blank card |
|
Alert or promo banner present |
A row in the header below the tab bar |
Design both the presence and absence states; many users will never see a banner |
|
Alert and promo simultaneously |
Two stacked banner rows above the content |
Use sparingly; two banners add significant vertical offset before users reach any content |
|
Side panel open |
Content frame splits into main + panel columns |
Design both states; the main column must still be functional when the panel is open |
|
Tab disabled |
Tab label muted, non-interactive |
Only disable when the reason is obvious or explained nearby |
|
Subpage (no inline header) |
Topbar shows breadcrumb chain, no in-page title |
Supply a complete breadcrumb; every parent item links back; the last item (current screen) has no link |
Usage guidelines
Do
|
Guideline |
Why |
|---|---|
|
Use columns layout by default; switch to full only when horizontal space is genuinely required |
Column layout keeps content readable; full layout used without a reason creates unnecessary visual sprawl |
|
Supply a breadcrumb on every subpage |
Without one the topbar shows nothing and users lose their location in the app hierarchy |
|
Put the one primary action in the page header |
Users look to the top right for the most important action; distributing primary actions across the page creates confusion about what to do next |
|
Add a sticky toolbar only when its controls are used while scrolling |
A toolbar that doesn't earn its vertical real estate adds friction to every scroll interaction |
|
Label tabs as the thing, not the action; "Open shifts" not "View open shifts" |
Tab labels are scanned in context of the page title; the verb adds no meaning |
|
Design both the closed and open states when using a side panel |
The main content column changes width when the panel opens; layouts that only account for one state break in the other |
Don't
|
Guideline |
Why |
|---|---|
|
Don't use tabs for content types that belong on separate pages |
Tabs imply parallel views of the same thing; mixing fundamentally different content types confuses the mental model |
|
Don't place content required for the primary task in Page.Aside |
Aside is visually secondary; critical content placed there is frequently missed |
|
Don't stack multiple Page instances |
Pages don't nest; embedding one inside another breaks scroll, topbar, and breadcrumb behavior |
|
Don't duplicate page header actions in the toolbar |
Each action should have one clear location; showing it in two places creates uncertainty about which one to use |
|
Don't use full-with-no-header on a standalone content or settings page |
This mode is for views with a persistent self-scrolling frame (like a schedule grid); using it on a settings page removes the title from the screen entirely |
|
Don't show an alert and promo banner together unless both are genuinely urgent |
Two stacked banners before the content adds significant vertical offset and trains users to ignore both |
Content guidelines
|
Element |
Rule |
Example |
|---|---|---|
|
Page title |
Sentence case; noun or noun phrase; as short as possible; names the screen's subject |
"Shifts", "Pay periods", "Taylor's schedule" |
|
Tab labels |
Short noun phrases; sentence case; parallel structure across sibling tabs |
"All", "Open", "My shifts" |
|
Action labels |
Verb + noun; sentence case; specific to the action |
"Publish schedule", "Add employee" |
|
Card title |
Sentence case; describes the card's content group |
"This week", "Labor summary" |
|
Card subtitle |
Optional; one supporting sentence |
"Compared to the same period last week" |
|
Breadcrumb items |
Match the parent screen's title exactly; last item is the current screen (no link) |
"Shifts > Taylor Emmerson" |
Common copy mistakes:
- Don't: "Manage your team" as a page title; describes what the user does, not what the screen is
- Do: "Team"; names the object type; the user infers the management affordance from the actions
- Don't: "View all employees" as a tab label; the page title carries the noun; the verb adds nothing
- Do: "All"
Accessibility responsibilities
|
What to ensure |
Why it matters |
|---|---|
|
The page title is the most prominent heading on the screen; it renders as an H1 |
Screen reader users navigate by headings; the H1 tells them where they are |
|
Card titles render as H3; don't skip heading levels between the page H1 and card H3 |
Heading levels communicate hierarchy; a gap breaks that signal for screen reader users |
|
Every breadcrumb item representing a parent screen must be a link, not static text |
Keyboard users navigating a subpage need a way back without relying on the browser's back button |
|
The active tab is distinguishable from inactive tabs without relying on color alone |
Users with low vision or color blindness need a shape or position cue, not just a highlight color |
|
Disabled tabs must have a visible reason for being disabled, or the reason must be nearby |
A disabled control with no explanation is a dead end |
|
When the side panel opens, focus moves to the panel automatically |
Keyboard and screen reader users need to know the panel has appeared; silent DOM insertion is disorienting |
|
Annotate page title and tab labels in handoff |
Correct semantic markup (H1, nav, aria-selected) depends on these annotations being explicit in the handoff |
Related components
|
|
Component |
When to choose it |
|---|---|---|
|
Instead of Page.Card |
Section divider + spacing |
When content sections don't need visual card boundaries, e.g. a form page where sections are separated by headings and whitespace |
|
Instead of Page tabs |
Sidebar navigation |
When sections are truly separate destinations (different URLs, different mental models) rather than parallel views of the same object |
|
Instead of Page.Aside |
Subpage (subpage mode) |
When the detail view requires its own tabs, multiple sections, or its own primary actions |
|
Often used with |
Page.Toolbar |
On any full-layout screen that needs persistent filter or action controls |
|
Often used with |
AppLayout |
Page is always a child of AppLayout in production; the topbar breadcrumb and scroll-away header depend on this relationship |