Skip to content

Commit affaf28

Browse files
authored
Merge pull request #13854 from saurabhburade/shadcn-migrate/Breadcrumbs
Shadcn migration - Breadcrumbs
2 parents dfed703 + f2b38a7 commit affaf28

File tree

5 files changed

+161
-29
lines changed

5 files changed

+161
-29
lines changed

src/components/Breadcrumbs/index.tsx

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1+
import { Fragment } from "react"
12
import { useRouter } from "next/router"
23
import { useTranslation } from "next-i18next"
3-
import {
4-
Breadcrumb,
5-
BreadcrumbItem,
6-
BreadcrumbLink,
7-
type BreadcrumbProps as ChakraBreadcrumbProps,
8-
} from "@chakra-ui/react"
94

105
import type { Lang } from "@/lib/types"
116

12-
import { BaseLink } from "@/components/Link"
13-
147
import { isLangRightToLeft } from "@/lib/utils/translations"
158

16-
export type BreadcrumbsProps = ChakraBreadcrumbProps & {
9+
import {
10+
Breadcrumb,
11+
BreadcrumbItem,
12+
BreadcrumbLink,
13+
BreadcrumbList,
14+
BreadcrumbPage,
15+
BreadcrumbProps,
16+
BreadcrumbSeparator,
17+
} from "../ui/breadcrumb"
18+
19+
export type BreadcrumbsProps = BreadcrumbProps & {
1720
slug: string
1821
startDepth?: number
1922
}
@@ -65,23 +68,28 @@ const Breadcrumbs = ({ slug, startDepth = 0, ...props }: BreadcrumbsProps) => {
6568

6669
return (
6770
<Breadcrumb {...props} dir={dir}>
68-
{crumbs.map(({ fullPath, text }) => {
69-
const isCurrentPage = slug === fullPath
70-
return (
71-
<BreadcrumbItem key={fullPath} isCurrentPage={isCurrentPage}>
72-
<BreadcrumbLink
73-
// If current page, render as span since the `href` will not be
74-
// passed down to the child
75-
// ref: https://github.com/chakra-ui/chakra-ui/blob/v2/packages/components/src/breadcrumb/breadcrumb-link.tsx#L32
76-
as={isCurrentPage ? "span" : BaseLink}
77-
href={fullPath}
78-
textTransform="uppercase"
79-
>
80-
{text}
81-
</BreadcrumbLink>
82-
</BreadcrumbItem>
83-
)
84-
})}
71+
<BreadcrumbList>
72+
{crumbs.map(({ fullPath, text }) => {
73+
const normalizePath = (path) => path.replace(/\/$/, "") // Remove trailing slash
74+
const isCurrentPage = normalizePath(slug) === normalizePath(fullPath)
75+
return (
76+
<Fragment key={fullPath}>
77+
<BreadcrumbItem>
78+
{isCurrentPage ? (
79+
<BreadcrumbPage>{text}</BreadcrumbPage>
80+
) : (
81+
<BreadcrumbLink href={fullPath}>{text}</BreadcrumbLink>
82+
)}
83+
</BreadcrumbItem>
84+
{!isCurrentPage && (
85+
<BreadcrumbSeparator className="me-[0.625rem] ms-[0.625rem] text-gray-400">
86+
/
87+
</BreadcrumbSeparator>
88+
)}
89+
</Fragment>
90+
)
91+
})}
92+
</BreadcrumbList>
8593
</Breadcrumb>
8694
)
8795
}

src/components/ui/breadcrumb.tsx

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import * as React from "react"
2+
import Link, { LinkProps } from "next/link"
3+
import { LuChevronRight, LuMoreHorizontal } from "react-icons/lu"
4+
import { Slot } from "@radix-ui/react-slot"
5+
6+
import { cn } from "@/lib/utils/cn"
7+
8+
interface BreadcrumbProps extends React.ComponentPropsWithoutRef<"nav"> {
9+
separator?: React.ReactNode
10+
}
11+
const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(
12+
({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />
13+
)
14+
Breadcrumb.displayName = "Breadcrumb"
15+
16+
const BreadcrumbList = React.forwardRef<
17+
HTMLOListElement,
18+
React.ComponentPropsWithoutRef<"ol">
19+
>(({ className, ...props }, ref) => (
20+
<ol
21+
ref={ref}
22+
className={cn(
23+
"m-0 flex list-none flex-wrap items-center tracking-wider",
24+
className
25+
)}
26+
{...props}
27+
/>
28+
))
29+
BreadcrumbList.displayName = "BreadcrumbList"
30+
31+
const BreadcrumbItem = React.forwardRef<
32+
HTMLLIElement,
33+
React.ComponentPropsWithoutRef<"li">
34+
>(({ className, ...props }, ref) => (
35+
<li
36+
ref={ref}
37+
className={cn(
38+
"m-0 inline-flex items-center gap-1.5 tracking-wider",
39+
className
40+
)}
41+
{...props}
42+
/>
43+
))
44+
BreadcrumbItem.displayName = "BreadcrumbItem"
45+
46+
const BreadcrumbLink = React.forwardRef<
47+
HTMLAnchorElement,
48+
React.ComponentPropsWithoutRef<"a"> &
49+
LinkProps & {
50+
asChild?: boolean
51+
}
52+
>(({ asChild, className, ...props }, ref) => {
53+
const Comp = asChild ? Slot : Link
54+
55+
return (
56+
<Comp
57+
ref={ref}
58+
className={cn(
59+
"uppercase !text-body-medium no-underline transition-colors hover:!text-primary",
60+
className
61+
)}
62+
{...props}
63+
/>
64+
)
65+
})
66+
BreadcrumbLink.displayName = "BreadcrumbLink"
67+
68+
const BreadcrumbPage = React.forwardRef<
69+
HTMLSpanElement,
70+
React.ComponentPropsWithoutRef<"span">
71+
>(({ className, ...props }, ref) => (
72+
<span
73+
ref={ref}
74+
role="link"
75+
aria-disabled="true"
76+
aria-current="page"
77+
className={cn("uppercase text-primary", className)}
78+
{...props}
79+
/>
80+
))
81+
BreadcrumbPage.displayName = "BreadcrumbPage"
82+
83+
const BreadcrumbSeparator = ({
84+
children,
85+
className,
86+
...props
87+
}: React.ComponentProps<"li">) => (
88+
<li
89+
role="presentation"
90+
aria-hidden="true"
91+
className={cn("m-0", className)}
92+
{...props}
93+
>
94+
{children ?? <LuChevronRight />}
95+
</li>
96+
)
97+
BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
98+
99+
const BreadcrumbEllipsis = ({
100+
className,
101+
...props
102+
}: React.ComponentProps<"span">) => (
103+
<span
104+
role="presentation"
105+
aria-hidden="true"
106+
className={cn("flex h-9 w-9 items-center justify-center", className)}
107+
{...props}
108+
>
109+
<LuMoreHorizontal className="h-4 w-4" />
110+
<span className="sr-only">More</span>
111+
</span>
112+
)
113+
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
114+
115+
export {
116+
Breadcrumb,
117+
BreadcrumbEllipsis,
118+
BreadcrumbItem,
119+
BreadcrumbLink,
120+
BreadcrumbList,
121+
BreadcrumbPage,
122+
type BreadcrumbProps,
123+
BreadcrumbSeparator,
124+
}

src/pages/bug-bounty.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ const BugBountiesPage = () => {
476476
<Content>
477477
<HeroCard>
478478
<HeroContainer>
479-
<Breadcrumbs slug={pathname} mb="8" />
479+
<Breadcrumbs slug={pathname} className="mb-8" />
480480
<Row>
481481
<On />
482482
<Title>{t("page-upgrades-bug-bounty-title")}</Title>

src/pages/contributing/translation-program/acknowledgements.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ const TranslatorAcknowledgements = () => {
9292
/>
9393

9494
<Content>
95-
<Breadcrumbs slug={router.asPath} mt={12} />
95+
<Breadcrumbs slug={router.asPath} className="mt-12" />
9696
<ContentHeading
9797
as="h1"
9898
fontSize={{ base: "2rem", sm: "2.5rem", md: "5xl" }}

src/pages/contributing/translation-program/contributors.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const Contributors = () => {
8080
/>
8181

8282
<Content>
83-
<Breadcrumbs slug={router.asPath} mt={12} />
83+
<Breadcrumbs slug={router.asPath} className="mt-12" />
8484
<ContentHeading
8585
as="h1"
8686
fontSize={{ base: "2.5rem", md: "5xl" }}

0 commit comments

Comments
 (0)