Breadcrumbs
Presentational breadcrumb trail showing the path to the current page. The last item is treated as the current page and is not a link.
Preview
<EsaBreadcrumbs items={[
{ label: 'Home', href: '/' },
{ label: 'Projects', href: '/projects' },
{ label: 'Wetland Survey' },
]} /> States
Crumbs accept an optional leading icon (raw inline SVG) on any item — useful for a home glyph.
<EsaBreadcrumbs items={[
{ label: 'Home', href: '/', icon: homeIconSvg },
{ label: 'Compliance', href: '/compliance' },
{ label: 'Permits', href: '/compliance/permits' },
{ label: 'NPDES-2024-118' },
]} /> Sizes
<EsaBreadcrumbs items={items} size="xs" />
<EsaBreadcrumbs items={items} size="sm" />
<EsaBreadcrumbs items={items} size="md" />
<EsaBreadcrumbs items={items} size="lg" /> API
| Prop | Type | Default | Description |
|---|---|---|---|
items | EsaBreadcrumbItem[] | required | Trail of crumbs. Each item is { label; href?; icon? }. The last item is rendered as the current page. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'md' | Type scale of the trail. |
Each EsaBreadcrumbItem is { label: string; href?: string; icon?: string }. Omit href on the final item; icon is a raw inline SVG string.
Accessibility
- Wraps the trail in
<nav aria-label="Breadcrumb">with an ordered<ol>. - The last crumb receives
aria-current="page"and renders as plain text, not a link. - The chevron separator is decorative — marked
aria-hidden="true".
Theming surface
Every public token this component reads, extracted from its source at build time,
split by blast radius: the hooks that belong to this component,
then the shared and system tokens it consumes alongside everything else. The
Resolves to column walks each token's real lineage —
component → semantic → primitive → raw value — so you
can see exactly where re-pointing it lands. A spoke re-skins by overriding these in
its theme-<slug>.css; component internals are never edited. No
hook for what you need? File it with /request-lego.
Type roles it names
This component does not set a size, weight, face or tracking of its own — it names a composite, and the composite carries all five. A composite is a class rather than a token, so none of it appears in the tables below; re-theme text by re-pointing the token family, not by editing the component.
| Role | Re-point | Reach |
|---|---|---|
.typography-body-lg |
| +7 more componentsesa-checkbox, esa-checkbox-group, esa-combobox, esa-input-tag, esa-radio-group, esa-select, esa-textarea |
.typography-body-md |
| +28 more componentsesa-app-shell, esa-card, esa-checkbox, esa-checkbox-group, esa-collapsible, esa-combobox, esa-command-palette, esa-confirm-dialog, esa-container, esa-danger-zone, esa-dialog, esa-dropdown-menu, esa-empty-state, esa-entity-search, esa-form-field, esa-header-nav, esa-input-tag, esa-nav-dropdown, esa-page-header, esa-popover, esa-progress-bar, esa-radio-group, esa-select, esa-side-dialog, esa-snackbar-item, esa-switch-toggle, esa-tab-layout, esa-textarea |
.typography-body-sm |
| +20 more componentsesa-alert-box, esa-button-toggle, esa-card, esa-checkbox-group, esa-combobox, esa-command-palette, esa-date-picker, esa-empty-state, esa-file-upload, esa-form-field, esa-input-tag, esa-link-column, esa-loading-overlay, esa-progress-bar, esa-radio-group, esa-search-panel, esa-select, esa-stat, esa-text-field, esa-textarea |
.typography-body-xs |
| +14 more componentsesa-checkbox, esa-checkbox-group, esa-combobox, esa-command-palette, esa-empty-state, esa-entity-search, esa-field-error, esa-header-nav, esa-input-tag, esa-progress-bar, esa-radio-group, esa-search-panel, esa-select, esa-textarea |
.typography-label-lg |
| +12 more componentsesa-button-toggle, esa-checkbox-group, esa-color-picker, esa-combobox, esa-date-picker, esa-form-field, esa-input-tag, esa-radio-group, esa-range-slider, esa-select, esa-text-field, esa-textarea |
.typography-label-md |
| +33 more componentsesa-app-bar, esa-button-group, esa-button-toggle, esa-card, esa-checkbox-group, esa-color-picker, esa-combobox, esa-command-palette, esa-confirm-dialog, esa-danger-zone, esa-date-picker, esa-dialog, esa-empty-state, esa-entity-search, esa-file-upload, esa-filter-container, esa-form-field, esa-header-nav, esa-input-tag, esa-link-column, esa-page-header, esa-pillbox, esa-popover, esa-progress-bar, esa-radio-group, esa-range-slider, esa-select, esa-side-dialog, esa-sidebar-nav, esa-stat, esa-text-field, esa-textarea, esa-tooltip |
.typography-label-sm |
| +3 more componentsesa-progress-bar, esa-search-panel, esa-sidebar-nav |
.typography-label-xs |
| +14 more componentsesa-button-toggle, esa-checkbox-group, esa-color-picker, esa-combobox, esa-date-picker, esa-entity-search, esa-form-field, esa-input-tag, esa-progress-bar, esa-radio-group, esa-range-slider, esa-select, esa-text-field, esa-textarea |
Wired to this component
No other component reads these — re-point them and esa-breadcrumbs is the
only thing that moves.
| Token | Tier | Resolves to |
|---|---|---|
--breadcrumbs-bg | component | transparent |
--breadcrumbs-link-color | component | #646464 via --color-content-default-secondary → --color-gray-11 |
--breadcrumbs-link-hover | component | #202020 via --color-content-default → --color-gray-12 |
Shared tokens it reads
Owned by a family or by the semantic layer. Still overridable — but scope the
override (esa-foo { --form-border-color: … }) unless you mean to move
everything that reads it. Reach says what else that is.
| Token | Reach | Resolves to |
|---|---|---|
--color-border-default-strong | semantic every component | #bbbbbb via --color-gray-8 |
--color-content-default | semantic every component | #202020 via --color-gray-12 |
--spacing-100 | primitive every component | 0.25rem |
--spacing-200 | primitive every component | 0.5rem |