packages/react-aria/docs/breadcrumbs/useBreadcrumbs.mdx
{/* Copyright 2020 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */}
import {Layout} from '@react-spectrum/docs'; export default Layout;
import docs from 'docs:@react-aria/breadcrumbs'; import {HeaderInfo, FunctionAPI, TypeContext, InterfaceType, PageDescription} from '@react-spectrum/docs'; import {Keyboard} from '@react-spectrum/text'; import packageData from '@react-aria/breadcrumbs/package.json'; import Anatomy from './anatomy.svg';
<PageDescription>{docs.exports.useBreadcrumbs.description}</PageDescription>
<HeaderInfo packageData={packageData} componentNames={['useBreadcrumbs', 'useBreadcrumbItem']} sourceData={[ {type: 'W3C', url: 'https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/'} ]} />
Breadcrumbs provide a list of links to parent pages of the current page in hierarchical order.
useBreadcrumbs and useBreadcrumbItem help implement these in an accessible way.
<a> elements or custom element types via ARIABreadcrumbs consist of a navigation landmark element and a list of links, typically with a visual separator icon between each item. The last link represents the current page in the hierarchy, 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 <Keyboard>Enter</Keyboard> key to navigate to that page.
useBreadcrumbs returns props to be spread onto the navigation element:
<TypeContext.Provider value={docs.links}> <InterfaceType properties={docs.links[docs.exports.useBreadcrumbs.return.id].properties} /> </TypeContext.Provider>
useBreadcrumbItem returns props to spread onto the individual breadcrumb links:
<TypeContext.Provider value={docs.links}> <InterfaceType properties={docs.links[docs.exports.useBreadcrumbItem.return.id].properties} /> </TypeContext.Provider>
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.
import {useBreadcrumbs, useBreadcrumbItem} from '@react-aria/breadcrumbs';
function Breadcrumbs(props) {
let {navProps} = useBreadcrumbs(props);
let childCount = React.Children.count(props.children);
return (
<nav {...navProps}>
<ol style={{display: 'flex', listStyle: 'none', margin: 0, padding: 0}}>
{React.Children.map(props.children, (child, i) =>
React.cloneElement(child, {isCurrent: i === childCount - 1})
)}
</ol>
</nav>
)
}
function BreadcrumbItem(props) {
let ref = React.useRef(null);
let {itemProps} = useBreadcrumbItem({...props, elementType: 'span'}, ref);
return (
<li>
<span
{...itemProps}
ref={ref}
style={{
color: props.isDisabled ? 'var(--gray)' : 'var(--blue)',
textDecoration: props.isCurrent || props.isDisabled ? 'none' : 'underline',
fontWeight: props.isCurrent ? 'bold' : null,
cursor: props.isCurrent || props.isDisabled ? '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>
To render breadcrumbs that navigate to other pages rather than handle events via onPress, use an <a> element
for each BreadcrumbItem. This is the default elementType, so the option can be omitted from useBreadcrumbItem.
///- begin collapse -///
function Breadcrumbs(props) {
let {navProps} = useBreadcrumbs(props);
let childCount = React.Children.count(props.children);
return (
<nav {...navProps}>
<ol style={{display: 'flex', listStyle: 'none', margin: 0, padding: 0}}>
{React.Children.map(props.children, (child, i) =>
React.cloneElement(child, {isCurrent: i === childCount - 1})
)}
</ol>
</nav>
);
}
///- end collapse -///
function BreadcrumbItem(props) {
let ref = React.useRef(null);
let {itemProps} = useBreadcrumbItem(props, ref);
return (
<li>
<a
{...itemProps}
ref={ref}
href={props.href}
style={{
color: props.isDisabled ? 'var(--gray)' : 'var(--blue)',
textDecoration: props.isCurrent || props.isDisabled ? 'none' : 'underline',
fontWeight: props.isCurrent ? 'bold' : null,
cursor: props.isCurrent || props.isDisabled ? '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</BreadcrumbItem>
<BreadcrumbItem>useBreadcrumbs</BreadcrumbItem>
</Breadcrumbs>
The following examples show how to use the Breadcrumbs component created in the above examples.
Breadcrumbs can be disabled using the isDisabled prop, passed to each disabled BreadcrumbItem. This indicates that navigation is not currently available. When a breadcrumb is disabled, onPress will not be triggered, navigation will not occur, and links will be marked as aria-disabled for assistive technologies.
<Breadcrumbs>
<BreadcrumbItem href="#" isDisabled>Home</BreadcrumbItem>
<BreadcrumbItem href="#">React Aria</BreadcrumbItem>
<BreadcrumbItem>useBreadcrumbs</BreadcrumbItem>
</Breadcrumbs>