A path trail showing where the current page sits in the site hierarchy.

Last updated

Uses JavaScript

With maxVisible, the “…” button reveals the collapsed items and moves focus to the first of them.

Without JS: Every item renders and the … button is hidden, so nothing is unreachable.

Show code
<Breadcrumbs items={[
{ label: 'Home', href: '/' },
{ label: 'Products', href: '/products' },
{ label: 'Apogee' },
]} />

Add

npx @ava-ui/apogee add breadcrumbs

No Apogee dependencies. Uses @lucide/astro for the chevron separator.

Usage

---
import Breadcrumbs from '@/components/apogee/Breadcrumbs/Breadcrumbs.astro'
---
<Breadcrumbs items={[
  { label: 'Home', href: '/' },
  { label: 'Settings' },
]} />

API

@composable — exposed to Content Editors in AVA. Any other native <nav> attribute passes through.

Prop Type Default Description
items { label: string; href?: string; icon?; ariaLabel? }[] — The trail, in order. An item without href (or the last item) renders as plain text. icon is a Lucide component shown before the label; with an empty label the crumb is icon-only and needs ariaLabel.
items[].disabled boolean false Renders the item as plain text with aria-disabled.
maxVisible number — Show at most this many items: the first, an “…” button that reveals the rest, and the last ones.
expandLabel string 'Show all' Accessible name of the “…” button (localise it).
variant 'text' | 'button' | 'line' 'text' Plain links, small button-like crumbs with the current one filled, or the trail between two rules.
class string — Extra classes on the root <nav>, merged last.

Slot separator replaces the chevron between crumbs.

The last item in items is always treated as the current page: it renders as a <span aria-current="page">, even if it has an href.

Collapsed, separator and disabled

Show code
<Breadcrumbs maxVisible={4} items={[{ label: 'Home', href: '/' }, { label: 'Library', href: '#' }, { label: 'Shelf', href: '#' }, { label: 'Series', href: '#' }, { label: 'Volume', href: '#' }, { label: 'Chapter' }]} />
<Breadcrumbs items={[…]}><span slot="separator">/</span></Breadcrumbs>
<Breadcrumbs items={[{ label: 'Home', href: '/' }, { label: 'Archive', disabled: true }, { label: 'Entry' }]} />

Variants and icons

Show code
<Breadcrumbs variant="button" items={[…]} />
<Breadcrumbs variant="line" items={[…]} />
<Breadcrumbs items={[{ label: '', ariaLabel: 'Home', icon: Home, href: '/' }, { label: 'Projects', icon: Folder, href: '#' }, { label: 'Spring launch' }]} />

States

  • Hover / focus — linked crumbs (all but the last, when href is set) go from faded to full neutral on hover (button also fills); keyboard focus shows a visible ring (--outline-color-focus).
  • Current page — the last item is bold text, never a link, with aria-current="page".
Show code
<Breadcrumbs items={[
{ label: 'Home', href: '/' },
{ label: 'Current page' },
]} />

Examples

A deep trail wraps instead of overflowing:

Show code
<Breadcrumbs items={[
{ label: 'Home', href: '/' },
{ label: 'Products', href: '/products' },
{ label: 'Design systems', href: '/products/design-systems' },
{ label: 'Apogee', href: '/products/design-systems/apogee' },
{ label: 'Components' },
]} />

A single-item trail (just the current page, no links):

Show code
<Breadcrumbs items={[{ label: 'Dashboard' }]} />

Account switcher

A workspace switcher before the trail: a Dropdown whose anchor shows the current account, with radio items.

Show code
<div class="flex items-center gap-2">
<Dropdown id="acct" label="Switch workspace">
  <Button slot="anchor" popovertarget="acct" aria-haspopup="menu" variant="ghost" color="neutral" size="small">
    <Avatar name="Larkspur" size="xsmall" />Larkspur<ChevronsUpDown slot="end" class="size-3.5" />
  </Button>
  <DropdownItem indicator="radio" selected>Larkspur</DropdownItem>
  <DropdownItem indicator="radio">Fernhill</DropdownItem>
</Dropdown>
<span aria-hidden="true">/</span>
<Breadcrumbs items={[…]} />
</div>

Accessibility

Key Action
Tab Moves through the linked crumbs and the “…” button in order.
Enter Follows the focused link, or expands the “…” button.
Space Expands the hidden crumbs when the “…” button has focus.
  • Wrapped in <nav aria-label="Breadcrumb"> so assistive tech can jump to it as a landmark.
  • The trail is a real <ol> — order is conveyed to screen readers, not just visually.
  • The current page uses aria-current="page", not a visual cue alone.
  • The separator chevron is aria-hidden="true" (decorative) and flips (rtl:-scale-x-100) under dir="rtl".

Tokens

Token Used for
--foreground-neutral-faded Default crumb text
--foreground-neutral Hovered crumb + current-page text
--outline-color-focus Focus ring on linked crumbs

Do / Don’t

  • Do end the trail with the current page as plain text, not a link to itself.
  • Do keep labels short — this is a navigation aid, not a page title.
  • Don’t use Breadcrumbs as the only way to reach a parent page — pair with primary nav.

Content

  • Labels match the target page’s title (or a shortened form of it), sentence case.
  • No ending punctuation, no separators typed into the label — the component renders the chevron.