J3W1 / DESIGN SYSTEM
Breadcrumbs
The path from the root to the current page as an ordered list of links separated by slashes; the last item is the current page and not a link.
stable · LIGHT DOM · 1.1.0
Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.
Live variants
default
<j3w1-breadcrumbs id="example-breadcrumbs-default"><nav class="breadcrumbs" aria-label="Breadcrumb">
<ol class="breadcrumbs-list">
<li class="breadcrumbs-item"><a class="breadcrumbs-link" href="#example-breadcrumbs-default-bc-home">Home</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item breadcrumbs-item-ellipsis" hidden=""><button class="breadcrumbs-ellipsis" type="button" aria-expanded="false" aria-label="Show 2 hidden levels" aria-controls="example-breadcrumbs-default-breadcrumb-levels-0">…</button><span class="breadcrumbs-separator" aria-hidden="true">/</span><ol id="example-breadcrumbs-default-breadcrumb-levels-0" hidden=""><li><a class="breadcrumbs-link" href="#example-breadcrumbs-default-level-0">Level 1</a></li><li><a class="breadcrumbs-link" href="#example-breadcrumbs-default-level-1">Level 2</a></li></ol></li>
<li class="breadcrumbs-item breadcrumbs-item-collapsible"><a class="breadcrumbs-link" href="#example-breadcrumbs-default-bc-projects">Projects</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item breadcrumbs-item-collapsible"><a class="breadcrumbs-link" href="#example-breadcrumbs-default-bc-theme">Theme</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item"><a class="breadcrumbs-link breadcrumbs-link-demo-target" href="#example-breadcrumbs-default-bc-settings">Settings</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item"><a class="breadcrumbs-link breadcrumbs-current" href="#example-breadcrumbs-default-bc-appearance" aria-current="page">Appearance</a></li>
</ol>
</nav><p id="example-breadcrumbs-default-bc-home" tabindex="-1" class="j3w1-example-target">Example destination: bc home</p><p id="example-breadcrumbs-default-level-0" tabindex="-1" class="j3w1-example-target">Example destination: level 0</p><p id="example-breadcrumbs-default-level-1" tabindex="-1" class="j3w1-example-target">Example destination: level 1</p><p id="example-breadcrumbs-default-bc-projects" tabindex="-1" class="j3w1-example-target">Example destination: bc projects</p><p id="example-breadcrumbs-default-bc-theme" tabindex="-1" class="j3w1-example-target">Example destination: bc theme</p><p id="example-breadcrumbs-default-bc-settings" tabindex="-1" class="j3w1-example-target">Example destination: bc settings</p><p id="example-breadcrumbs-default-bc-appearance" tabindex="-1" class="j3w1-example-target">Example destination: bc appearance</p></j3w1-breadcrumbs>truncated
<j3w1-breadcrumbs id="example-breadcrumbs-truncated"><nav class="breadcrumbs" aria-label="Breadcrumb">
<ol class="breadcrumbs-list">
<li class="breadcrumbs-item"><a class="breadcrumbs-link" href="#example-breadcrumbs-truncated-bc-home">Home</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item breadcrumbs-item-ellipsis"><button class="breadcrumbs-ellipsis" type="button" aria-expanded="false" aria-label="Show 3 hidden levels" aria-controls="example-breadcrumbs-truncated-breadcrumb-levels-0">…</button><span class="breadcrumbs-separator" aria-hidden="true">/</span><ol id="example-breadcrumbs-truncated-breadcrumb-levels-0" hidden=""><li><a class="breadcrumbs-link" href="#example-breadcrumbs-truncated-level-0">Level 1</a></li><li><a class="breadcrumbs-link" href="#example-breadcrumbs-truncated-level-1">Level 2</a></li><li><a class="breadcrumbs-link" href="#example-breadcrumbs-truncated-level-2">Level 3</a></li></ol></li>
<li class="breadcrumbs-item breadcrumbs-item-collapsible" hidden=""><a class="breadcrumbs-link" href="#example-breadcrumbs-truncated-bc-projects">Projects</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item breadcrumbs-item-collapsible" hidden=""><a class="breadcrumbs-link" href="#example-breadcrumbs-truncated-bc-theme">Theme</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item breadcrumbs-item-collapsible" hidden=""><a class="breadcrumbs-link" href="#example-breadcrumbs-truncated-bc-site">Site</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item"><a class="breadcrumbs-link breadcrumbs-link-demo-target" href="#example-breadcrumbs-truncated-bc-settings">Settings</a><span class="breadcrumbs-separator" aria-hidden="true">/</span></li>
<li class="breadcrumbs-item"><a class="breadcrumbs-link breadcrumbs-current" href="#example-breadcrumbs-truncated-bc-appearance" aria-current="page">Appearance</a></li>
</ol>
</nav><p id="example-breadcrumbs-truncated-bc-home" tabindex="-1" class="j3w1-example-target">Example destination: bc home</p><p id="example-breadcrumbs-truncated-level-0" tabindex="-1" class="j3w1-example-target">Example destination: level 0</p><p id="example-breadcrumbs-truncated-level-1" tabindex="-1" class="j3w1-example-target">Example destination: level 1</p><p id="example-breadcrumbs-truncated-level-2" tabindex="-1" class="j3w1-example-target">Example destination: level 2</p><p id="example-breadcrumbs-truncated-bc-projects" tabindex="-1" class="j3w1-example-target">Example destination: bc projects</p><p id="example-breadcrumbs-truncated-bc-theme" tabindex="-1" class="j3w1-example-target">Example destination: bc theme</p><p id="example-breadcrumbs-truncated-bc-site" tabindex="-1" class="j3w1-example-target">Example destination: bc site</p><p id="example-breadcrumbs-truncated-bc-settings" tabindex="-1" class="j3w1-example-target">Example destination: bc settings</p><p id="example-breadcrumbs-truncated-bc-appearance" tabindex="-1" class="j3w1-example-target">Example destination: bc appearance</p></j3w1-breadcrumbs>Install and register
Use the exact version. If npm publication is pending, install the release tarball from the installation guide.
npm install --save-exact @j3w1/ui@1.1.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/breadcrumbs.css';
import '@j3w1/ui/register/breadcrumbs';Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.
Copy the complete implementation
npx --package=@j3w1/ui@1.1.0 j3w1-ui copy breadcrumbs --out ./vendor/j3w1/breadcrumbsThe CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.
Public API
attributes
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
events
| Name | Type / signature | Meaning |
|---|---|---|
j3w1-toggle | CustomEvent | A collapsed breadcrumb group changed visibility. |
Dependencies and verification
Registered components: none. Style dependencies: none.
Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.
Full implementation manifest, API and token dependency closure
Canonical specification
Purpose
Shows where the current page sits in a hierarchy and lets the user jump to any ancestor. Breadcrumbs are secondary navigation: they never replace the sidebar or the page title, and they are omitted on the root page.
Anatomy
A nav labelled “Breadcrumb” wrapping an ol. Each ancestor is a link in
color.text.link with a 1px color.text.link-underline; a / separator in
color.text.muted follows every item but the last; the last item is the
current page in color.text.bright with aria-current="page". When the
trail is deeper than the space allows, the middle levels collapse behind an
ellipsis button that names how many levels it hides.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | links color.text.link, 1px underline; separators color.text.muted; current color.text.bright | underline on links; none on the current page |
| hover | link background → color.interaction.hover.bg-strong; text → color.text.link-hover | underline thickens 1px → 2px; cursor |
| focus-visible | ring 1px dashed color.interaction.focus.ring at −2px around the link | the ring |
| current | text color.text.bright; no underline; no hover | aria-current="page"; no underline |
| truncated | the middle levels are replaced by an … button in color.text.default | aria-expanded="false" on the button; its label counts the hidden levels |
Keyboard
Every ancestor link is a tab stop in trail order. The ellipsis button is a tab
stop that discloses the hidden levels in place on Enter or Space and sets its
own aria-expanded; focus stays on the button so the newly revealed links are
the next Tab presses.
Accessibility
aria-label="Breadcrumb" on the nav, translated. The separator is
aria-hidden so nothing voices “slash”; the list structure gives the count.
aria-current="page" marks the last item whether or not it is a link. Hidden
levels stay in the DOM under the ellipsis (hidden until disclosed) so a
find-in-page still reaches them. Contrast: link text 10.10:1, current
10.10:1, separator 5.66:1, underline 4.57:1 on the panel surface. Each link
is at least 24 CSS pixels tall through its line box and padding.
Portability
Plain inline links and text; the only requirement is an inline-start margin on the separator that flips in RTL. Toolkits without an underline draw the link in the link colour and record the deviation. The ellipsis disclosure is optional; hosts without it show the full trail and let it wrap.
Non-examples
Chevrons, arrows or bullets as separators. A trail that ends with the site
name instead of the current page. The current page drawn as a link with an
underline. Automatic truncation by text-overflow that hides levels without
a way to reach them. A trail that scrolls horizontally. Uppercase or
letter-spaced items. Separators that are read aloud.