@mshafiqyajid/react-breadcrumb
Headless breadcrumb hook and styled component. Collapsible items with expand animation, three separator styles, icon support per item, link/button/span rendering, ARIA-compliant.
Playground #
Props
TSX
import { BreadcrumbStyled } from "@mshafiqyajid/react-breadcrumb/styled";
import "@mshafiqyajid/react-breadcrumb/styles.css";
<BreadcrumbStyled />Install #
npm install @mshafiqyajid/react-breadcrumb Quick start #
import { BreadcrumbStyled } from "@mshafiqyajid/react-breadcrumb/styled";
import "@mshafiqyajid/react-breadcrumb/styles.css";
const items = [
{ label: "Home", href: "/" },
{ label: "Products", href: "/products" },
{ label: "Smartphones" },
];
<BreadcrumbStyled items={items} /> Separators #
Three built-in separators: "chevron" (โบ, default), "slash" (/), and "arrow" (โ). You can also pass any ReactNode for a custom separator.
<BreadcrumbStyled items={items} separator="chevron" />
<BreadcrumbStyled items={items} separator="slash" />
<BreadcrumbStyled items={items} separator="arrow" />
<BreadcrumbStyled items={items} separator={<span>ยท</span>} /> Collapsible #
Set maxItems to collapse long breadcrumbs. When collapsed, only the first and last items are shown with an expand button (โฆ) in between. Clicking it reveals all items with a staggered fade-in animation.
<BreadcrumbStyled items={items} maxItems={2} /> Item types #
Each item renders the most semantically appropriate element based on its props:
const items = [
// <a href="..."> โ link
{ label: "Home", href: "/" },
// <button type="button"> โ click handler only
{ label: "Products", onClick: () => navigate("/products") },
// <span> โ no href, no onClick, not last
{ label: "Region" },
// <span aria-current="page"> โ last item is always a span
{ label: "Smartphones" },
]; Icons #
Add an icon to any item. The icon renders before the label.
const items = [
{ label: "Home", href: "/", icon: <HomeIcon /> },
{ label: "Products", href: "/products", icon: <BoxIcon /> },
{ label: "Smartphones" },
];
<BreadcrumbStyled items={items} /> Sizes #
<BreadcrumbStyled items={items} size="sm" />
<BreadcrumbStyled items={items} size="md" />
<BreadcrumbStyled items={items} size="lg" /> Headless #
import { useBreadcrumb } from "@mshafiqyajid/react-breadcrumb";
function MyBreadcrumb({ items }) {
const {
navProps,
visibleItems,
isCollapsed,
expand,
getItemProps,
} = useBreadcrumb({ items, maxItems: 3 });
return (
<nav {...navProps}>
<ol style={{ display: "flex", gap: "0.5rem", listStyle: "none" }}>
{visibleItems.map(({ item, originalIndex, isEllipsis }, i) => (
<li key={isEllipsis ? "e" : originalIndex}>
{i > 0 && <span aria-hidden="true"> / </span>}
{isEllipsis ? (
<button onClick={expand}>โฆ</button>
) : getItemProps(originalIndex).isLast ? (
<span aria-current="page">{item.label}</span>
) : item.href ? (
<a href={item.href}>{item.label}</a>
) : (
<span>{item.label}</span>
)}
</li>
))}
</ol>
</nav>
);
} API โ BreadcrumbStyled #
| Prop | Type | Default | Description |
|---|---|---|---|
| items | BreadcrumbItem[] | โ | Array of breadcrumb items (required) |
| separator | "chevron" | "slash" | "arrow" | ReactNode | "chevron" | Separator rendered between items |
| maxItems | number | โ | Collapse to first + ellipsis + last when length exceeds this |
| expandLabel | string | "Show all" | Accessible label for the expand button |
| size | "sm" | "md" | "lg" | "md" | Font size |
| className | string | โ | Extra class on the root element |
| style | CSSProperties | โ | Inline style override |
API โ BreadcrumbItem #
| Key | Type | Description |
|---|---|---|
| label | ReactNode | Item label (required) |
| href | string | If set, renders an <a> element |
| onClick | () => void | Click handler. Renders <button> when no href |
| icon | ReactNode | Leading icon rendered before the label |
API โ useBreadcrumb #
| Key | Type | Description |
|---|---|---|
| navProps | object | role="navigation" + aria-label="Breadcrumb" |
| listProps | object | Props to spread on the <ol> |
| visibleItems | VisibleItem[] | Items to render (respects collapse state) |
| isCollapsed | boolean | Whether items are currently collapsed |
| expand | () => void | Reveal all items |
| getItemProps | (index: number) => object | Returns aria-current, isLast, item for the original index |