LayoutReact
The trail of pages from the site's root to the one the reader is on: a navigation landmark named "Breadcrumb" around an ordered list, root first.
Rendered by React 19.3.1
Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<Breadcrumb.Root>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link />
</Breadcrumb.Item>
<Breadcrumb.Separator>
<Breadcrumb.Page />
</Breadcrumb.Separator>
</Breadcrumb.List>
</Breadcrumb.Root>
// Not in this example: Breadcrumb.Collection, Breadcrumb.EllipsisExamples
Collapsed
Six levels through Collection with maxItems 4 and itemsAfterCollapse 2: the three in the middle go behind the ellipsis, whose button opens a menu of them as links.
Custom Separator
A chevron icon as the children of each Separator, flipped in a right-to-left page.
Router
Each Link renders through render as the app's link component, which stands in for a router: a click changes the route without loading a page, and the last level is an active Link.
API reference
7 props across 8 parts, in React syntax. className, style, render are listed once, under Shared props.
CollectionBreadcrumb.Collection
Calls its function child once per entry of the trail: each visible level, and one ellipsis entry for the levels a collapsed trail hides. Doesn’t render its own element.
| Prop | Type | Default |
|---|---|---|
itemsrequiredThe levels of the trail, root first. | readonly Item[] | — |
maxItemsCollapses the trail when it has more levels than this. | number | — |
itemsBeforeCollapseThe levels kept before the ellipsis. | number | 1 |
itemsAfterCollapseThe levels kept after the ellipsis, at least 1, so the last level always shows. | number | 1 |
childrenrequiredRenders one entry: { type: 'item', item, index, key, first, last } or | (entry: BreadcrumbEntry<Item>, index: number) => React.ReactNode | — |
EllipsisBreadcrumb.Ellipsis
Stands for the levels a collapsed trail hides, … unless it has children. It is hidden from assistive technology: name the trigger around it with the Collection entry's label. Renders a <span>.
ItemBreadcrumb.Item
One level of the trail: holds a Breadcrumb.Link, a Breadcrumb.Page, or the trigger around a Breadcrumb.Ellipsis. Renders a <li>.
LinkBreadcrumb.Link
A link to a level of the trail. Use render for a router's link. Renders an <a>.
| Prop | Type | Default |
|---|---|---|
activeWhether the link is the current page: it gets aria-current="page" and keeps its href. | boolean | false |
| Data attribute | Description |
|---|---|
data-active | Present when the link is the current page. |
ListBreadcrumb.List
The ordered list of levels, from the root to the current page. Renders an <ol>.
PageBreadcrumb.Page
The current page as text, not a link. It is not focusable. Renders a <span>.
RootBreadcrumb.Root
Groups all parts of the breadcrumb: a navigation landmark of the trail of links to the current page, named "Breadcrumb" unless it is given aria-label or aria-labelledby. Renders a <nav>.
| Prop | Type | Default |
|---|---|---|
labelsThe texts of the breadcrumb: root, the landmark's name when it has no aria-label or | Partial<BreadcrumbLabels> | — |
SeparatorBreadcrumb.Separator
The mark between two levels, / unless it has children. It is hidden from assistive technology. Renders a <li>.
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
| Keys | Does | Part |
|---|---|---|
| Tab | Moves to the next link, in DOM order; the trail adds no keys of its own | Link |
| Tab | Leaves the trail after the last link: the current page as text is not a Tab stop | Page |
| Enter | On the ellipsis button: opens the menu of the hidden levels, each a link | Collection |
Accessibility
| Part | Sets | So that |
|---|---|---|
| Root | a nav named "Breadcrumb" (labels, or your aria-label or aria-labelledby, with no default beside it) | the trail is a landmark a screen reader lists and jumps to; name each one when a page has two |
| List | an ol with no role and no ARIA | the levels are read as an ordered list, root first |
| Link | with active, aria-current="page" and data-active, keeping its href; an aria-current you give wins | the current page is read as "current page, link" and still opens in a new tab |
| Page | a span with aria-current="page", no role, no aria-disabled, no tabindex | the current page is not announced as a link no one can follow, and Tab skips it |
| Separator | an li with aria-hidden="true" | the marks are not read between the levels nor counted as list items, and never join a link's name |
| Ellipsis | aria-hidden="true", … unless it has children | the glyph is not read; the button around it carries the entry's label as its name |
| Collection | no element; the ellipsis entry's label with {count} replaced | the button for the hidden levels has a name in words |
Focus order
- Each link is a Tab stop in DOM order, root first; the ellipsis button sits in its level's place. Nothing takes focus on mount.
- The current page as
Pageis not a Tab stop; as anactiveLinkit is. - The menu of hidden levels moves focus into its popup when opened with the keyboard, and back to the ellipsis button when closed.