Skip to content

[Breadcrumb] Structural improvements and feature enhancements #600

@ravisuhag

Description

@ravisuhag

Summary

Improvements to the Breadcrumb component to fix accessibility issues, structural HTML problems, and fragile patterns.

Feature Enhancements

1. Auto-collapse with maxItems

Add a maxItems prop to BreadcrumbRoot that automatically collapses middle items behind an Ellipsis when the breadcrumb exceeds the limit. Currently users must manually build the collapsed view themselves.

2. Truncation for long labels

There is no text-overflow: ellipsis or maxWidth support. Long breadcrumb labels push the layout. Add a truncate prop or a maxWidth on BreadcrumbItem to clamp text with an ellipsis and show a tooltip on hover.

4. Keyboard navigation on Ellipsis

BreadcrumbEllipsis renders as a <span> — it is not focusable or interactive. If the ellipsis is meant to expand collapsed items or trigger a dropdown, it should be a <button> with proper keyboard support and an aria-label like "Show more breadcrumbs".

6. Trailing icon support

Only leadingIcon is supported. A trailingIcon prop would allow patterns like external-link indicators or lock icons after the label.

8. Responsive/mobile collapse

No responsive behavior. On narrow viewports, breadcrumbs overflow. Consider a built-in strategy — e.g., showing only the parent and current item on small screens, or wrapping into a single "Back to {parent}" link.

9. Render current item as plain text instead of <a>

When current is set, the component still renders an <a> with pointer-events: none. Semantically the current page should not be a link. It should render as a <span> instead, which also avoids the CSS hack.

10. href on dropdown items

BreadcrumbDropdownItem only supports onClick. Adding an href field would let dropdown items work as proper navigation links, which is better for accessibility and SSR (right-click → open in new tab).

11. itemsBeforeCollapse / itemsAfterCollapse

Fine-grained control over the maxItems collapse — specify how many items stay visible on each side of the ellipsis. For example, itemsBeforeCollapse={1} and itemsAfterCollapse={2} would show the first item and last two items with an ellipsis in between.

12. variant and color props

Visual style variants (solid, bordered, light) and semantic color options (primary, secondary, muted) for different breadcrumb contexts.

13. Data attributes for CSS state targeting

Emit data-current, data-hovered, data-disabled, data-focus-visible attributes on items so users can style states purely in CSS without needing prop callbacks.

Improvements

14. Dropdown item breaks <ol> list structure

When BreadcrumbItem has dropdownItems, it renders a <DropdownMenu> directly without wrapping in <li>. This breaks the semantic <ol> structure required for breadcrumb navigation.

15. Ellipsis and Separator break <ol> list structure

BreadcrumbEllipsis and BreadcrumbSeparator render as bare <span> elements directly inside the <ol>. Per HTML spec, <ol> should only contain <li> as direct children. Both should be wrapped in <li> elements (with appropriate ARIA attributes).

16. ref not forwarded in dropdown path

In BreadcrumbItem, the ref from forwardRef is only captured in the default <a> element (line 46). When dropdownItems is provided, the early return never attaches ref to anything — it is silently lost.

17. Props silently ignored in dropdown path

When dropdownItems is provided, className, href, and the spread ...props (including data-testid, aria-label, etc.) are all destructured but never applied to any element in the dropdown branch. They are silently dropped with no warning.

19. cloneElement usage is fragile

BreadcrumbItem uses cloneElement to merge props into the as element. React docs recommend alternatives like render props or composition patterns.

20. Array index as key in dropdown items

dropdownItems.map((dropdownItem, dropdownIndex) => ...) uses index as key — if items reorder, React won't reconcile correctly.

22. Manual separator insertion

Users must manually add <Breadcrumb.Separator> between each item. Consider an autoSeparator prop or auto-inserting separators between children.

Moved to Cross-Cutting Issues

The following items have been moved to cross-cutting issues that address them across all components:

Metadata

Metadata

Assignees

No one assigned

    Labels

    componentIndividual component-level issueenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions