Skip to content

[Bug]: BreadcrumbButtonBaseProps collapses the ARIA button union, so href is not assignable #36645

Description

Component

Breadcrumb

Package version

@fluentui/react-breadcrumb 9.4.5 (repo master; also reproduces against the version
@fluentui/react-components depends on).

React version

18.3.1

Environment

node v22.12.0, TypeScript as pinned by the repo root
@fluentui/react-breadcrumb 9.4.5
@fluentui/react-headless-components-preview 0.2.5

Current Behavior

packages/react-components/react-breadcrumb/library/src/components/BreadcrumbButton/BreadcrumbButton.types.ts:28
declares:

export type BreadcrumbButtonBaseProps = Omit<BreadcrumbButtonProps, 'size'>;

BreadcrumbButtonProps includes ComponentProps<ButtonSlots>, whose root is
ARIAButtonSlotProps — a distributive union over as: 'button' | 'a'. A plain Omit is not
distributive: it collapses the union into a single object type keyed on the intersection of its
members, and the anchor arm's href disappears from the resulting type.

The consequence is that the anchor spelling of BreadcrumbButton — the spelling the component's own
Default story uses — does not type-check against the base props type.

This is type-level only. Runtime rendering is unaffected.

Expected Behavior

BreadcrumbButtonBaseProps should preserve the distributive union, so that both arms
(as="button" and as="a" with href) remain assignable. @fluentui/react-button already does
exactly this for the same reason — Button.types.ts:72,84 use DistributiveOmit.

Reproduction

Minimal, in any TypeScript file in a workspace with @fluentui/react-breadcrumb installed:

import type { BreadcrumbButtonBaseProps } from '@fluentui/react-breadcrumb';

// Errors today: `href` does not exist on the collapsed type.
const props: BreadcrumbButtonBaseProps = { as: 'a', href: '/somewhere' };

A branch demonstrating the failure and the fix is available; happy to add a StackBlitz if the
triage flow needs one, though the failure is a compiler error rather than a runtime one and the
snippet above is sufficient to see it.

Steps to reproduce

  1. Add the snippet above to a .ts file in a project that depends on @fluentui/react-breadcrumb.
  2. Run tsc --noEmit.
  3. Observe the assignment error on href.

Discovery context

Found during pixel-level verification of a styling layer built over
@fluentui/react-headless-components-preview. That work rebuilds each component's public prop
surface against its @fluentui/react-components twin and compiles the twin's own stories against
both, which is what surfaced this: the Breadcrumb Default story's anchor spelling would not compile
against the base props type.

Worth recording so this issue is not read as broader than it is: two further losses were originally
attributed to the same Omit (iconPosition, and a { href }-only object literal). Both were
re-measured and withdrawn — they fail against the Griffel surface too, for an unrelated reason
(TypeScript weak-type detection). Only the union collapse described above is a defect.

Proposed fix

Change the Omit to DistributiveOmit, matching @fluentui/react-button:

export type BreadcrumbButtonBaseProps = DistributiveOmit<BreadcrumbButtonProps, 'size'>;

One line, plus the regenerated etc/react-breadcrumb.api.md. No runtime change, and the widened
type is strictly a superset of the current one, so no existing consumer's code stops compiling.

A working implementation is included in PR #[WINDMOD-PR-NUMBER] (commit b95a4152c4); happy to
split it into a standalone PR against this issue if that is easier to take.

Suggested severity

Low - Has or doesn't need a workaround (the workaround is casting, which is exactly what a consumer
should not have to do).

Are you willing to submit a PR to fix?

yes

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions