APG Patterns
日本語
日本語

Breadcrumb

A navigation pattern that shows the user's current location within a site hierarchy.

Demo

Basic Breadcrumb

A simple breadcrumb trail showing the path to the current page.

Long Path

A deeper navigation path with multiple levels of hierarchy.

Open demo only →

Accessibility Features

WAI-ARIA Roles

Role Target Element Description
navigation <nav> element Provides a navigation landmark for assistive technology (implicit role of

WAI-ARIA Breadcrumb Pattern (opens in new tab)

WAI-ARIA Properties

Attribute Target Values Required Description
aria-label <nav> "Breadcrumb" (or localized) Yes Labels the navigation landmark for screen readers
aria-current Current page element "page" Yes (on last item) Identifies the current page within the breadcrumb trail

WAI-ARIA States

aria-current=""page""

Indicates the current page location within the breadcrumb navigation.

Target Last item in the breadcrumb (current page)
Values "page"
Required Yes
Reference aria-current (opens in new tab)

Keyboard Support

Key Action
Tab Move focus between breadcrumb links
Enter Activate the focused link

Breadcrumb uses native element behavior for keyboard interaction. No additional keyboard handlers are required.

Source Code

Breadcrumb.vue
<script setup lang="ts">
/**
 * Breadcrumb component following WAI-ARIA APG pattern
 * @see https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/
 */

export interface BreadcrumbItem {
  label: string;
  href?: string;
}

export interface BreadcrumbProps {
  items: BreadcrumbItem[];
  ariaLabel?: string;
  class?: string;
}

const props = withDefaults(defineProps<BreadcrumbProps>(), {
  ariaLabel: 'Breadcrumb',
});

function getItemKey(item: BreadcrumbItem): string {
  return `${item.href ?? 'current'}-${item.label}`;
}
</script>

<template>
  <nav v-if="items.length > 0" :aria-label="ariaLabel" :class="['apg-breadcrumb', props.class]">
    <ol class="apg-breadcrumb-list">
      <li v-for="(item, index) in items" :key="getItemKey(item)" class="apg-breadcrumb-item">
        <a
          v-if="item.href && index !== items.length - 1"
          :href="item.href"
          class="apg-breadcrumb-link"
        >
          {{ item.label }}
        </a>
        <span
          v-else
          :aria-current="index === items.length - 1 ? 'page' : undefined"
          class="apg-breadcrumb-current"
        >
          {{ item.label }}
        </span>
      </li>
    </ol>
  </nav>
</template>

Usage

Example
<script setup>
import Breadcrumb from './Breadcrumb.vue';

const items = [
  { label: 'Home', href: '/' },
  { label: 'Products', href: '/products' },
  { label: 'Current Product' }
];
</script>

<template>
  <Breadcrumb :items="items" />
</template>

API

Props

Prop Type Default Description
items BreadcrumbItem[] required Array of breadcrumb items
ariaLabel string "Breadcrumb" Accessible label for the navigation

BreadcrumbItem

Property Type Required Description
label string Yes Display text for the item
href string No URL for the link (omit for current page)

Testing

Tests verify APG compliance across ARIA attributes, semantic structure, and accessibility requirements. The Breadcrumb component uses a two-layer testing strategy.

Testing Strategy

Unit Tests (Testing Library)

Verify the component's rendered output using framework-specific testing libraries. These tests ensure correct HTML structure and ARIA attributes.

  • HTML structure (nav, ol, li elements)
  • ARIA attributes (aria-label, aria-current)
  • Link rendering and href values
  • Accessibility via jest-axe

E2E Tests (Playwright)

Verify component behavior in a real browser environment across all frameworks. These tests cover interactions and cross-framework consistency.

  • Keyboard navigation (Tab, Enter)
  • ARIA structure in live browser
  • axe-core accessibility scanning
  • Cross-framework consistency checks

Test Categories

High Priority: APG ARIA Attributes

TestDescription
nav elementUses semantic
aria-labelNavigation has accessible label (default: "Breadcrumb")
aria-current="page"Last item has aria-current="page"
ol/li structureUses ordered list for proper semantic structure

High Priority: Keyboard Interaction

TestDescription
Tab navigationTab moves focus between breadcrumb links
Enter activationEnter key activates focused link
Current page not focusableLast item (span) is not in tab order

Medium Priority: Accessibility

TestDescription
axe violationsNo WCAG 2.1 AA violations (via jest-axe)
Custom aria-labelCan override default label via ariaLabel prop
Separator hiddenVisual separators are hidden from assistive technology

Low Priority: Component Behavior

TestDescription
Renders all itemsAll provided items are rendered in order
Links have hrefNon-current items render as links with correct href
className mergeCustom classes are merged with component classes

Low Priority: Cross-framework Consistency

TestDescription
All frameworks have navReact, Vue, Svelte, Astro all render breadcrumb navigation
Same item countAll frameworks render the same number of breadcrumb items
Current page markedAll frameworks mark the last item with aria-current="page"

Testing Tools

See testing-strategy.md (opens in new tab) for full documentation.

Resources