Prototype Library

Page Header

The standard prototype page top: optional breadcrumbs OR an eyebrow (with a leading icon), a title (page-title role, or the oversized display role for a hero), and a right-aligned actions slot.

Inherited .astro import EsaPageHeader from '@esa/ecology/esa-page-header.astro';

Preview

The default form: a page-title-scale heading with an actions slot. The container is neutral and transparent — color is the consumer’s job.

Requirements

<PageHeader title="Requirements">
  <EsaButton slot="actions" variant="primary" icon="plus">New requirement</EsaButton>
</PageHeader>

There is no description slot

This component takes no lede, subtitle, or description. A page header carries the page’s name and its actions; a sentence explaining the page to its reader is text about the page rather than of it, and the page’s own data and structure are what say what it is.

Every real fill of the former lede prop was that kind of sentence, which is why it was removed on 2026-08-16. If a page genuinely needs a number or a date up top, that is a datum — put it in the eyebrow, or in an esa-stat below the header where it can be read as data.

Eyebrow + display prominence (hero)

For a landing or hero, add an eyebrow (with an optional leading icon) and bump the title to the display role with prominence="display". The actions here are link-buttons — esa-button with an href.

Annual Report

2026 in Review

<PageHeader
  eyebrow="Annual Report"
  icon="award"
  prominence="display"
  title="2026 in Review">
  <EsaButton slot="actions" variant="primary" href="/report">Read the report</EsaButton>
  <EsaButton slot="actions" variant="ghost" appearance="outline" href="/data">View the data</EsaButton>
</PageHeader>

Host an esa-breadcrumbs in the breadcrumbs slot for a record or nested page.

Filed 12 days ago

Permit #4471

<PageHeader title="Permit #4471" eyebrow="Filed 12 days ago">
  <nav slot="breadcrumbs">Permits / Active / #4471</nav>
  <EsaButton slot="actions" variant="ghost" appearance="outline" icon="pencil">Edit</EsaButton>
</PageHeader>

API

PropTypeDefaultDescription
title string required The page’s name, as it appears in navigation and breadcrumbs (required). Rendered as the <h1>.
pairs [{ label: 'Project', value: 'Delta Conveyance Project' }]. Renders required
meta EsaMetaPair[] — Identifying facts about the record this page shows, as {label, value} pairs: [{ label: 'Project', value: 'Delta Conveyance Project' }]. Renders as a definition list under the title. A period pair states its calendar ("Calendar Q2 2026", "Water year 2026"), since a bare quarter means a different span under each.
eyebrow string — The named thing this page sits inside — a section, a report, a person, a record id. A proper noun or a short label, never a sentence.
icon string — esa-icon registry name for the eyebrow’s leading glyph, e.g. "award" (eyebrow only).
prominence 'page-title' | 'display' 'page-title' Title scale: the page-title role (default) or the oversized display role for a hero.
as 'header' | 'div' | 'section' 'header' The host element tag.

Slots

PropTypeDefaultDescription
breadcrumbs slot — Above the title — host an esa-breadcrumbs here. Mutually exclusive in spirit with eyebrow.
actions slot — Right-aligned, top-aligned with the title block — buttons or links.

Accessibility

  • The title is the page <h1> — there should be exactly one per page; keep heading order sensible below it.
  • The host defaults to a <header> landmark; use as="div" when the header is nested inside another landmark.
  • The eyebrow icon is decorative (rendered via esa-icon, aria-hidden) — the eyebrow text carries the meaning.