breadcrumb.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import * as React from 'react';
  2. import { mergeProps } from '@base-ui/react/merge-props';
  3. import { useRender } from '@base-ui/react/use-render';
  4. import { cn } from '@/lib/utils';
  5. import { ChevronRightIcon, MoreHorizontalIcon } from 'lucide-react';
  6. function Breadcrumb({ className, ...props }: React.ComponentProps<'nav'>) {
  7. return (
  8. <nav
  9. aria-label="breadcrumb"
  10. data-slot="breadcrumb"
  11. className={cn(className)}
  12. {...props}
  13. />
  14. );
  15. }
  16. function BreadcrumbList({ className, ...props }: React.ComponentProps<'ol'>) {
  17. return (
  18. <ol
  19. data-slot="breadcrumb-list"
  20. className={cn(
  21. 'text-muted-foreground gap-1.5 text-sm flex flex-wrap items-center wrap-break-word',
  22. className,
  23. )}
  24. {...props}
  25. />
  26. );
  27. }
  28. function BreadcrumbItem({ className, ...props }: React.ComponentProps<'li'>) {
  29. return (
  30. <li
  31. data-slot="breadcrumb-item"
  32. className={cn('gap-1 inline-flex items-center', className)}
  33. {...props}
  34. />
  35. );
  36. }
  37. function BreadcrumbLink({
  38. className,
  39. render,
  40. ...props
  41. }: useRender.ComponentProps<'a'>) {
  42. return useRender({
  43. defaultTagName: 'a',
  44. props: mergeProps<'a'>(
  45. {
  46. className: cn('hover:text-foreground transition-colors', className),
  47. },
  48. props,
  49. ),
  50. render,
  51. state: {
  52. slot: 'breadcrumb-link',
  53. },
  54. });
  55. }
  56. function BreadcrumbPage({ className, ...props }: React.ComponentProps<'span'>) {
  57. return (
  58. <span
  59. data-slot="breadcrumb-page"
  60. role="link"
  61. aria-disabled="true"
  62. aria-current="page"
  63. className={cn('text-foreground font-normal', className)}
  64. {...props}
  65. />
  66. );
  67. }
  68. function BreadcrumbSeparator({
  69. children,
  70. className,
  71. ...props
  72. }: React.ComponentProps<'li'>) {
  73. return (
  74. <li
  75. data-slot="breadcrumb-separator"
  76. role="presentation"
  77. aria-hidden="true"
  78. className={cn('[&>svg]:size-3.5', className)}
  79. {...props}
  80. >
  81. {children ?? <ChevronRightIcon className="cn-rtl-flip" />}
  82. </li>
  83. );
  84. }
  85. function BreadcrumbEllipsis({
  86. className,
  87. ...props
  88. }: React.ComponentProps<'span'>) {
  89. return (
  90. <span
  91. data-slot="breadcrumb-ellipsis"
  92. role="presentation"
  93. aria-hidden="true"
  94. className={cn(
  95. 'size-5 [&>svg]:size-4 flex items-center justify-center',
  96. className,
  97. )}
  98. {...props}
  99. >
  100. <MoreHorizontalIcon />
  101. <span className="sr-only">More</span>
  102. </span>
  103. );
  104. }
  105. export {
  106. Breadcrumb,
  107. BreadcrumbList,
  108. BreadcrumbItem,
  109. BreadcrumbLink,
  110. BreadcrumbPage,
  111. BreadcrumbSeparator,
  112. BreadcrumbEllipsis,
  113. };