Breadcrumb
A trail that shows where the user is in the site hierarchy — with collapsing, an overflow menu and Next.js Link support.
'use client';
import { Breadcrumb } from '@akhatmirzo/ui';
import { House } from 'lucide-react';
export default function BreadcrumbBasic() {
return (
<Breadcrumb
items={[
{ label: 'Bosh sahifa', href: '#', icon: <House /> },
{ label: 'Mahsulotlar', href: '#mahsulotlar' },
{ label: 'Telefonlar', href: '#telefonlar' },
{ label: 'iPhone 17' },
]}
/>
);
}
Import
import { Breadcrumb } from '@akhatmirzo/ui';When to use
- Deep hierarchies — catalog → category → product, settings → account → security. Users get back to a higher level in one click.
- Place it above the page title, before the content.
- Skip it on flat sites — "Home → Current" alone adds little.
- Not for steps. To show a sequential process, use
Stepper.
Items
items is a list of { label, href?, icon?, onClick? }. The last item is the current page: it is
not a link and gets aria-current="page". An item with onClick but no href renders as a button.
Collapsing
When there are more than maxItems: first + … + the last maxItems - 2 (at least 1). Clicking
… opens the hidden pages in a DropdownMenu.
'use client';
import { Breadcrumb } from '@akhatmirzo/ui';
import { House } from 'lucide-react';
export default function BreadcrumbCollapse() {
return (
<Breadcrumb
maxItems={4}
items={[
{ label: 'Bosh sahifa', href: '#', icon: <House /> },
{ label: 'Katalog', href: '#katalog' },
{ label: 'Elektronika', href: '#elektronika' },
{ label: 'Telefonlar', href: '#telefonlar' },
{ label: 'Apple', href: '#apple' },
{ label: 'iPhone 17 Pro Max 256 GB' },
]}
/>
);
}
On phones (< 640px) the trail automatically collapses to … + parent + current. This is done with
a CSS breakpoint, so there is no SSR hydration mismatch. Long labels are truncated (links at 20ch,
the current page at 32ch).
Separator and size
separator accepts any ReactNode (default — a › chevron). size="sm" uses text-xs.
'use client';
import { Breadcrumb } from '@akhatmirzo/ui';
const items = [
{ label: 'Sozlamalar', href: '#' },
{ label: 'Hisob', href: '#hisob' },
{ label: 'Xavfsizlik' },
];
export default function BreadcrumbSeparator() {
return (
<div className="flex flex-col items-start gap-4">
<Breadcrumb items={items} separator="/" />
<Breadcrumb items={items} size="sm" />
</div>
);
}
Next.js Link
renderLink replaces <a> with your own link component. It is used inside the overflow menu too.
import Link from 'next/link';
import { Breadcrumb } from '@akhatmirzo/ui';
<Breadcrumb
items={[
{ label: 'Home', href: '/' },
{ label: 'Products', href: '/products' },
{ label: 'iPhone 17' },
]}
renderLink={(props) => <Link {...props} />}
/>;Props
Other <nav> attributes are passed through.
| Prop | Type | Default | Description |
|---|---|---|---|
itemsrequired | { label: ReactNode; href?: string; icon?: ReactNode; onClick?: (event) => void }[] | — | Trail items; the last one is the current page |
separator | ReactNode | — | Separator (default — `›` chevron) |
maxItems | number | — | When exceeded: first + `…` + the last ones; hidden items go to a menu |
renderLink | (props: { href, className, children, onClick }) => ReactNode | — | Custom link component such as Next `Link` |
size | 'sm' | 'md' | 'md' | `text-xs` / `text-sm` |
labels | { nav?: string; more?: string } | — | Defaults: "Sahifa yo'li", "Yashirilgan sahifalar" |
Data attributes
| Attribute | Where | Value |
|---|---|---|
data-size | nav | sm · md |
data-slot | parts | breadcrumb-item · breadcrumb-ellipsis · breadcrumb-separator |
data-viewport | … item | desktop · mobile |
Accessibility
- Structure.
<nav aria-label="Sahifa yo'li">wraps an ordered<ol>list. - The current page is not a link and is marked with
aria-current="page". - Separators are decorative —
aria-hidden, screen readers skip them. - The
…button hasaria-label="Yashirilgan sahifalar"andaria-haspopup="menu".Enter/Spaceopens it,↑ ↓move through items,Esccloses it and returns focus to the button. - The phone layout hides items with CSS (
display: none), so screen readers only read what is visible.