{
  "componentId": "breadcrumbs",
  "componentName": "Breadcrumbs",
  "lastReviewed": "2026-05-05",
  "keyboardWalk": [
    {
      "keys": "Tab",
      "expected": "Focus moves through each link slot in DOM order. The current-marker (last item) is NOT in the tab order because it is not a link. The overflow-collapse button is in the tab order between the first item and the post-collapse items."
    },
    {
      "keys": "Shift+Tab",
      "expected": "Reverse focus through the same elements. Standard link navigation — no breadcrumbs-specific behavior."
    },
    {
      "keys": "Enter, Space (overflow-collapse focused)",
      "expected": "Activates the menu-button. Menu opens; focus moves to the first item in the menu (or the menu container with `tabindex=\"-1\"`). `aria-expanded` flips to true."
    },
    {
      "keys": "Escape (menu open)",
      "expected": "Closes the menu. Focus returns to the overflow-collapse button. `aria-expanded` flips back to false."
    },
    {
      "keys": "Arrow keys (menu open)",
      "expected": "Navigate between menu items (vertical: ArrowUp / ArrowDown for a `role=\"menu\"` listing of collapsed breadcrumb items). Enter activates the focused item."
    }
  ],
  "announcements": [
    {
      "trigger": "SR enters the breadcrumb landmark",
      "expected": "SR announces \"navigation, Breadcrumb\" (the landmark plus its label). For deep trails, the announcement continues with \"list, 4 items\"."
    },
    {
      "trigger": "SR encounters each item",
      "expected": "Intermediate items announce as \"link, Home\" / \"link, Settings\" / \"link, Account\". The current item announces as \"current page, Email\" — the link role is absent because the element is a span (or anchor without href)."
    },
    {
      "trigger": "User activates overflow-collapse",
      "expected": "SR announces the menu open (\"menu, 3 items\") and reads the first menu item. The button's `aria-expanded` flip is announced."
    }
  ],
  "axeRules": [
    "aria-allowed-attr",
    "aria-valid-attr-value",
    "aria-required-attr",
    "landmark-unique",
    "link-name"
  ],
  "_about": "Per-component a11y-acceptance data shaped for direct ingestion into Playwright + @axe-core/playwright or Jest + jest-axe.\n\nSuggested wiring:\n- axeRules → pass to AxeBuilder.options({ runOnly: { type: \"rule\", values: axeRules } }) so the run targets only the rules the canon has pinned for this component (other rules can run in your global pass).\n- keyboardWalk → iterate the entries; each `keys` is a human-readable sequence (e.g. \"Tab → Tab → Esc\"). Translate to page.keyboard.press calls and assert `expected` against the result (focused element, aria-state, visible text, etc.).\n- announcements → assert text content of any aria-live region or capture the accessibility tree at the trigger moment and match against `expected`.\n\nEmpty sub-arrays mean the canon does not yet pin behaviour for that axis on this component, not that none is required."
}