Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shadcn migration - Breadcrumbs #13854

Merged
merged 8 commits into from
Sep 23, 2024
Merged
60 changes: 34 additions & 26 deletions src/components/Breadcrumbs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { Fragment } from "react"
import { useRouter } from "next/router"
import { useTranslation } from "next-i18next"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
type BreadcrumbProps as ChakraBreadcrumbProps,
} from "@chakra-ui/react"

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

import { BaseLink } from "@/components/Link"

import { isLangRightToLeft } from "@/lib/utils/translations"

export type BreadcrumbsProps = ChakraBreadcrumbProps & {
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbProps,
BreadcrumbSeparator,
} from "../ui/breadcrumb"

export type BreadcrumbsProps = BreadcrumbProps & {
slug: string
startDepth?: number
}
Expand Down Expand Up @@ -65,23 +68,28 @@ const Breadcrumbs = ({ slug, startDepth = 0, ...props }: BreadcrumbsProps) => {

return (
<Breadcrumb {...props} dir={dir}>
{crumbs.map(({ fullPath, text }) => {
const isCurrentPage = slug === fullPath
return (
<BreadcrumbItem key={fullPath} isCurrentPage={isCurrentPage}>
<BreadcrumbLink
// If current page, render as span since the `href` will not be
// passed down to the child
// ref: https://github.com/chakra-ui/chakra-ui/blob/v2/packages/components/src/breadcrumb/breadcrumb-link.tsx#L32
as={isCurrentPage ? "span" : BaseLink}
href={fullPath}
textTransform="uppercase"
>
{text}
</BreadcrumbLink>
</BreadcrumbItem>
)
})}
<BreadcrumbList>
{crumbs.map(({ fullPath, text }) => {
const normalizePath = (path) => path.replace(/\/$/, "") // Remove trailing slash
const isCurrentPage = normalizePath(slug) === normalizePath(fullPath)
return (
<Fragment key={fullPath}>
<BreadcrumbItem>
{isCurrentPage ? (
<BreadcrumbPage>{text}</BreadcrumbPage>
) : (
<BreadcrumbLink href={fullPath}>{text}</BreadcrumbLink>
)}
</BreadcrumbItem>
{!isCurrentPage && (
<BreadcrumbSeparator className="me-[0.625rem] ms-[0.625rem] text-gray-400">
/
</BreadcrumbSeparator>
)}
</Fragment>
)
})}
</BreadcrumbList>
</Breadcrumb>
)
}
Expand Down
124 changes: 124 additions & 0 deletions src/components/ui/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import * as React from "react"
import Link, { LinkProps } from "next/link"
import { LuChevronRight, LuMoreHorizontal } from "react-icons/lu"
import { Slot } from "@radix-ui/react-slot"

import { cn } from "@/lib/utils/cn"

interface BreadcrumbProps extends React.ComponentPropsWithoutRef<"nav"> {
separator?: React.ReactNode
}
const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(
({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />
)
Breadcrumb.displayName = "Breadcrumb"

const BreadcrumbList = React.forwardRef<
HTMLOListElement,
React.ComponentPropsWithoutRef<"ol">
>(({ className, ...props }, ref) => (
<ol
ref={ref}
className={cn(
"m-0 flex list-none flex-wrap items-center tracking-wider",
className
)}
{...props}
/>
))
BreadcrumbList.displayName = "BreadcrumbList"

const BreadcrumbItem = React.forwardRef<
HTMLLIElement,
React.ComponentPropsWithoutRef<"li">
>(({ className, ...props }, ref) => (
<li
ref={ref}
className={cn(
"m-0 inline-flex items-center gap-1.5 tracking-wider",
className
)}
{...props}
/>
))
BreadcrumbItem.displayName = "BreadcrumbItem"

const BreadcrumbLink = React.forwardRef<
HTMLAnchorElement,
React.ComponentPropsWithoutRef<"a"> &
LinkProps & {
asChild?: boolean
}
>(({ asChild, className, ...props }, ref) => {
const Comp = asChild ? Slot : Link

return (
<Comp
ref={ref}
className={cn(
"uppercase !text-body-medium no-underline transition-colors hover:!text-primary",
className
)}
{...props}
/>
)
})
BreadcrumbLink.displayName = "BreadcrumbLink"

const BreadcrumbPage = React.forwardRef<
HTMLSpanElement,
React.ComponentPropsWithoutRef<"span">
>(({ className, ...props }, ref) => (
<span
ref={ref}
role="link"
aria-disabled="true"
aria-current="page"
className={cn("uppercase text-primary", className)}
{...props}
/>
))
BreadcrumbPage.displayName = "BreadcrumbPage"

const BreadcrumbSeparator = ({
children,
className,
...props
}: React.ComponentProps<"li">) => (
<li
role="presentation"
aria-hidden="true"
className={cn("m-0", className)}
{...props}
>
{children ?? <LuChevronRight />}
</li>
)
BreadcrumbSeparator.displayName = "BreadcrumbSeparator"

const BreadcrumbEllipsis = ({
className,
...props
}: React.ComponentProps<"span">) => (
<span
role="presentation"
aria-hidden="true"
className={cn("flex h-9 w-9 items-center justify-center", className)}
{...props}
>
<LuMoreHorizontal className="h-4 w-4" />
<span className="sr-only">More</span>
</span>
)
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"

export {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
type BreadcrumbProps,
BreadcrumbSeparator,
}
2 changes: 1 addition & 1 deletion src/pages/bug-bounty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ const BugBountiesPage = () => {
<Content>
<HeroCard>
<HeroContainer>
<Breadcrumbs slug={pathname} mb="8" />
<Breadcrumbs slug={pathname} className="mb-8" />
<Row>
<On />
<Title>{t("page-upgrades-bug-bounty-title")}</Title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const TranslatorAcknowledgements = () => {
/>

<Content>
<Breadcrumbs slug={router.asPath} mt={12} />
<Breadcrumbs slug={router.asPath} className="mt-12" />
<ContentHeading
as="h1"
fontSize={{ base: "2rem", sm: "2.5rem", md: "5xl" }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const Contributors = () => {
/>

<Content>
<Breadcrumbs slug={router.asPath} mt={12} />
<Breadcrumbs slug={router.asPath} className="mt-12" />
<ContentHeading
as="h1"
fontSize={{ base: "2.5rem", md: "5xl" }}
Expand Down
Loading