Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions components/retroui/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { ChevronRight, MoreHorizontal } from "lucide-react"
import { cn } from "@/lib/utils"

const BreadcrumbRoot = React.forwardRef<
HTMLElement,
React.ComponentPropsWithoutRef<"nav">
>(({ className, ...props }, ref) => (
<nav
ref={ref}
aria-label="breadcrumb"
className={cn("w-full text-sm", className)}
{...props}
/>
))
BreadcrumbRoot.displayName = "Breadcrumb"

const BreadcrumbList = React.forwardRef<
HTMLOListElement,
React.ComponentPropsWithoutRef<"ol">
>(({ className, ...props }, ref) => (
<ol
ref={ref}
className={cn(
"flex flex-wrap items-center gap-1.5 sm:gap-2.5 text-muted-foreground",
className
)}
{...props}
/>
))
BreadcrumbList.displayName = "BreadcrumbList"

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

const BreadcrumbLink = React.forwardRef<
HTMLAnchorElement,
React.ComponentPropsWithoutRef<"a"> & { asChild?: boolean }
>(({ asChild, className, ...props }, ref) => {
const Comp = asChild ? Slot : "a"
return (
<Comp
ref={ref}
className={cn(
"font-medium transition-colors hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring rounded-sm",
className
)}
{...props}
/>
)
})
BreadcrumbLink.displayName = "BreadcrumbLink"

const BreadcrumbPage = React.forwardRef<
HTMLSpanElement,
React.ComponentPropsWithoutRef<"span">
>(({ className, ...props }, ref) => (
<span
ref={ref}
aria-current="page"
className={cn("text-foreground font-semibold", className)}
{...props}
/>
))
BreadcrumbPage.displayName = "BreadcrumbPage"

const BreadcrumbSeparator = ({
children,
className,
...props
}: React.ComponentProps<"li">) => (
<li
role="presentation"
aria-hidden="true"
className={cn("text-muted-foreground [&>svg]:h-4 [&>svg]:w-4", className)}
{...props}
>
{children ?? <ChevronRight />}
</li>
)
BreadcrumbSeparator.displayName = "BreadcrumbSeparator"

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

const Breadcrumb = Object.assign(BreadcrumbRoot, {
List: BreadcrumbList,
Item: BreadcrumbItem,
Link: BreadcrumbLink,
Page: BreadcrumbPage,
Separator: BreadcrumbSeparator,
Ellipsis: BreadcrumbEllipsis,
})

export { Breadcrumb }


1 change: 1 addition & 0 deletions components/retroui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * from "./Toggle";
export * from "./ToggleGroup";
export * from "./Sonner";
export * from "./Tooltip";
export * from "./Breadcrumb";
32 changes: 32 additions & 0 deletions config/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ export const componentConfig: {
name: "tooltip",
filePath: "components/retroui/Tooltip.tsx",
},
breadcrumb: {
name: "breadcrumb",
filePath: "components/retroui/Breadcrumb.tsx",
}
},
examples: {
"accordion-style-default": {
Expand Down Expand Up @@ -469,5 +473,33 @@ export const componentConfig: {
() => import("@/preview/components/toggle-group-style-solid"),
),
},
"breadcrumb-style-default": {
name: "breadcrumb-style-default",
filePath: "preview/components/breadcrumb-style-default.tsx",
preview: lazy(
() => import("@/preview/components/breadcrumb-style-default"),
),
},
"breadcrumb-custom-separator": {
name: "breadcrumb-custom-separator",
filePath: "preview/components/breadcrumb-custom-separator.tsx",
preview: lazy(
() => import("@/preview/components/breadcrumb-custom-separator"),
),
},
"breadcrumb-style-collapsed": {
name: "breadcrumb-style-collapsed",
filePath: "preview/components/breadcrumb-style-collapsed.tsx",
preview: lazy(
() => import("@/preview/components/breadcrumb-style-collapsed"),
),
},
"breadcrumb-link-component": {
name: "breadcrumb-link-component",
filePath: "preview/components/breadcrumb-link-component.tsx",
preview: lazy(
() => import("@/preview/components/breadcrumb-link-component"),
),
},
},
};
1 change: 1 addition & 0 deletions config/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const navConfig: INavigationConfig = {
{ title: "Alert", href: `${componentsRoute}/alert` },
{ title: "Avatar", href: `${componentsRoute}/avatar` },
{ title: "Badge", href: `${componentsRoute}/badge` },
{ title: "Breadcrumb", href: `${componentsRoute}/breadcrumb` },
{ title: "Button", href: `${componentsRoute}/button` },
{ title: "Card", href: `${componentsRoute}/card` },
{ title: "Checkbox", href: `${componentsRoute}/checkbox` },
Expand Down
68 changes: 68 additions & 0 deletions content/docs/components/breadcrumb.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: Breadcrumb
description: A navigation component that shows users where they are within a hierarchy.
lastUpdated: 12 May, 2025
---

<ComponentShowcase name="breadcrumb-style-default" />
<br />
<br />

<ComponentInstall>
<ComponentInstall.Cli>
```sh
npx shadcn@latest add "https://retroui.dev/r/breadcrumb.json"
```
</ComponentInstall.Cli>
<ComponentInstall.Manual>
#### 1. Install dependencies:

```sh
npm install lucide-react class-variance-authority
````

<br />

#### 2. Copy the code 👇 into your project:

<ComponentSource name="breadcrumb" />

</ComponentInstall.Manual>
</ComponentInstall>

<br />
<br />

## Examples

### Default

<hr />
<br />
<ComponentShowcase name="breadcrumb-style-default" />
<br />
<br />

### Custom Separator

<hr />
<br />
<ComponentShowcase name="breadcrumb-custom-separator" />
<br />
<br />

### Collapsed

<hr />
<br />
<ComponentShowcase name="breadcrumb-style-collapsed" />
<br />
<br />

### Link Component

<hr />
<br />
<ComponentShowcase name="breadcrumb-link-component" />
<br />
<br />
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@radix-ui/react-radio-group": "^1.2.3",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-slider": "^1.2.4",
"@radix-ui/react-slot": "^1.2.2",
"@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-toggle": "^1.1.6",
"@radix-ui/react-toggle-group": "^1.1.7",
Expand Down
19 changes: 19 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions preview/components/breadcrumb-custom-separator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Breadcrumb } from "@/components/retroui/Breadcrumb";
import { Slash } from "lucide-react";

export default function BreadcrumbCustomSeparator() {
return (
<Breadcrumb>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="/">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator>
<Slash />
</Breadcrumb.Separator>
<Breadcrumb.Item>
<Breadcrumb.Link href="/components">Components</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator>
<Slash />
</Breadcrumb.Separator>
<Breadcrumb.Item>
<Breadcrumb.Page>Breadcrumb</Breadcrumb.Page>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb>
);
}
27 changes: 27 additions & 0 deletions preview/components/breadcrumb-link-component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Link from "next/link"

import { Breadcrumb } from "@/components/retroui/Breadcrumb"

export default function BreadcrumbLinkComponent() {
return (
<Breadcrumb>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link asChild>
<Link href="/">Home</Link>
</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link asChild>
<Link href="/docs/components">Components</Link>
</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Page>Breadcrumb</Breadcrumb.Page>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb>
)
}
30 changes: 30 additions & 0 deletions preview/components/breadcrumb-style-collapsed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Link from "next/link"

import { Breadcrumb } from "@/components/retroui/Breadcrumb";

export default function BreadcrumbCollapsed() {
return (
<Breadcrumb>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link asChild>
<Link href="/">Home</Link>
</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
<Breadcrumb.Ellipsis />
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link asChild>
<Link href="/docs/components">Components</Link>
</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Page>Breadcrumb</Breadcrumb.Page>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb>
)
}
Loading