useBreadcrumbs

Provides the behavior and accessibility implementation for a breadcrumbs component. Breadcrumbs display a heirarchy of links to the current page or resource in an application.

installyarn add @react-aria/breadcrumbs
version3.0.0-alpha.1
usageimport {useBreadcrumbs, useBreadcrumbItem} from '@react-aria/breadcrumbs'

API#


useBreadcrumbs<T>(props: AriaBreadcrumbsProps<T>): BreadcrumbsAriauseBreadcrumbItem(props: AriaBreadcrumbItemProps): BreadcrumbItemAria

Features#


Breadcrumbs provide a list of links to parent pages of the current page in heirarchical order. useBreadcrumbs and useBreadcrumbItem help implement these in an accessible way.

Anatomy#


Breadcrumbs consist of a navigation landmark element and a list of links. The last link represents the current page in the heirarchy, with the previous links representing the parent pages of the current page. Each of these parent links can be clicked, tapped, or triggered via the Enter key to navigate to that page. Optionally, breadcrumbs can be used in place of a page title, in which case the last breadcrumb acts as a heading.

useBreadcrumbs returns props to be spread onto the navigation element:

NameTypeDescription
breadcrumbsPropsHTMLAttributes<HTMLDivElement>Props for the bradcrumbs navigation element.

useBreadcrumbItem returns props to spread onto the individual breadcrumb links:

NameTypeDescription
breadcrumbItemPropsHTMLAttributes<HTMLDivElement>Props for the breadcrumb item link element.

Example#


This example displays a basic list of breadcrumbs using an HTML <nav> element, and a <ol> for the list of links. Each link is a span because we are handling the interactions locally via onPress. useBreadcrumbItem automatically handles exposing these spans as links to assistive technology.

The chevrons between each link are rendered using a span with aria-hidden="true" so that screen readers do not pick them up. You could also render them similarly using SVG icons, CSS :after, or other techniques.

The last link is non-interactive since it represents the current page. This is passed to the last breadcrumb item by cloning the element and adding the isCurrent prop.

function Breadcrumbs(props) {
  let {breadcrumbsProps} = useBreadcrumbs(props);
  let children = React.Children.toArray(props.children);

  return (
    <nav {...breadcrumbsProps}>
      <ol style={{display: 'flex', listStyle: 'none'}}>
        {children.map((child, i) => 
          React.cloneElement(child, {isCurrent: i === children.length - 1})
        )}
      </ol>
    </nav>
  )
}

function BreadcrumbItem(props) {
  let {breadcrumbItemProps} = useBreadcrumbItem({...props, elementType: 'span'});
  return (
    <li>
      <span
        {...breadcrumbItemProps}
        style={{
          color: 'dodgerblue',
          textDecoration: props.isCurrent ? null : 'underline',
          fontWeight: props.isCurrent ? 'bold' : null,
          cursor: props.isCurrent ? 'default' : 'pointer'
        }}>
        {props.children}
      </span>
      {!props.isCurrent &&
        <span aria-hidden="true" style={{padding: '0 5px'}}>{'›'}</span>
      }
    </li>
  );
}

<Breadcrumbs>
  <BreadcrumbItem onPress={() => alert('Pressed Folder 1')}>Folder 1</BreadcrumbItem>
  <BreadcrumbItem onPress={() => alert('Pressed Folder 2')}>Folder 2</BreadcrumbItem>
  <BreadcrumbItem>Folder 3</BreadcrumbItem>
</Breadcrumbs>

This example is similar to the previous one, except the individual breadcrumbs are native navigation links to other pages rather than handled by JavaScript.

function Breadcrumbs(props) {
  // Same as in the previous example...
}

function BreadcrumbItem(props) {
  let {breadcrumbItemProps} = useBreadcrumbItem(props);
  return (
    <li>
      <a
        {...breadcrumbItemProps}
        href={props.href}
        style={{
          color: 'dodgerblue',
          fontWeight: props.isCurrent ? 'bold' : null,
          cursor: props.isCurrent ? 'default' : 'pointer'
        }}>
        {props.children}
      </a>
      {!props.isCurrent &&
        <span aria-hidden="true" style={{padding: '0 5px'}}>{'›'}</span>
      }
    </li>
  );
}

<Breadcrumbs>
  <BreadcrumbItem href="/">Home</BreadcrumbItem>
  <BreadcrumbItem href="/react-aria">React Aria</BreadcrumbItem>
  <BreadcrumbItem>useBreadcrumbs</BreadcrumbItem>
</Breadcrumbs>

If you use breadcrumbs in the context where a heading would normally be used, you can pass the isHeading prop to the breadcrumb items and the last breadcrumb will be exposed as a heading to assistive technology. headingAriaLevel can also be used to set the level of that heading.

function Breadcrumbs(props) {
  let {breadcrumbsProps} = useBreadcrumbs(props);
  let children = React.Children.toArray(props.children);

  return (
    <nav {...breadcrumbsProps}>
      <ol style={{display: 'flex', listStyle: 'none'}}>
        {children.map((child, i) => 
          React.cloneElement(child, {
            isCurrent: i === children.length - 1,
            isHeading: true,
            headingAriaLevel: 3
          })
        )}
      </ol>
    </nav>
  );
}

function BreadcrumbItem(props) {
  // Same as in the previous example...
}

<Breadcrumbs>
  <BreadcrumbItem href="/">Home</BreadcrumbItem>
  <BreadcrumbItem href="/react-aria">React Aria</BreadcrumbItem>
  <BreadcrumbItem>useBreadcrumbs</BreadcrumbItem>
</Breadcrumbs>