Breadcrumb
Pokazuje, gdzie w hierarchii znajduje się bieżąca strona, i jednym kliknięciem prowadzi na każdy wyższy poziom.
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
export default function BreadcrumbDemo() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs" />}>Dokumentacja</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs/components" />}>
Komponenty
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}Anatomia
- 1LinkPoziom nadrzędny. Używa tytułu strony docelowej.
- 2SeparatorDomyślnie dyskretny ukośnik; ukryty przed technologiami wspomagającymi.
- 3Bieżąca stronaOstatni element. Nie jest linkiem, ma atrybut
aria-current="page".
Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/breadcrumb.jsonUżycie
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/docs" />}>Docs</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>BreadcrumbLink domyślnie renderuje <a>; przekaż link swojego routera przez render, aby zachować nawigację po stronie klienta. Ostatni element to BreadcrumbPage — bieżąca lokalizacja, która nie jest linkiem.
Przykłady
Domyślny
prfct oddziela poziomy subtelnym ukośnikiem. Czyta się go jak ścieżkę, zajmuje mniej miejsca niż strzałka i nie konkuruje z linkami.
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
export default function BreadcrumbDemo() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs" />}>Dokumentacja</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs/components" />}>
Komponenty
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}Własny separator
Przekaż dowolną ikonę jako dziecko BreadcrumbSeparator. Strzałki pasują do ustawień i hierarchii plików, w których ścieżka oznacza schodzenie w głąb.
import { ChevronRightIcon } from "lucide-react"
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
export default function BreadcrumbCustomSeparator() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs" />}>
Ustawienia
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<ChevronRightIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs" />}>
Przestrzeń robocza
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<ChevronRightIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Członkowie</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}Zwinięta ścieżka
Gdy ścieżka ma więcej niż cztery poziomy, zostaw poziom główny i dwa ostatnie, a środek zwiń do menu rozwijanego Dropdown Menu ukrytego za wielokropkiem. Nic nie staje się nieosiągalne.
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
const hidden = [
{ title: "Inżynieria", href: "/pl/docs" },
{ title: "Platforma", href: "/pl/docs" },
{ title: "Design system", href: "/pl/docs" },
]
export default function BreadcrumbCollapsed() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs" />}>Acme</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger
aria-label="Pokaż ukrytą ścieżkę"
className="rounded-md text-muted-foreground focus-ring transition-colors duration-fast hover:bg-accent hover:text-foreground data-popup-open:bg-accent"
>
<BreadcrumbEllipsis />
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-44">
<DropdownMenuGroup>
{hidden.map((item) => (
<DropdownMenuItem
key={item.title}
render={<Link href={item.href} />}
>
{item.title}
</DropdownMenuItem>
))}
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink render={<Link href="/pl/docs" />}>
Komponenty
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}Z ikonami
Ikona domu może zastąpić poziom główny, gdy nazwa produktu jest już widoczna w nagłówku — nadaj jej wtedy aria-label. Ikony w środku ścieżki powinny oznaczać rodzaj poziomu, a nie go ozdabiać.
import { FolderIcon, HouseIcon } from "lucide-react"
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
export default function BreadcrumbWithIcon() {
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink
render={<Link href="/pl" />}
aria-label="Strona główna"
className="flex items-center"
>
<HouseIcon className="size-4" />
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink
render={<Link href="/pl/docs" />}
className="flex items-center gap-1.5"
>
<FolderIcon className="size-4" />
Projekty
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Strona marketingowa</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}Przełącznik
W aplikacjach ostatni segment może jednocześnie przełączać między elementami tego samego poziomu — projektami w zespole, gałęziami w repozytorium. Wyzwalacz wygląda jak bieżąca strona, a menu oznacza aktywny element.
"use client"
import * as React from "react"
import { ChevronsUpDownIcon } from "lucide-react"
import Link from "next/link"
import { Badge } from "@/components/ui/badge"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
const projects = ["Strona marketingowa", "Aplikacja mobilna", "Design system"]
export default function BreadcrumbSwitcher() {
const [current, setCurrent] = React.useState("Design system")
return (
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink
render={<Link href="/pl/docs" />}
className="font-medium text-foreground"
>
Acme
</BreadcrumbLink>
<Badge variant="secondary" size="sm">
Pro
</Badge>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1.5 rounded-md px-1.5 py-1 font-medium text-foreground focus-ring transition-colors duration-fast hover:bg-accent data-popup-open:bg-accent">
<span aria-current="page">{current}</span>
<ChevronsUpDownIcon className="size-3.5 text-muted-foreground" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-52">
<DropdownMenuGroup>
<DropdownMenuLabel>Projekty</DropdownMenuLabel>
<DropdownMenuRadioGroup
value={current}
onValueChange={setCurrent}
>
{projects.map((project) => (
<DropdownMenuRadioItem key={project} value={project}>
{project}
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}Wytyczne
Kiedy używać
- W hierarchiach o głębokości co najmniej trzech poziomów — w dokumentacji, systemach plików, ustawieniach, kategoriach sklepów internetowych.
- Gdy ktoś trafia głęboko w strukturę z wyszukiwarki lub udostępnionego linku i musi się zorientować, gdzie jest.
Kiedy nie używać
- W płaskich serwisach z jednym lub dwoma poziomami — wystarczy tytuł strony.
- Do pokazywania kolejnych kroków lub historii — ścieżka nawigacji opisuje położenie, a nie drogę, którą ktoś przeszedł. W procesach wieloetapowych użyj wskaźnika kroków.
- Jako nawigacji głównej. Ścieżka nawigacji uzupełnia Sidebar lub Navigation Menu, ale ich nie zastępuje.
Treść
Każdy element używa tytułu strony docelowej, skróconego tylko w razie potrzeby. Nie linkuj bieżącej strony, nie powtarzaj jej tuż poniżej jako tytułu strony w innym brzmieniu i nie dodawaj separatora na końcu.
Umiejscowienie
Umieść ścieżkę nawigacji nad tytułem strony, wyrównaną z nim do lewej, w kolumnie treści. Na wąskich ekranach zwiń ją do poziomu głównego i nadrzędnego albo pokaż tylko link Wróć do poziomu wyżej.
Dostępność
- Punkt orientacyjny.
Breadcrumbrenderuje<nav>z etykietą Ścieżka nawigacji (tłumaczoną przez LocaleProvider), więc użytkownicy czytników ekranu mogą przejść do niego z listy punktów orientacyjnych. - Kolejność. Elementy tworzą listę uporządkowaną (
<ol>), która przekazuje hierarchię i liczbę poziomów. - Bieżąca strona.
BreadcrumbPagerenderuje<span>zaria-current="page", który oznacza go jako bieżącą lokalizację. To zwykły tekst, a nie link, więc nie przyjmuje fokusu. - Separatory mają
aria-hidden, więc nie są odczytywane między poziomami. - Zwinięte poziomy wymagają wyzwalacza z dostępną nazwą, np. Pokaż ukrytą ścieżkę.
| Klawisz | Działanie |
|---|---|
Tab | Przenosi fokus kolejno po linkach. Bieżąca strona jest pomijana. |
Enter | Otwiera link, na którym jest fokus. |
Dokumentacja API
Breadcrumb
Punkt orientacyjny <nav>. Przyjmuje wszystkie propsy elementu <nav>; nadpisz aria-label, gdy strona ma więcej niż jedną ścieżkę nawigacji.
BreadcrumbList i BreadcrumbItem
BreadcrumbList to <ol>, który układa ścieżkę i zawija ją na wąskich ekranach. BreadcrumbItem to <li>, który wyrównuje swoją zawartość — link, bieżącą stronę lub wyzwalacz menu.
BreadcrumbLink
BreadcrumbPage
Bieżąca lokalizacja. Renderuje <span> z aria-current="page".
BreadcrumbSeparator
BreadcrumbEllipsis
Znak ⋯ dla zwiniętych poziomów, odczytywany jako Więcej w języku ustawionym przez LocaleProvider. W wyzwalaczu nadaj samemu wyzwalaczowi nazwę, która mówi, co odsłania.