ComponentsLayout

Page Header

The title, description, and main actions at the top of a page. Inside an app shell it moves its title and actions into the shared header bar.

Back to projects

Spring launch

Shared space for the launch team's chats, files, and instructions.

Usage

Page header usageTSX
import { PageHeader } from "@tulipfarm/sprout/page-header";

<PageHeader
  title="Files"
  description="Find, open, and organize workspace files."
  actions={<>
    <Button><Upload aria-hidden="true" />Upload</Button>
    <Button variant="outline"><FolderAdd aria-hidden="true" />New folder</Button>
  </>}
/>

title renders the page's only h1. The description sits under it. The actions sit at the end of the row and wrap under the title when space runs out. Long titles wrap; they never overflow.

Title and description

Usage

Credits, and where they go. Split by model, agent, or activity.

Primary action

Workflows

See how repeatable work runs. Create and edit workflows in chat.

Disabled action

Chats

Shared with everyone in Spring launch. Most recently active first.

Icon actions

Files

Find, open, and organize workspace files. Sharing a file never changes who owns it.

Linked actions

Agents

Private instructions you can share with people and teams.

Small link action

Workflows

Calendar actions

Calendar

File with busy action

Q3 customer retention analysis – board review copy (final).xlsx

2.4 MB · Owned by you

Back link
Back to skills

Import skill

Back link with description and action
Back to agents

New agent

Give it a role. Choose its access. Review before it starts.

Back link with status
Back to agents

Weekly pipeline digest

Start tasks with this agent. Managers set up how it runs and who can use it.

Active
Back link with ghost action
Back to projects

Spring launch

Parent breadcrumb
Back, parent, and page actions
Back to examples

Back link and breadcrumb

NavigationTSX
<PageHeader
  title="Customer accounts"
  parent={{ label: "Tables", link: <Link to="/tables" /> }}
/>

<PageHeader
  title="Import skill"
  back={{ label: "Back to skills", link: <Link to="/skills" /> }}
/>

back adds a small ghost link above the title. Below 640px only its chevron shows; the label stays its accessible name. A parent shows the title as the last step of a breadcrumb. Both take your router's link element, so links stay real links.

Moving focus to the title

Set focusable to let code focus the heading, for example after a route change or after an action removes the focused control. Use titleRef to reach it and titleId to label a region with it.

Focusable title

Skills

Reusable procedures. Skills never grant tools or permissions.

App header

Provide header slotsTSX
const [title, setTitle] = useState<HTMLDivElement | null>(null);
const [actions, setActions] = useState<HTMLDivElement | null>(null);
const chrome = useMemo(
  () => ({ title, actions, documentTitle: (page) => `${page} · Northwind` }),
  [title, actions],
);

<header>
  <SidebarTrigger />
  <div ref={setTitle} className="flex min-w-0 flex-1 items-center gap-2" />
  <div ref={setActions} className="flex shrink-0 items-center gap-2" />
</header>
<PageChromeContext value={chrome}>
  <Outlet />
</PageChromeContext>

When PageChromeContext has both elements, the back link and title move into the header bar at 14px and truncate on one line. Actions move beside them. The description stays in the page. Pages without a header use PageActions to place actions there, or right-aligned in the page when there is no header bar.

documentTitle is optional. When set, a string title also updates the browser tab and restores it when the page leaves.

Northwind

Accessibility

The title is an h1. The breadcrumb is a nav named “Breadcrumb”, its last step marked aria-current="page", and its chevrons are hidden from assistive technology. A focusable title shows a focus ring only for keyboard focus. Link colors change over 120ms; reduced motion turns this off. Routing, dialogs, and menus in these examples are sample code.