forked from Talenttrust/Talenttrust-Frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBreadcrumbs.tsx
More file actions
82 lines (75 loc) · 2.53 KB
/
Copy pathBreadcrumbs.tsx
File metadata and controls
82 lines (75 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import React from 'react';
import Link from 'next/link';
/** A single breadcrumb entry. Omit `href` for the current (final) crumb. */
export type BreadcrumbItem = {
/** Visible label for this crumb. */
label: string;
/**
* Navigation target. When provided the crumb renders as a Next.js `<Link>`.
* Omit for the final crumb, which renders as plain text with `aria-current="page"`.
*/
href?: string;
};
export type BreadcrumbsProps = {
/** Ordered list of crumbs from root to current page. */
items: BreadcrumbItem[];
};
/**
* Accessible breadcrumb navigation component.
*
* Renders a `<nav aria-label="Breadcrumb">` containing an `<ol>` of crumbs.
* Ancestral crumbs are wrapped in Next.js `<Link>`; the final crumb is plain
* text marked with `aria-current="page"`. Visual separators are hidden from
* assistive technologies via `aria-hidden`.
*
* @example
* ```tsx
* <Breadcrumbs
* items={[
* { label: 'Dashboard', href: '/' },
* { label: 'Contracts', href: '/contracts' },
* { label: 'Contract #42' },
* ]}
* />
* ```
*/
const Breadcrumbs = ({ items }: BreadcrumbsProps) => {
if (items.length === 0) return null;
return (
<nav aria-label="Breadcrumb">
<ol className="flex flex-wrap items-center gap-1 text-sm text-slate-500">
{items.map((item, index) => {
const isLast = index === items.length - 1;
return (
<li key={`${item.label}-${index}`} className="flex items-center gap-1">
{/* Separator — hidden from screen readers */}
{index > 0 && (
<span aria-hidden="true" className="select-none text-slate-400">
/
</span>
)}
{isLast ? (
// Current page: plain text, no link, aria-current for AT
<span
aria-current="page"
className="font-medium text-slate-900 truncate max-w-[16rem]"
>
{item.label}
</span>
) : (
// Ancestor: linked crumb
<Link
href={item.href ?? '/'}
className="truncate max-w-[16rem] transition hover:text-slate-900 hover:underline rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"
>
{item.label}
</Link>
)}
</li>
);
})}
</ol>
</nav>
);
};
export default Breadcrumbs;