Breadcrumb Navigation
YuuvisBreadcrumbComponent renders an accessible breadcrumb trail that shows the user’s position in a
hierarchical navigation path — for example, Case #42 / Review / Contract.pdf. It is part of
@yuuvis/client-framework and is available as a standalone Angular component.
The component renders a flat, ordered list of items. All items except the last are interactive links.
The last item represents the current location and is displayed as plain text. Clicking or pressing
Enter on a link emits a navigate event — the parent component is always responsible for the
actual routing. The breadcrumb performs no navigation itself.
Use yuv-breadcrumb whenever a user navigates into nested object hierarchies and needs a way to
understand where they are and return to a parent level. A typical scenario is a detail page for a
document stored inside a multi-level structure (e.g. a folder, a sub-folder, then the document
itself) — the breadcrumb shows the full path and lets the user jump back to any ancestor.
The component requires two things from the host:
- A
BreadcrumbItem[]input — an ordered array of{ id, name }objects that describe the trail, built from your domain model. The full interface is described in TheBreadcrumbItemInterface. - A
(navigate)output handler — the callback that executes routing when the user activates a link.
Prerequisites
Section titled “Prerequisites”- A working yuuvis shell client project (see Quick Start)
@yuuvis/client-frameworkinstalled as a project dependency
Importing the Component
Section titled “Importing the Component”YuuvisBreadcrumbComponent and BreadcrumbItem are exported from the breadcrumb entry point of
@yuuvis/client-framework. Add both to your component’s imports array:
import { YuuvisBreadcrumbComponent, BreadcrumbItem } from '@yuuvis/client-framework/breadcrumb';
@Component({ // ... imports: [YuuvisBreadcrumbComponent],})export class YourComponent { items: BreadcrumbItem[] = [];}The BreadcrumbItem Interface
Section titled “The BreadcrumbItem Interface”Each item in the trail is a plain object with two properties:
export interface BreadcrumbItem { id: string; name: string;}| Property | Type | Description |
|---|---|---|
id | string | A unique identifier for this item. Emitted via the navigate output when the user activates the link. Use a value that lets your navigation handler identify the target — for example, the object’s database ID or route segment. |
name | string | The display label rendered in the trail. Displayed as-is — no truncation, translation, or fallback is applied by the component. |
Position in the array determines rendering: all items except the last become clickable links; the
last item is rendered as plain text and marked as the current page with aria-current="page".
Building the Item Array
Section titled “Building the Item Array”The items input is a plain BreadcrumbItem[] — you build it in your component from whatever
domain data is available. The component only renders what you pass; it never fetches or infers
hierarchy on its own.
Flat Hierarchy
Section titled “Flat Hierarchy”For a simple two- or three-level path, construct the array inline or as a computed signal:
import { computed } from '@angular/core';import { BreadcrumbItem } from '@yuuvis/client-framework/breadcrumb';
// Inside your component:// (folder and document are signal inputs or computed signals defined elsewhere in the component)readonly breadcrumbItems = computed<BreadcrumbItem[]>(() => { const folder = this.folder(); const doc = this.document(); if (!folder || !doc) return [];
return [ { id: folder.id, name: folder.name }, // ← link { id: doc.id, name: doc.title }, // ← current location ];});<yuv-breadcrumb [items]="breadcrumbItems()" (navigate)="onBreadcrumbNavigate($event)"/>Multi-Level Hierarchy
Section titled “Multi-Level Hierarchy”When the depth depends on the object model at runtime, build the array programmatically. The
following example shows a three-tier model where an optional intermediate level exists between a
parent container and its documents — replace actionObj with whatever intermediate node your
domain provides (it could be a folder, a phase, a sub-category, or any other level):
readonly breadcrumbItems = computed<BreadcrumbItem[]>(() => { const parent = this.parentObject(); const actionObj = this.actionObject(); const doc = this.documentObject(); if (!parent || !doc) return [];
const items: BreadcrumbItem[] = [ { id: parent.id, name: parent.title }, ];
if (actionObj) { items.push({ id: actionObj.id, name: actionObj.title }); }
items.push({ id: doc.id, name: doc.title }); // always last = current location return items;});The same pattern scales to any number of levels — iterate over an ancestor chain and push each
level as a BreadcrumbItem, then append the current object last.
Handling Navigation
Section titled “Handling Navigation”When the user clicks or presses Enter on a breadcrumb link, the component emits the full
BreadcrumbItem for that link via the (navigate) output. Your handler receives the item and is
responsible for executing the actual navigation.
Simple Routing
Section titled “Simple Routing”Use this when each breadcrumb item maps directly to its own route. The most common handler
navigates to the target object using the Angular Router:
import { inject } from '@angular/core';import { Router } from '@angular/router';import { BreadcrumbItem } from '@yuuvis/client-framework/breadcrumb';
// Inside your component:readonly #router = inject(Router);
onBreadcrumbNavigate(item: BreadcrumbItem): void { this.#router.navigate(['/objects', item.id]);}item.id is whatever value you put into the BreadcrumbItem when building the array, so it can
be a route segment, a database ID, or any other application-specific key.
Pre-Selecting a Node on Navigation
Section titled “Pre-Selecting a Node on Navigation”Use this when the trail contains items that all live inside the same parent page, and clicking an
intermediate item should open that parent page with a specific node pre-selected. For example: a
document’s detail page shows the path Container / Sub-folder / Document.pdf. Clicking
Sub-folder should open the container page and automatically highlight the sub-folder in its
navigation tree.
The navigate handler always routes to the parent container (/containers/parentId). When the
clicked item is the parent itself, the navigation is plain — no query parameter is needed. When
the clicked item is an intermediate node (not the parent), the node’s ID is passed as a
selected-node-id query parameter so the container page can apply the selection once its
data is loaded:
// parentObject is a Signal<ContainerObject | undefined> defined in your component —// its id is the route target for all breadcrumb links on this page.onBreadcrumbNavigate(item: BreadcrumbItem): void { const parentId = this.parentObject()?.id; if (!parentId) return;
const isParent = item.id === parentId;
// Navigate to the parent container page. // If the clicked item IS the parent, no query params are needed. // If the clicked item is an intermediate node, pass its id so the // container page can pre-select it in its navigation tree. this.#router.navigate( ['/containers', parentId], isParent ? undefined : { queryParams: { 'selected-node-id': item.id } } );}Truncating the Trail on Navigation
Section titled “Truncating the Trail on Navigation”Use this in self-contained, in-page navigation where clicking a breadcrumb link collapses the trail rather than routing to a new page — for example, a wizard-style component where each step drills deeper and clicking back in the breadcrumb undoes steps.
Maintain the trail as a signal<BreadcrumbItem[]> initialized from the full initial path. When a
link is clicked, slice the array to include only items up to and including the clicked one — that
item then becomes the new current location (last item):
import { signal } from '@angular/core';import { BreadcrumbItem } from '@yuuvis/client-framework/breadcrumb';
// Inside your component:// initialTrail is the starting BreadcrumbItem[] for this page — e.g. the full path// from the root down to the current location when the user arrived at the page.readonly trail = signal<BreadcrumbItem[]>([...this.initialTrail]);
navigateToLevel(item: BreadcrumbItem): void { const idx = this.trail().findIndex(i => i.id === item.id); if (idx >= 0) { this.trail.set(this.trail().slice(0, idx + 1)); }}Bind the signal and handler in the template:
<yuv-breadcrumb [items]="trail()" (navigate)="navigateToLevel($event)"/>The trail collapses to the clicked level, and the last item becomes the new current location.
Non-Navigable Labels
Section titled “Non-Navigable Labels”The component determines clickability by position only: all items except the last render as clickable links; only the last item renders as plain text. There is no built-in support for a display-only label in the middle of the trail.
If your domain model includes intermediate classification labels or category names that have no
navigation target, use a handler guard pattern: give each such item a sentinel id value
that your handler recognises and ignores.
// A sentinel id that signals "this item is a label, not a navigation target"const LABEL_SENTINEL = '__label__';
// Build the trail — the phase name is a display-only classification labelreadonly breadcrumbItems = computed<BreadcrumbItem[]>(() => { const items: BreadcrumbItem[] = [ { id: 'container-1', name: 'Archive' }, { id: LABEL_SENTINEL, name: 'Confidential' }, // display-only, no route target { id: 'doc-42', name: 'Report.pdf' }, // current location ]; return items;});
// Guard: ignore items that have no navigation targetonBreadcrumbNavigate(item: BreadcrumbItem): void { if (item.id === LABEL_SENTINEL) return; this.#router.navigate(['/objects', item.id]);}The label item renders visually identical to a real link — same hover underline, same keyboard-focusability — because the component applies no disabled or suppressed styling for non-last items. Activating it has no effect only because the handler returns early. This is a known UX trade-off: if the visual distinction matters for your use case, add custom CSS targeting the specific item or restructure the trail so that label-only levels always appear last.
Single-Item Trail
Section titled “Single-Item Trail”A breadcrumb with a single item renders only the current location — nothing is clickable and no
(navigate) event is ever emitted. Use this when you want to display a title consistently using
the breadcrumb’s styling even when there is no parent to navigate to:
readonly breadcrumbItems = computed<BreadcrumbItem[]>(() => { const obj = this.currentObject(); if (!obj) return []; return [{ id: obj.id, name: obj.title }]; // single item = current location only});<yuv-breadcrumb [items]="breadcrumbItems()" />The (navigate) binding can be omitted entirely when the trail will never have more than one item.
Theming
Section titled “Theming”yuv-breadcrumb exposes three CSS custom properties. Override them on any ancestor element or
directly on the yuv-breadcrumb host to change the appearance:
| CSS Custom Property | Default | Controls |
|---|---|---|
--yuv-breadcrumb-link-color | inherit | Color of clickable link items |
--yuv-breadcrumb-current-color | currentColor | Color of the current-location item (also font-weight: 500) |
--yuv-breadcrumb-separator-color | currentColor at 40% opacity | Color of the / separator |
Apply overrides in your component’s SCSS:
.breadcrumb-wrapper { --yuv-breadcrumb-link-color: var(--your-brand-color); --yuv-breadcrumb-current-color: var(--your-text-emphasis-color); --yuv-breadcrumb-separator-color: var(--your-muted-color);}<div class="breadcrumb-wrapper"> <yuv-breadcrumb [items]="breadcrumbItems()" (navigate)="onBreadcrumbNavigate($event)" /></div>