-
Notifications
You must be signed in to change notification settings - Fork 13
Description
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:
- Accessibility baseline (Accessibility baseline: aria attributes, roles, and semantic HTML #673)
- TypeScript strictness (TypeScript strictness: eliminate any, @ts-ignore, and export prop types #675)
- Standardize disabled state styling (Standardize disabled state styling #680)