Skip to content

Breadcrumb

Experimental Alpha

This library is a work-in-progress. We are releasing it early to gather feedback, but it is not ready for production.

The Breadcrumb component is a wayfinding element that helps make users aware of their current location within an application or website.

Examples

Vue
Lit
React
Live Preview

Default

Types

CSS Shadow Parts Customization

Breadcrumb can be customized using CSS Shadow Parts: ::part(ag-breadcrumb-item), ::part(ag-breadcrumb-item-link), ::part(ag-breadcrumb-item-current). The following are meant solely to show how to utilize CSS shadow parts to create custom breadcrumb styles. They are NOT meant to represent best practices or good taste in breadcrumb design!

Minimal with Underline

View Vue Code
<template>
  <section>
    <div class="mbe4">
      <div class="mbe2">
        <h2>Default</h2>
      </div>
      <VueBreadcrumb
        :items="items"
        @breadcrumb-click="handleClick"
      />
    </div>
    <div class="mbe4">
      <div class="mbe2">
        <h2>Types</h2>
      </div>
      <VueBreadcrumb
        class="mbe4"
        type="slash"
        :items="items"
        @breadcrumb-click="handleClick"
      />
      <VueBreadcrumb
        class="mbe4"
        type="bullet"
        :items="items"
        @breadcrumb-click="handleClick"
      />
      <VueBreadcrumb
        class="mbe4"
        type="arrow"
        :items="items"
        @breadcrumb-click="handleClick"
      />
      <VueBreadcrumb
        primary
        type="arrow"
        :items="items"
        @breadcrumb-click="handleClick"
      />
    </div>

    <div class="mbe4">
      <div class="mbe2">
        <h2>CSS Shadow Parts Customization</h2>
        <p style="margin-top: 0.5rem; margin-bottom: 1rem; color: var(--vp-c-text-2);">
          Breadcrumb can be customized using CSS Shadow Parts:
          <code>::part(ag-breadcrumb-item)</code>,
          <code>::part(ag-breadcrumb-item-link)</code>,
          <code>::part(ag-breadcrumb-item-current)</code>. The following are meant solely to show how to utilize CSS shadow parts to create custom breadcrumb styles. They are NOT meant to represent best practices or good taste in breadcrumb design!
        </p>
      </div>

      <div style="display: flex; flex-direction: column; gap: 2rem;">
        <div>
          <h3>Minimal with Underline</h3>
          <div class="mbe3"></div>
          <VueBreadcrumb
            class="custom-minimal-breadcrumb"
            :items="items"
          />
        </div>
      </div>
    </div>
  </section>
</template>

<script>
import VueBreadcrumb from "agnosticui-core/breadcrumb/vue";
export default {
  name: "BreadcrumbExamples",
  components: { VueBreadcrumb },
  data() {
    return {
      items: [
        { label: "Home", href: "#" },
        { label: "About", href: "#about" },
        { label: "Services", href: "#services" },
        { label: "Products", href: "#products" },
      ],
    };
  },
  methods: {
    handleClick(event) {
      console.log(
        `VueBreadcrumb -> handleClick -- label: ${event.item.label}, href: ${event.item.href}`
      );
    },
  },
};
</script>

<style scoped>
/* Minimalist breadcrumb */
.custom-minimal-breadcrumb::part(ag-breadcrumb-item-link) {
  color: var(--vp-c-text-1);
  font-weight: 500;
  text-decoration: none;
  padding: 0.25rem 0.75rem;
  border-bottom: 2px solid transparent;
  transition: border-color 0.2s ease;
}

.custom-minimal-breadcrumb::part(ag-breadcrumb-item-link):hover {
  border-bottom-color: var(--vp-c-brand-1);
}

.custom-minimal-breadcrumb::part(ag-breadcrumb-item-current) {
  color: var(--vp-c-brand-1);
  font-weight: 700;
  padding: 0.25rem 0.75rem;
  border-bottom: 2px solid var(--vp-c-brand-1);
}

/* Pill-style breadcrumb */
.custom-pill-breadcrumb::part(ag-breadcrumb-item-link) {
  color: #333;
  font-weight: 600;
  text-decoration: none;
  padding: 0.5rem 1.25rem;
  border-radius: 50px;
  background: #e5e7eb;
  transition: all 0.2s ease;
}

.custom-pill-breadcrumb::part(ag-breadcrumb-item-link):hover {
  background: #d1d5db;
  transform: scale(1.05);
}

.custom-pill-breadcrumb::part(ag-breadcrumb-item-current) {
  color: white;
  font-weight: 700;
  padding: 0.5rem 1.25rem;
  border-radius: 50px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  box-shadow: 0 4px 8px rgba(102, 126, 234, 0.3);
}
</style>
Live Preview
View Lit / Web Component Code
import { LitElement, html } from 'lit';
import 'agnosticui-core/breadcrumb';

export class BreadcrumbLitExamples extends LitElement {
  // Render in light DOM to access global utility classes
  createRenderRoot() {
    return this;
  }

  constructor() {
    super();
    this.items = [
      { label: 'Home', href: '#' },
      { label: 'About', href: '#about' },
      { label: 'Services', href: '#services' },
      { label: 'Products', href: '#products' },
    ];
  }

  firstUpdated() {
    // Set up event listeners for breadcrumb items
    const breadcrumbs = this.querySelectorAll('ag-breadcrumb');
    breadcrumbs.forEach((breadcrumb) => {
      breadcrumb.items = this.items;

      breadcrumb.addEventListener('breadcrumb-click', (event) => {
        console.log(
          `ag-breadcrumb -> breadcrumb-click -- label: ${event.detail.item.label}, href: ${event.detail.item.href}`
        );
      });
    });
  }

  render() {
    return html`
      <section>
        <!-- Default -->
        <div class="mbe4">
          <div class="mbe2">
            <h2>Default</h2>
          </div>
          <ag-breadcrumb></ag-breadcrumb>
        </div>

        <!-- Types -->
        <div class="mbe4">
          <div class="mbe2">
            <h2>Types</h2>
          </div>
          <ag-breadcrumb class="mbe4" type="slash"></ag-breadcrumb>
          <ag-breadcrumb class="mbe4" type="bullet"></ag-breadcrumb>
          <ag-breadcrumb class="mbe4" type="arrow"></ag-breadcrumb>
          <ag-breadcrumb primary type="arrow"></ag-breadcrumb>
        </div>

        <!-- CSS Shadow Parts Customization -->
        <div class="mbe4">
          <div class="mbe2">
            <h2>CSS Shadow Parts Customization</h2>
            <p style="margin-top: 0.5rem; margin-bottom: 1rem; color: var(--vp-c-text-2);">
              Breadcrumb can be customized using CSS Shadow Parts:
              <code>::part(ag-breadcrumb-item)</code>,
              <code>::part(ag-breadcrumb-item-link)</code>,
              <code>::part(ag-breadcrumb-item-current)</code>. The following are meant solely to show how to utilize CSS shadow parts to create custom breadcrumb styles. They are NOT meant to represent best practices or good taste in breadcrumb design!
            </p>
          </div>

          <div style="display: flex; flex-direction: column; gap: 2rem;">
            <div>
              <h3>Minimal with Underline</h3>
              <div class="mbe3"></div>
              <ag-breadcrumb class="custom-minimal-breadcrumb"></ag-breadcrumb>
            </div>
          </div>
        </div>
      </section>
    `;
  }
}

// Register the custom element
customElements.define('breadcrumb-lit-examples', BreadcrumbLitExamples);

Interactive Preview: Click the "Open in StackBlitz" button below to see this example running live in an interactive playground.

View React Code
import { ReactBreadcrumb } from "agnosticui-core/breadcrumb/react";

export default function BreadcrumbReactExamples() {
  const items = [
    { label: "Home", href: "#" },
    { label: "About", href: "#about" },
    { label: "Services", href: "#services" },
    { label: "Products", href: "#products" },
  ];

  const handleClick = (event) => {
    console.log(
      `ReactBreadcrumb -> handleClick -- label: ${event.item.label}, href: ${event.item.href}`
    );
  };

  return (
    <section>
      {/* Default */}
      <div className="mbe4">
        <div className="mbe2">
          <h2>Default</h2>
        </div>
        <ReactBreadcrumb items={items} onBreadcrumbClick={handleClick} />
      </div>

      {/* Types */}
      <div className="mbe4">
        <div className="mbe2">
          <h2>Types</h2>
        </div>
        <ReactBreadcrumb
          className="mbe4"
          type="slash"
          items={items}
          onBreadcrumbClick={handleClick}
        />
        <ReactBreadcrumb
          className="mbe4"
          type="bullet"
          items={items}
          onBreadcrumbClick={handleClick}
        />
        <ReactBreadcrumb
          className="mbe4"
          type="arrow"
          items={items}
          onBreadcrumbClick={handleClick}
        />
        <ReactBreadcrumb
          primary
          type="arrow"
          items={items}
          onBreadcrumbClick={handleClick}
        />
      </div>

      {/* CSS Shadow Parts Customization */}
      <div className="mbe4">
        <div className="mbe2">
          <h2>CSS Shadow Parts Customization</h2>
          <p style={{ marginTop: "0.5rem", marginBottom: "1rem", color: "var(--vp-c-text-2)" }}>
            Breadcrumb can be customized using CSS Shadow Parts:
            <code>::part(ag-breadcrumb-item)</code>,
            <code>::part(ag-breadcrumb-item-link)</code>,
            <code>::part(ag-breadcrumb-item-current)</code>. The following are meant solely to show how to utilize CSS shadow parts to create custom breadcrumb styles. They are NOT meant to represent best practices or good taste in breadcrumb design!
          </p>
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
          <div>
            <h3>Minimal with Underline</h3>
            <div className="mbe3"></div>
            <ReactBreadcrumb className="custom-minimal-breadcrumb" items={items} />
          </div>
        </div>
      </div>
    </section>
  );
}
Open in StackBlitz

Usage

TIP

The framework examples below import AgnosticUI as an npm package. Alternatively, you can use the CLI for complete control, AI/LLM visibility, and full code ownership:

bash
npx ag init --framework FRAMEWORK # react, vue, lit, svelte, etc.
npx ag add Breadcrumb

The CLI copies source code directly into your project, giving you full visibility and control. After running npx ag add, you'll receive exact import instructions.

Vue
vue
<template>
  <section>
    <div class="mbe4">
      <div class="mbe2">
        <h3>Default</h3>
      </div>
      <VueBreadcrumb
        :items="items"
        @breadcrumb-click="handleClick"
      />
    </div>
    <div class="mbe4">
      <div class="mbe2">
        <h3>Types</h3>
      </div>
      <VueBreadcrumb
        type="slash"
        :items="items"
        @breadcrumb-click="handleClick"
      />
      <VueBreadcrumb
        type="bullet"
        :items="items"
        @breadcrumb-click="handleClick"
      />
      <VueBreadcrumb
        type="arrow"
        :items="items"
        @breadcrumb-click="handleClick"
      />
      <VueBreadcrumb
        primary
        type="arrow"
        :items="items"
        @breadcrumb-click="handleClick"
      />
    </div>
  </section>
</template>
<script>
import VueBreadcrumb from "agnosticui-core/breadcrumb/vue";
export default {
  name: "BreadcrumbExamples",
  components: { VueBreadcrumb },
  data() {
    return {
      items: [
        { label: "Home", href: "#" },
        { label: "About", href: "#about" },
        { label: "Services", href: "#services" },
        { label: "Products", href: "#products" },
      ],
    };
  },
  methods: {
    handleClick(event) {
      console.log(
        `VueBreadcrumb -> handleClick -- label: ${event.item.label}, href: ${event.item.href}`
      );
    },
  },
};
</script>
React
tsx
import { ReactBreadcrumb, type BreadcrumbItem } from 'agnosticui-core/breadcrumb/react';

export default function BreadcrumbExamples() {
  const items: BreadcrumbItem[] = [
    { label: 'Home', href: '#' },
    { label: 'About', href: '#about' },
    { label: 'Services', href: '#services' },
    { label: 'Products', href: '#products' },
  ];

  const handleClick = (event: CustomEvent) => {
    console.log(
      `ReactBreadcrumb -> handleClick -- label: ${event.detail.item.label}, href: ${event.detail.item.href}`
    );
  };

  return (
    <section>
      <div className="mbe4">
        <div className="mbe2">
          <h3>Default</h3>
        </div>
        <ReactBreadcrumb
          items={items}
          onBreadcrumbClick={handleClick}
        />
      </div>
      <div className="mbe4">
        <div className="mbe2">
          <h3>Types</h3>
        </div>
        <ReactBreadcrumb
          type="slash"
          items={items}
          onBreadcrumbClick={handleClick}
        />
        <ReactBreadcrumb
          type="bullet"
          items={items}
          onBreadcrumbClick={handleClick}
        />
        <ReactBreadcrumb
          type="arrow"
          items={items}
          onBreadcrumbClick={handleClick}
        />
        <ReactBreadcrumb
          primary
          type="arrow"
          items={items}
          onBreadcrumbClick={handleClick}
        />
      </div>
    </section>
  );
}
Lit (Web Components)
typescript
import { LitElement, html, css } from 'lit';
import { customElement } from 'lit/decorators.js';
import 'agnosticui-core/breadcrumb';

@customElement('breadcrumb-example')
export class BreadcrumbExample extends LitElement {
  private items = [
    { label: 'Home', href: '#' },
    { label: 'About', href: '#about' },
    { label: 'Services', href: '#services' },
    { label: 'Products', href: '#products' },
  ];

  static styles = css`
    :host {
      display: block;
    }
    section {
      display: flex;
      flex-direction: column;
      gap: 1rem;
    }
  `;

  firstUpdated() {
    // Set up event listeners for breadcrumb items in the shadow DOM
    const breadcrumbs = this.shadowRoot?.querySelectorAll('ag-breadcrumb');
    breadcrumbs?.forEach((breadcrumb: any) => {
      breadcrumb.items = this.items;

      breadcrumb.addEventListener('breadcrumb-click', (event: Event) => {
        const customEvent = event as CustomEvent;
        console.log(
          `ag-breadcrumb -> breadcrumb-click -- label: ${customEvent.detail.item.label}, href: ${customEvent.detail.item.href}`
        );
      });
    });
  }

  render() {
    return html`
      <section>
        <div class="mbe4">
          <div class="mbe2">
            <h3>Default</h3>
          </div>
          <ag-breadcrumb></ag-breadcrumb>
        </div>
        <div class="mbe4">
          <div class="mbe2">
            <h3>Types</h3>
          </div>
          <ag-breadcrumb type="slash"></ag-breadcrumb>
          <ag-breadcrumb type="bullet"></ag-breadcrumb>
          <ag-breadcrumb type="arrow"></ag-breadcrumb>
          <ag-breadcrumb primary type="arrow"></ag-breadcrumb>
        </div>
      </section>
    `;
  }
}

Note: When using breadcrumb components within a custom element's shadow DOM, set up event listeners in the component's lifecycle (e.g., firstUpdated()) rather than using DOMContentLoaded, as document.querySelector() cannot access elements inside shadow DOM. Use this.shadowRoot.querySelector() instead.

Props

PropTypeDefaultDescription
itemsBreadcrumbItem[][]Array of breadcrumb items to display
type'default' | 'slash' | 'bullet' | 'arrow''default'Separator style between breadcrumb items
primarybooleanfalseUses primary (blue) color styling for links
ariaLabelstring'Breadcrumb'Custom aria-label for the navigation landmark
typescript
interface BreadcrumbItem {
  label: string;
  href?: string;
  current?: boolean;
}

Events

EventFrameworkDetailDescription
breadcrumb-clickVue: @breadcrumb-click
React: onBreadcrumbClick
Lit: @breadcrumb-click or .onBreadcrumbClick
{ item: BreadcrumbItem, index: number, event: MouseEvent }Fired when a breadcrumb link is clicked. Provides the clicked item, its index, and the original mouse event.

Event Patterns

AgnosticUI Breadcrumb supports three event handling patterns:

  1. addEventListener (Lit/Vanilla JS):
javascript
const breadcrumb = document.querySelector("ag-breadcrumb");
breadcrumb.addEventListener("breadcrumb-click", (e) => {
  console.log("Breadcrumb clicked:", e.detail.item.label);
  console.log("Item index:", e.detail.index);
  e.detail.event.preventDefault();
});
  1. Callback props (Lit/Vanilla JS):
javascript
const breadcrumb = document.querySelector("ag-breadcrumb");
breadcrumb.onBreadcrumbClick = (e) => {
  console.log("Breadcrumb clicked:", e.detail.item.label);
};
  1. Framework event handlers (Vue/React):
vue
<VueBreadcrumb
  :items="items"
  @breadcrumb-click="handleClick"
/>
tsx
<ReactBreadcrumb
  items={items}
  onBreadcrumbClick={handleClick}
/>

All three patterns work identically thanks to the dual-dispatch system.

Note: The component does NOT prevent default navigation by default. To implement client-side routing, call event.detail.event.preventDefault() in your event handler.

CSS Shadow Parts

The Breadcrumb component exposes the following CSS Shadow Parts for custom styling:

PartDescription
ag-breadcrumb-itemIndividual breadcrumb list item wrapper
ag-breadcrumb-item-linkClickable breadcrumb link element
ag-breadcrumb-item-currentCurrent/active breadcrumb item (non-clickable)

Customization Example

css
ag-breadcrumb::part(ag-breadcrumb-item-link) {
  color: #667eea;
  font-weight: 600;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  transition: all 0.3s ease;
}

ag-breadcrumb::part(ag-breadcrumb-item-link):hover {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

ag-breadcrumb::part(ag-breadcrumb-item-current) {
  color: #764ba2;
  font-weight: 700;
  padding: 0.5rem 1rem;
}

See the CSS Shadow Parts Customization section in the examples above for more styling demonstrations.

Notes

  • The last item or any item with current: true is automatically styled as the current page (not clickable)
  • Items without an href are rendered as plain text
  • The primary prop changes link colors to use the primary theme color (typically blue)
  • All three implementations share the same underlying styles and behavior
  • Use CSS Shadow Parts for advanced customization while maintaining component encapsulation