Breadcrumb
stimeo--breadcrumb
A breadcrumb trail that collapses its middle items behind a disclosure when it overflows.
The stimeo--breadcrumb controller implements the WAI-ARIA Breadcrumb pattern. The base structure (nav + ol + aria-current="page") lives in your markup; the controller adds the responsive behavior. When the trail is wider than its container it hides the author-marked middle items and reveals an ellipsis (…) disclosure button; pressing it expands the full path back and toggles aria-expanded. When the trail fits, everything is shown and the ellipsis is hidden. Overflow is detected with a ResizeObserver that is released on disconnect. Behavior only — separators and the look are yours.
Keyboard
| Key | Action |
|---|---|
| Enter / Space | Expand or re-collapse the full path on the ellipsis button. |
<%# Markup for the breadcrumb demo.
The APG structure (nav + ol + aria-current="page") lives in the markup; the
library only handles the responsive behavior of collapsing middle items into a
"…" disclosure button when width runs short. Separators are drawn by demo.css's
::after. %>
<nav
class="breadcrumb"
data-controller="stimeo--breadcrumb"
aria-label="<%= t("components.breadcrumb.demo.label") %>">
<ol class="breadcrumb__list" data-stimeo--breadcrumb-target="list">
<li class="breadcrumb__item">
<a href="#"><%= t("components.breadcrumb.demo.home") %></a>
</li>
<li class="breadcrumb__item" data-stimeo--breadcrumb-target="ellipsis" hidden>
<button
type="button"
class="breadcrumb__ellipsis"
aria-expanded="false"
aria-controls="breadcrumb-collapsed"
aria-label="<%= t("components.breadcrumb.demo.expand") %>"
data-stimeo--breadcrumb-target="trigger"
data-action="click->stimeo--breadcrumb#toggle">…</button>
</li>
<li
class="breadcrumb__item"
id="breadcrumb-collapsed"
data-stimeo--breadcrumb-target="collapsible">
<a href="#"><%= t("components.breadcrumb.demo.section") %></a>
</li>
<li class="breadcrumb__item" data-stimeo--breadcrumb-target="collapsible">
<a href="#"><%= t("components.breadcrumb.demo.subsection") %></a>
</li>
<li class="breadcrumb__item" data-stimeo--breadcrumb-target="collapsible">
<a href="#"><%= t("components.breadcrumb.demo.category") %></a>
</li>
<li class="breadcrumb__item">
<a href="#" aria-current="page"><%= t("components.breadcrumb.demo.current") %></a>
</li>
</ol>
</nav>
/*
* Presentation-only styles for the breadcrumb demo.
* Collapse/expand is the library toggling the hidden attribute of collapsible items
* and the ellipsis, plus the trigger's aria-expanded. Here we narrow the container
* to force overflow and draw the "/" separator with ::after.
*/
.breadcrumb {
max-width: 22rem;
overflow: hidden;
}
.breadcrumb__list {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 0.25rem;
margin: 0;
padding: 0;
list-style: none;
white-space: nowrap;
}
.breadcrumb__item {
display: inline-flex;
align-items: center;
gap: 0.25rem;
font-size: 0.875rem;
}
.breadcrumb__item:not(:last-child)::after {
content: "/";
color: var(--color-text-subtle);
}
.breadcrumb__item a {
color: var(--accent, var(--color-primary));
text-decoration: none;
}
.breadcrumb__item a[aria-current="page"] {
color: var(--fg, var(--color-text));
font-weight: 600;
pointer-events: none;
}
.breadcrumb__ellipsis {
padding: 0 0.25rem;
border: 0;
background: none;
color: var(--color-text-muted);
font: inherit;
line-height: 1;
cursor: pointer;
}
.breadcrumb__ellipsis:hover {
color: var(--fg, var(--color-text));
}
This demo needs no consumer-side JS (the controller handles the behavior).
These demo styles use shared design tokens (light + dark). Copy the shared styles too, then toggle data-theme on your root element for dark mode.
The data-* attributes you add to your own HTML to wire this component. Put the data-controller below on a root element, then place its targets / values / actions inside that element.
On the root element
data-controller="stimeo--breadcrumb"
Targets
| Name | Description | Attribute |
|---|---|---|
list
required
|
The <ol> trail container; its width is measured to detect overflow. |
data-stimeo--breadcrumb-target="list" |
collapsible
|
An author-marked middle item that is hidden when the trail collapses. | data-stimeo--breadcrumb-target="collapsible" |
ellipsis
|
The ellipsis (…) item shown in place of the collapsed items while overflowing. | data-stimeo--breadcrumb-target="ellipsis" |
trigger
|
The disclosure button that expands/re-collapses the trail; its aria-expanded is synced. |
data-stimeo--breadcrumb-target="trigger" |
Actions
| Name | Description | Action |
|---|---|---|
toggle
|
Expands or re-collapses the trail and dispatches the toggle event. | stimeo--breadcrumb#toggle |
Events
| Name | Description | Event |
|---|---|---|
toggle
|
Dispatched when the user expands or re-collapses the trail; detail carries { expanded }. |
stimeo--breadcrumb:toggle |
State hooks
The library only manages these ARIA/data attributes and custom properties. Your CSS reads them to render the look — selectors like [aria-selected], [aria-expanded], or var(--stimeo--…) hook into this state.
| Hook | Target | Meaning |
|---|---|---|
hidden |
Collapsible items | Present while collapsed, removed while expanded or when the trail fits. |
hidden |
Ellipsis | Removed while overflowing, present when the trail fits. |
aria-expanded |
Trigger | "true" while the collapsed items are expanded. |