breadcrumb.tsx (2691B)
1 import { Slot } from "@radix-ui/react-slot" 2 import { ChevronRight, MoreHorizontal } from "lucide-react" 3 4 import { cn } from "@/lib/utils" 5 import { forwardRef, ComponentPropsWithoutRef, ReactNode, ComponentProps } from "react" 6 7 const Breadcrumb = forwardRef< 8 HTMLElement, 9 ComponentPropsWithoutRef<"nav"> & { 10 separator?: ReactNode 11 } 12 >(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />) 13 Breadcrumb.displayName = "Breadcrumb" 14 15 const BreadcrumbList = forwardRef< 16 HTMLOListElement, 17 ComponentPropsWithoutRef<"ol"> 18 >(({ className, ...props }, ref) => ( 19 <ol 20 ref={ref} 21 className={cn( 22 "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", 23 className 24 )} 25 {...props} 26 /> 27 )) 28 BreadcrumbList.displayName = "BreadcrumbList" 29 30 const BreadcrumbItem = forwardRef< 31 HTMLLIElement, 32 ComponentPropsWithoutRef<"li"> 33 >(({ className, ...props }, ref) => ( 34 <li 35 ref={ref} 36 className={cn("inline-flex items-center gap-1.5", className)} 37 {...props} 38 /> 39 )) 40 BreadcrumbItem.displayName = "BreadcrumbItem" 41 42 const BreadcrumbLink = forwardRef< 43 HTMLAnchorElement, 44 ComponentPropsWithoutRef<"a"> & { 45 asChild?: boolean 46 } 47 >(({ asChild, className, ...props }, ref) => { 48 const Comp = asChild ? Slot : "a" 49 50 return ( 51 <Comp 52 ref={ref} 53 className={cn("transition-colors hover:text-foreground", className)} 54 {...props} 55 /> 56 ) 57 }) 58 BreadcrumbLink.displayName = "BreadcrumbLink" 59 60 const BreadcrumbPage = forwardRef< 61 HTMLSpanElement, 62 ComponentPropsWithoutRef<"span"> 63 >(({ className, ...props }, ref) => ( 64 <span 65 ref={ref} 66 role="link" 67 aria-disabled="true" 68 aria-current="page" 69 className={cn("font-normal text-foreground", className)} 70 {...props} 71 /> 72 )) 73 BreadcrumbPage.displayName = "BreadcrumbPage" 74 75 const BreadcrumbSeparator = ({ 76 children, 77 className, 78 ...props 79 }: ComponentProps<"li">) => ( 80 <li 81 role="presentation" 82 aria-hidden="true" 83 className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)} 84 {...props} 85 > 86 {children ?? <ChevronRight />} 87 </li> 88 ) 89 BreadcrumbSeparator.displayName = "BreadcrumbSeparator" 90 91 const BreadcrumbEllipsis = ({ 92 className, 93 ...props 94 }: ComponentProps<"span">) => ( 95 <span 96 role="presentation" 97 aria-hidden="true" 98 className={cn("flex h-9 w-9 items-center justify-center", className)} 99 {...props} 100 > 101 <MoreHorizontal className="h-4 w-4" /> 102 <span className="sr-only">More</span> 103 </span> 104 ) 105 BreadcrumbEllipsis.displayName = "BreadcrumbElipssis" 106 107 export { 108 Breadcrumb, 109 BreadcrumbList, 110 BreadcrumbItem, 111 BreadcrumbLink, 112 BreadcrumbPage, 113 BreadcrumbSeparator, 114 BreadcrumbEllipsis, 115 }