Breadcrumb
A hierarchy trail showing where a page sits, with linked ancestors and a marked current location.
Live demo
Breadcrumb renders a location trail: an ordered list of ancestor links ending in the current page, with a separator glyph between each step. It is a <nav> landmark labeled "Breadcrumb" wrapping an <ol>; ancestors render as anchors and the final crumb renders as plain text carrying aria-current="page".
Pass the trail declaratively via the items array (each entry is { label, href?, value?, title?, current? }) and the engine builds the list, injects the separators, and marks the last item current. For an in-app trail where a crumb drives state instead of navigating (selecting an ancestor node, not following a URL), give the item a value and no href: it renders as a real button and fires a select event carrying { value, index } on click or Enter/Space, so interactive crumbs never have to drop to the slot. href wins when both are set. The separator glyph defaults to / and is purely decorative. A tone tints the ancestor links and three sizes scale the type. For fully custom crumbs, omit items and provide your own <li> markup in the default slot.
When to use
How this component composes with the rest of the set.
Props
5 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Appearance
Variants
accent
Ancestor links tinted with the accent tone (the default).
neutral
Ancestor links in neutral ink for a quieter trail.
Sizes
sm
Compact.
md
Default.
lg
Large.
States
hover
Pointer over an ancestor link; it underlines.
focus-visible
Keyboard focus on a link: a token-colored ring, plus a transparent outline promoted to a real one in forced-colors mode.
Anatomy
The named parts that make up the component, with their selectors.
breadcrumb
The <nav> landmark wrapping the trail, carrying the tone and size classes.
list
The ordered list laying the crumbs and separators out in a wrapping row.
item
An ancestor link (anchor) or the current crumb (text). Links tint with the tone; the current crumb is bold neutral ink.
separator
The decorative glyph between crumbs, hidden from assistive tech.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--accent-2-vivid
--accent-3-vivid
--accent-4-vivid
--accent-vivid
--black-vivid
--blue-vivid
--border-normal
--border-thick
--brown-vivid
--cyan-vivid
--danger-vivid
--duration-fast
--ease-standard
--fg-0
--fg-2
--fg-3
--font-sans
--gray-vivid
--green-vivid
--info-vivid
--leading-normal
--neutral-vivid
--orange-vivid
--pink-vivid
--purple-vivid
--radius-sm
--red-vivid
--ring
--space-0
--space-1
--success-vivid
--text-body
--text-sm
--text-xs
--warn-vivid
--weight-medium
--white-vivid
--yellow-vivid
Slots
Custom crumb markup (<li> items and separators) used when items is omitted.
Accessibility
Code
A location trail
An ordered trail of linked ancestors ending in the current page; tone and separator are adjustable.
<xtyle-breadcrumb
items='[
{"label":"Home","href":"/"},
{"label":"Library","href":"/library"},
{"label":"Themes"}
]'
></xtyle-breadcrumb>
<xtyle-breadcrumb tone="neutral" separator="›" items='[
{"label":"Docs","href":"/docs"},
{"label":"Components","href":"/docs/components"},
{"label":"Breadcrumb"}
]'></xtyle-breadcrumb>
<xtyle-breadcrumb label="You are here">
<li class="xtyle-breadcrumb__item"><a class="xtyle-breadcrumb__link" href="/">Home</a></li>
<li class="xtyle-breadcrumb__separator" aria-hidden="true">/</li>
<li class="xtyle-breadcrumb__item"><span class="xtyle-breadcrumb__current" aria-current="page">Settings</span></li>
</xtyle-breadcrumb>
<script lang="ts">
import { Breadcrumb } from "@xtyle/svelte";
const trail = [
{ label: "Home", href: "/" },
{ label: "Library", href: "/library" },
{ label: "Themes" },
];
</script>
<Breadcrumb items={trail} />
<Breadcrumb tone="neutral" separator="›" items={trail} />
---
import { Breadcrumb } from "@xtyle/astro";
const trail = [
{ label: "Home", href: "/" },
{ label: "Library", href: "/library" },
{ label: "Themes" },
];
---
<Breadcrumb items={trail} />
<Breadcrumb tone="neutral" separator="›" items={trail} />
In-app crumbs (select, not navigate)
Give a crumb a value instead of an href and it becomes a keyboard-accessible button that fires select with { value, index }, so clicking an ancestor drives app state rather than following a URL.
<xtyle-breadcrumb id="tree-trail" label="Node ancestry" items='[
{"label":"root","value":"0"},
{"label":"window","value":"1"},
{"label":"toolbar"}
]'></xtyle-breadcrumb>
<script>
// a valued crumb drives app state instead of navigating
document.querySelector("#tree-trail").addEventListener("select", (e) => {
selectNode(e.detail.value); // { value, index }
});
</script>
<script lang="ts">
import { Breadcrumb } from "@xtyle/svelte";
const ancestry = [
{ label: "root", value: "0" },
{ label: "window", value: "1" },
{ label: "toolbar" }, // the current node: no value, not clickable
];
</script>
<Breadcrumb label="Node ancestry" items={ancestry} onselect={(e) => selectNode(e.detail.value)} />
---
import { Breadcrumb } from "@xtyle/astro";
const ancestry = [
{ label: "root", value: "0" },
{ label: "window", value: "1" },
{ label: "toolbar" },
];
---
<Breadcrumb label="Node ancestry" items={ancestry} />
<script>
document.querySelector("xtyle-breadcrumb").addEventListener("select", (e) => {
selectNode(e.detail.value);
});
</script>
Shortened crumbs with hover detail
A title on an item reveals the full value behind an abbreviated, truncated, or glyph label on hover, and carries it to assistive tech as the crumb's accessible description.
<!-- a title reveals the full value behind a shortened crumb -->
<xtyle-breadcrumb items='[
{"label":"~","href":"/","title":"/home/ada"},
{"label":"…","href":"/p","title":"projects/2026/q3"},
{"label":"report.md","title":"projects/2026/q3/report.md"}
]'></xtyle-breadcrumb>
<script lang="ts">
import { Breadcrumb } from "@xtyle/svelte";
const path = [
{ label: "~", href: "/", title: "/home/ada" },
{ label: "…", href: "/p", title: "projects/2026/q3" }, // middle-truncated, full path on hover
{ label: "report.md", title: "projects/2026/q3/report.md" },
];
</script>
<Breadcrumb items={path} />
---
import { Breadcrumb } from "@xtyle/astro";
const path = [
{ label: "~", href: "/", title: "/home/ada" },
{ label: "…", href: "/p", title: "projects/2026/q3" },
{ label: "report.md", title: "projects/2026/q3/report.md" },
];
---
<Breadcrumb items={path} />