packages/react-components/react-breadcrumb/library/docs/Spec.md
Breadcrumbs should be used as a navigational aid in your app or site. They indicate the current page's location within a hierarchy and help the user understand where they are in relation to the rest of that hierarchy.
import { Breadcrumb, IBreadcrumbItem } from '@fluentui/react/lib/Breadcrumb';
const items: IBreadcrumbItem[] = [
{ text: 'Files', key: 'Files', onClick: _onBreadcrumbItemClicked },
{ text: 'This is folder 1', key: 'f1', onClick: _onBreadcrumbItemClicked },
{ text: 'This is folder 2 with a long name', key: 'f2', onClick: _onBreadcrumbItemClicked },
{ text: 'This is folder 3 long', key: 'f3', onClick: _onBreadcrumbItemClicked },
{ text: 'This is non-clickable folder 4', key: 'f4' },
{ text: 'This is folder 5', key: 'f5', onClick: _onBreadcrumbItemClicked, isCurrentItem: true },
];
export const BreadcrumbStaticExample: React.FunctionComponent = () => {
return (
<Breadcrumb
items={items}
maxDisplayedItems={3}
ariaLabel="Breadcrumb with static width"
overflowAriaLabel="More items"
/>
);
};
function _onBreadcrumbItemClicked(ev: React.MouseEvent<HTMLElement>, item: IBreadcrumbItem): void {
console.log(`Breadcrumb item with key "${item.key}" has been clicked.`);
}
import { Breadcrumb } from '@fluentui/react-northstar';
import { ChevronEndMediumIcon } from '@fluentui/react-icons-northstar';
const BreadcrumbExampleIconDivider = props => (
<Breadcrumb aria-label="breadcrumb">
<Breadcrumb.Item>
<Breadcrumb.Link href="">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Divider>
<ChevronEndMediumIcon />
</Breadcrumb.Divider>
<Breadcrumb.Item>
<Breadcrumb.Link href="">Store</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Divider>
<ChevronEndMediumIcon />
</Breadcrumb.Divider>
<Breadcrumb.Item aria-current="page">T-shirt</Breadcrumb.Item>
</Breadcrumb>
);
| Purpose | Fabric | Northstar | Matching? |
|---|---|---|---|
| Breadcrumb is a component that indicates the path of the current page | Breadcrumb | Breadcrumb | ⚠️ |
| BreadcrumbItem an actionable item within a Breadcrumb | BreadcrumbItem | ❌ | |
| BreadcrumbDivider divides BreadcrumbItem components within Breadcrumb | BreadcrumbDivider | ❌ | |
| BreadcrumbLink represents a anchor to be used inside the Breadcrumb | BreadcrumbLink | ❌ |
const BreadcrumbV9Example = props => (
<Breadcrumb aria-label="breadcrumb">
<BreadcrumbItem>
<BreadcrumbButton href="#">
Home
</BreadcrumbButton>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbButton href="#">
Gallery
</BreadcrumbButton>
</BreadcrumbItem>
<BreadcrumbItem current={true}>
<BreadcrumbButton href="#">
About
</BreadcrumbButton>
</BreadcrumbItem>
</Breadcrumb>
</>
);
BreadcrumbButton uses @fluentui/react-button component under the hood. It's semantically a Link but has appearance of subtle Button.Breadcrumb items can have icons.
Breadcrumb can have the following sizes: small, medium and large.
Tooltips appear on collapsed menu or truncated name of item.
Dropdown contains collapsed items.
| Component | Purpose |
|---|---|
| Breadcrumb | Wrapper for the Breadcrumb component. Contains nav and ol elements. |
| BreadcrumbDivider | Divider component |
| BreadcrumbItem | li element. Can contain BreadcrumbButton component. |
| BreadcrumbButton | Breadcrumb Button |
<nav aria-label="breadcrumb">
<ol>
{children}
</ol>
</nav>
nav elementol element| Property | Values | Default | Purpose |
|---|---|---|---|
| focusMode | tab, arrow | tab | Sets focus mode |
| size | small, medium, large | medium | Defines size of the Breadcrumb |
BreadcrumbItem is a container for BreadcrumbButton.
<li>
{children}
</li>
Link
<li>
<a href="#">
{children}
</a>
</li>
Button (used only as OverflowMenu)
<li>
<button>
{children}
</button>
</li>
Usage
<BreadcrumbItem>
<BreadcrumbButton href="#">
Item 1
</BreadcrumbButton>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbButton href="#">
Item 2
</BreadcrumbButton>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbButton href="#">
Item 3
</BreadcrumbButton>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbButton icon={<IconComponent />}>Item</BreadcrumbButton>
</BreadcrumbItem>
<li class="fui-BreadcrumbDivider">
<svg
aria-hidden="true"
fill="currentColor"
height="16"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M5.65 3.15a.5.5 0 000 .7L9.79 8l-4.14 4.15a.5.5 0 00.7.7l4.5-4.5a.5.5 0 000-.7l-4.5-4.5a.5.5 0 00-.7 0z" fill="currentColor" />
</svg>
</li>
<Breadcrumb>
<BreadcrumbItem>Item</BreadcrumbItem>
<BreadcrumbDivider />
<BreadcrumbItem>Item</BreadcrumbItem>
</Breadcrumb>
<BreadcrumbButton href="#">Item</BreadcrumbButton>
| Property | Values | Default | Purpose |
|---|---|---|---|
| current | boolean | false | Indicates current page |
| icon | slot | Sets icon |
The default position of ellipses should be the second element because from a UX perspective root folder should be shown.
maxDisplayedItems prop is provided and number of items is bigger than maxDisplayedItems.By default Overflow component is used to hide items when there's not enough space.
Also, maxDisplayedItems prop can be provided. By default maxDisplayedItems is equal 6 elements.
This logic can be combined with Overflow component.
Getting overflowItems is handled by partitionBreadcrumbItems method.
const DEFAULT_OVERFLOW_INDEX = 1;
export type PartitionBreadcrumbItemsOptions<T> = {
items: readonly T[];
maxDisplayedItems?: number;
overflowIndex?: number;
};
export type PartitionBreadcrumbItems<T> = {
startDisplayedItems: readonly T[];
overflowItems?: readonly T[];
endDisplayedItems?: readonly T[];
};
/**
* Get the displayed items and overflow items based on the array of BreadcrumbItems.
*
* @param options - Configure the partition options
*
* @returns Three arrays split into displayed items and overflow items based on maxDisplayedItems.
*/
export const partitionBreadcrumbItems = <T>(
options: PartitionBreadcrumbItemsOptions<T>,
): PartitionBreadcrumbItems<T> => {
// implementation
return {
startDisplayedItems,
overflowItems,
endDisplayedItems,
};
};
In case if there are no overflowItems original array is returned.
const { startDisplayedItems, overflowItems, endDisplayedItems } = partitionBreadcrumbItems({
items,
maxDisplayedItems: 4,
overflowIndex: 2,
});
<Breadcrumb size="large">
{startDisplayedItems.map(item => renderButton(item))}
{overflowItems && renderMenu(overflowItems)}
{endDisplayedItems &&
endDisplayedItems.map(item => {
const isLastItem = item.key === buttonItems.length - 1;
return renderButton(item, isLastItem);
})}
</Breadcrumb>;
It should be done by the partners using JSX composition.
For Menu @fluentui/react-menu component should be used.
maxDisplayedItems and overflowIndex are part of partitionBreadcrumbItems which is helper in Breadcrumb utils.
Currently truncation of long names should be done by partners. It's recommended to truncate a name when there are more than 30 symbols.
Breadcrumb can have the folloing states:
Tooltip is shown onHover on collapsed menu or items with long names.
Tooltipls can be multiline. It is recommended to use content no longer than 80 symbols. Items have tooltips when their names are longer than 30 symbols.
When navigating via keyboard, focus will be place initially on the first breadcrumb item. Either tab key (default) or left and right arrow can be used to move through the breadcrumb items.
If the overflow button is in focus, Enter, Arrow down or Space activate the overflow menu.
Use the tab key to navigate to the first item of the string and Tab or arrow keys to move through previous and next items.
Each item is conisdered a ListItem with nested links.
Use button roles for Overflow menu.