feat: breadcrumb component (#405)

* feat: adding breadcrumb component, resolves #395

* fix: revert kbd component in main layout

* feat: add slot for `BreadcrumbEllipsis` icons too

build registry, bump radix-vue

* refactor: using primitive instead of computed

* chore: update

---------

Co-authored-by: Sadegh Barati <sadeghbaratiwork@gmail.com>
This commit is contained in:
Saeid Zareie 2024-03-13 11:03:22 +03:30 committed by GitHub
parent 454ecf0df7
commit 4d08adc81e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 1358 additions and 17 deletions

View File

@ -158,6 +158,12 @@ export const docsConfig: DocsConfig = {
href: '/docs/components/badge',
items: [],
},
{
title: 'Breadcrumb',
href: '/docs/components/breadcrumb',
items: [],
label: 'New',
},
{
title: 'Button',
href: '/docs/components/button',

View File

@ -2,7 +2,6 @@
import { useMagicKeys, useToggle } from '@vueuse/core'
import { onMounted, ref, watch } from 'vue'
import { Content, useData, useRoute, useRouter } from 'vitepress'
import { SearchIcon } from 'lucide-vue-next'
import { type NavItem, docsConfig } from '../config/docs'
import Logo from '../components/Logo.vue'
import MobileNav from '../components/MobileNav.vue'
@ -119,11 +118,11 @@ watch(() => $route.path, (n) => {
class="relative h-8 w-full justify-start rounded-[0.5rem] bg-background text-sm font-normal text-muted-foreground shadow-none sm:pr-12 md:w-40 lg:w-64"
@click="isOpen = true"
>
<span className="hidden lg:inline-flex">Search documentation...</span>
<span className="inline-flex lg:hidden">Search...</span>
<kbd className="pointer-events-none absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
<span className="text-xs"></span>K
</kbd>
<span class="hidden lg:inline-flex">Search documentation...</span>
<span class="inline-flex lg:hidden">Search...</span>
<Kbd class="pointer-events-none absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
<span class="text-xs"></span>K
</Kbd>
</Button>
</div>

View File

@ -73,6 +73,48 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/BadgeSecondaryDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/BadgeSecondaryDemo.vue"],
},
"BreadcrumbDemo": {
name: "BreadcrumbDemo",
type: "components:example",
registryDependencies: ["breadcrumb","dropdown-menu"],
component: () => import("../src/lib/registry/default/example/BreadcrumbDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/BreadcrumbDemo.vue"],
},
"BreadcrumbDropdown": {
name: "BreadcrumbDropdown",
type: "components:example",
registryDependencies: ["breadcrumb","dropdown-menu"],
component: () => import("../src/lib/registry/default/example/BreadcrumbDropdown.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/BreadcrumbDropdown.vue"],
},
"BreadcrumbEllipsisDemo": {
name: "BreadcrumbEllipsisDemo",
type: "components:example",
registryDependencies: ["breadcrumb"],
component: () => import("../src/lib/registry/default/example/BreadcrumbEllipsisDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/BreadcrumbEllipsisDemo.vue"],
},
"BreadcrumbLinkDemo": {
name: "BreadcrumbLinkDemo",
type: "components:example",
registryDependencies: ["breadcrumb"],
component: () => import("../src/lib/registry/default/example/BreadcrumbLinkDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/BreadcrumbLinkDemo.vue"],
},
"BreadcrumbResponsive": {
name: "BreadcrumbResponsive",
type: "components:example",
registryDependencies: ["breadcrumb","button","drawer","dropdown-menu"],
component: () => import("../src/lib/registry/default/example/BreadcrumbResponsive.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/BreadcrumbResponsive.vue"],
},
"BreadcrumbSeparatorDemo": {
name: "BreadcrumbSeparatorDemo",
type: "components:example",
registryDependencies: ["breadcrumb"],
component: () => import("../src/lib/registry/default/example/BreadcrumbSeparatorDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/BreadcrumbSeparatorDemo.vue"],
},
"ButtonAsChildDemo": {
name: "ButtonAsChildDemo",
type: "components:example",
@ -1131,6 +1173,48 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/BadgeSecondaryDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/BadgeSecondaryDemo.vue"],
},
"BreadcrumbDemo": {
name: "BreadcrumbDemo",
type: "components:example",
registryDependencies: ["breadcrumb","dropdown-menu"],
component: () => import("../src/lib/registry/new-york/example/BreadcrumbDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/BreadcrumbDemo.vue"],
},
"BreadcrumbDropdown": {
name: "BreadcrumbDropdown",
type: "components:example",
registryDependencies: ["breadcrumb","dropdown-menu"],
component: () => import("../src/lib/registry/new-york/example/BreadcrumbDropdown.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/BreadcrumbDropdown.vue"],
},
"BreadcrumbEllipsisDemo": {
name: "BreadcrumbEllipsisDemo",
type: "components:example",
registryDependencies: ["breadcrumb"],
component: () => import("../src/lib/registry/new-york/example/BreadcrumbEllipsisDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/BreadcrumbEllipsisDemo.vue"],
},
"BreadcrumbLinkDemo": {
name: "BreadcrumbLinkDemo",
type: "components:example",
registryDependencies: ["breadcrumb"],
component: () => import("../src/lib/registry/new-york/example/BreadcrumbLinkDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/BreadcrumbLinkDemo.vue"],
},
"BreadcrumbResponsive": {
name: "BreadcrumbResponsive",
type: "components:example",
registryDependencies: ["breadcrumb","button","drawer","dropdown-menu"],
component: () => import("../src/lib/registry/new-york/example/BreadcrumbResponsive.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/BreadcrumbResponsive.vue"],
},
"BreadcrumbSeparatorDemo": {
name: "BreadcrumbSeparatorDemo",
type: "components:example",
registryDependencies: ["breadcrumb"],
component: () => import("../src/lib/registry/new-york/example/BreadcrumbSeparatorDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/BreadcrumbSeparatorDemo.vue"],
},
"ButtonAsChildDemo": {
name: "ButtonAsChildDemo",
type: "components:example",

View File

@ -31,7 +31,7 @@
"embla-carousel-autoplay": "^8.0.0",
"embla-carousel-vue": "^8.0.0",
"lucide-vue-next": "^0.350.0",
"radix-vue": "^1.5.0",
"radix-vue": "^1.5.2",
"tailwindcss-animate": "^1.0.7",
"v-calendar": "^3.1.2",
"vaul-vue": "^0.1.0",

View File

@ -0,0 +1,205 @@
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
---
<ComponentPreview name="BreadcrumbDemo" class="[&_.preview]:p-2" />
## Installation
```bash
npx shadcn-ui@latest add breadcrumb
```
## Usage
```vue
<script setup lang="ts">
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/components/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/components">
Components
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>
```
## Examples
### Custom separator
Use a custom component as `slot` for `<BreadcrumbSeparator />` to create a custom separator.
<ComponentPreview name="BreadcrumbSeparatorDemo" />
```vue showLineNumbers {2,20-22}
<script setup lang="ts">
import { Slash } from 'lucide-react'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator,
} from '@/lib/components/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="/components">
Components
</BreadcrumbLink>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>
```
---
### Dropdown
You can compose `<BreadcrumbItem />` with a `<DropdownMenu />` to create a dropdown in the breadcrumb.
<ComponentPreview name="BreadcrumbDropdown" class="[&_.preview]:p-2" />
```vue showLineNumbers {2-7,16-26}
<script setup lang="ts">
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/lib/components/ui/dropdown-menu'
import { BreadcrumbItem } from '@/lib/components/ui/breadcrumb'
import ChevronDownIcon from '~icons/radix-icons/chevron-down'
</script>
<template>
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger class="flex items-center gap-1">
Components
<ChevronDownIcon />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
</template>
```
---
### Collapsed
We provide a `<BreadcrumbEllipsis />` component to show a collapsed state when the breadcrumb is too long.
<ComponentPreview name="BreadcrumbEllipsisDemo" class="[&_.preview]:p-2" />
```vue showLineNumbers {3,15}
<script setup lang="ts">
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbList,
} from '@/lib/components/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<!-- ... -->
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
<!-- ... -->
</BreadcrumbList>
</Breadcrumb>
</template>
```
---
### Link component
To use a custom link component from your routing library, you can use the `asChild` prop on `<BreadcrumbLink />`.
<ComponentPreview name="BreadcrumbLinkDemo" />
```vue showLineNumbers {15-19}
<script setup lang="ts">
import { RouterLink } from 'vue-router'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
} from '@/lib/components/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink as-child>
<RouterLink to="/">
Home
</RouterLink>
</BreadcrumbLink>
</BreadcrumbItem>
<!-- -->
</BreadcrumbList>
</Breadcrumb>
</template>
```
---
### Responsive
Here's an example of a responsive breadcrumb that composes `<BreadcrumbItem />` with `<BreadcrumbEllipsis />`, `<DropdownMenu />`, and `<Drawer />`.
It displays a dropdown on desktop and a drawer on mobile.
<ComponentPreview name="BreadcrumbResponsive" class="[&_.preview]:p-2" />

View File

@ -0,0 +1,53 @@
<script lang="ts" setup>
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/default/ui/breadcrumb'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/lib/registry/default/ui/dropdown-menu'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger class="flex items-center gap-1">
<BreadcrumbEllipsis class="h-4 w-4" />
<span class="sr-only">Toggle menu</span>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/docs/components/accordion.html">
Components
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,51 @@
<script lang="ts" setup>
import { ChevronDown, Slash } from 'lucide-vue-next'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/default/ui/breadcrumb'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/lib/registry/default/ui/dropdown-menu'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger class="flex items-center gap-1">
Components
<ChevronDown class="h-4 w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,41 @@
<script lang="ts" setup>
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/default/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink as-child>
<a href="/">
Home
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink as-child>
<a href="/docs/components/accordion.html">
Components
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,36 @@
<script lang="ts" setup>
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/default/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink>
<a href="/">
Home
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink>
<a href="/docs/components/accordion.html">
Components
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,125 @@
<script lang="ts" setup>
import { useMediaQuery } from '@vueuse/core'
import { computed, ref } from 'vue'
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/default/ui/breadcrumb'
import { Button } from '@/lib/registry/default/ui/button'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/default/ui/drawer'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/lib/registry/default/ui/dropdown-menu'
const isDesktop = useMediaQuery('(min-width: 768px)')
const isOpen = ref(false)
const items = ref([
{ href: '#', label: 'Home' },
{ href: '#', label: 'Documentation' },
{ href: '#', label: 'Building Your Application' },
{ href: '#', label: 'Data Fetching' },
{ label: 'Caching and Revalidating' },
])
const itemsToDisplay = 3
const firstLabel = computed(() => items.value[0]?.label)
const allButLastTwoItems = computed(() => items.value.slice(1, -2))
const remainingItems = computed(() => items.value.slice(-itemsToDisplay + 1))
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="{items[0].href}">
{{ firstLabel }}
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<template v-if="items.length > itemsToDisplay">
<BreadcrumbItem>
<DropdownMenu v-if="isDesktop" v-model:open="isOpen">
<DropdownMenuTrigger
class="flex items-center gap-1"
aria-label="Toggle menu"
>
<BreadcrumbEllipsis class="h-4 w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem v-for="item of allButLastTwoItems" :key="item.label">
<a :href="item.href || '#'">
{{ item.label }}
</a>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Drawer v-else v-model:open="isOpen">
<DrawerTrigger aria-label="Toggle Menu">
<BreadcrumbEllipsis class="h-4 w-4" />
</DrawerTrigger>
<DrawerContent>
<DrawerHeader class="text-left">
<DrawerTitle>Navigate to</DrawerTitle>
<DrawerDescription>
Select a page to navigate to.
</DrawerDescription>
</DrawerHeader>
<div class="grid gap-1 px-4">
<a
v-for="item of allButLastTwoItems"
:key="item.label"
:href="item.href"
class="py-1 text-sm"
>
{{ item.label }}
</a>
</div>
<DrawerFooter class="pt-4">
<DrawerClose as-child>
<Button variant="outline">
Close
</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</BreadcrumbItem>
<BreadcrumbSeparator />
</template>
<BreadcrumbItem v-for=" item of remainingItems" :key="item.label">
<template v-if="item.href">
<BreadcrumbLink
as-child
class="max-w-20 truncate md:max-w-none"
>
<a :href="item.href">
{{ item.label }}
</a>
</BreadcrumbLink>
<BreadcrumbSeparator />
</template>
<BreadcrumbPage v-else class="max-w-20 truncate md:max-w-none">
{{ item.label }}
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,37 @@
<script lang="ts" setup>
import { Slash } from 'lucide-vue-next'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/default/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="/docs/components/accordion.html">
Components
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<Slash />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,13 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<nav aria-label="breadcrumb" :class="props.class">
<slot />
</nav>
</template>

View File

@ -0,0 +1,22 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { MoreHorizontal } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<span
role="presentation"
aria-hidden="true"
:class="cn('flex h-9 w-9 items-center justify-center', props.class)"
>
<slot>
<MoreHorizontal class="h-4 w-4" />
</slot>
<span class="sr-only">More</span>
</span>
</template>

View File

@ -0,0 +1,16 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<li
:class="cn('inline-flex items-center gap-1.5', props.class)"
>
<slot />
</li>
</template>

View File

@ -0,0 +1,19 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { Primitive, type PrimitiveProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<PrimitiveProps & { class?: HTMLAttributes['class'] }>(), {
as: 'a',
})
</script>
<template>
<Primitive
:as="as"
:as-child="asChild"
:class="cn('transition-colors hover:text-foreground', props.class)"
>
<slot />
</Primitive>
</template>

View File

@ -0,0 +1,16 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<ol
:class="cn('flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5', props.class)"
>
<slot />
</ol>
</template>

View File

@ -0,0 +1,19 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<span
role="link"
aria-disabled="true"
aria-current="page"
:class="cn('font-normal text-foreground', props.class)"
>
<slot />
</span>
</template>

View File

@ -0,0 +1,21 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { ChevronRight } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<li
role="presentation"
aria-hidden="true"
:class="cn('[&>svg]:size-3.5', props.class)"
>
<slot>
<ChevronRight />
</slot>
</li>
</template>

View File

@ -0,0 +1,7 @@
export { default as Breadcrumb } from './Breadcrumb.vue'
export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue'
export { default as BreadcrumbItem } from './BreadcrumbItem.vue'
export { default as BreadcrumbLink } from './BreadcrumbLink.vue'
export { default as BreadcrumbList } from './BreadcrumbList.vue'
export { default as BreadcrumbPage } from './BreadcrumbPage.vue'
export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'

View File

@ -0,0 +1,53 @@
<script lang="ts" setup>
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/new-york/ui/breadcrumb'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/lib/registry/new-york/ui/dropdown-menu'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger class="flex items-center gap-1">
<BreadcrumbEllipsis class="h-4 w-4" />
<span class="sr-only">Toggle menu</span>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/docs/components/accordion.html">
Components
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,51 @@
<script lang="ts" setup>
import { ChevronDownIcon, SlashIcon } from '@radix-icons/vue'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/new-york/ui/breadcrumb'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/lib/registry/new-york/ui/dropdown-menu'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger class="flex items-center gap-1">
Components
<ChevronDownIcon class="h-4 w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem>Documentation</DropdownMenuItem>
<DropdownMenuItem>Themes</DropdownMenuItem>
<DropdownMenuItem>GitHub</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,41 @@
<script lang="ts" setup>
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/new-york/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink as-child>
<a href="/">
Home
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbEllipsis />
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink as-child>
<a href="/docs/components/accordion.html">
Components
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,36 @@
<script lang="ts" setup>
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/new-york/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink>
<a href="/">
Home
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink>
<a href="/docs/components/accordion.html">
Components
</a>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,125 @@
<script lang="ts" setup>
import { useMediaQuery } from '@vueuse/core'
import { computed, ref } from 'vue'
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/new-york/ui/breadcrumb'
import { Button } from '@/lib/registry/new-york/ui/button'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/new-york/ui/drawer'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/lib/registry/new-york/ui/dropdown-menu'
const isDesktop = useMediaQuery('(min-width: 768px)')
const isOpen = ref(false)
const items = ref([
{ href: '#', label: 'Home' },
{ href: '#', label: 'Documentation' },
{ href: '#', label: 'Building Your Application' },
{ href: '#', label: 'Data Fetching' },
{ label: 'Caching and Revalidating' },
])
const itemsToDisplay = 3
const firstLabel = computed(() => items.value[0]?.label)
const allButLastTwoItems = computed(() => items.value.slice(1, -2))
const remainingItems = computed(() => items.value.slice(-itemsToDisplay + 1))
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="{items[0].href}">
{{ firstLabel }}
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<template v-if="items.length > itemsToDisplay">
<BreadcrumbItem>
<DropdownMenu v-if="isDesktop" v-model:open="isOpen">
<DropdownMenuTrigger
class="flex items-center gap-1"
aria-label="Toggle menu"
>
<BreadcrumbEllipsis class="h-4 w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem v-for="item of allButLastTwoItems" :key="item.label">
<a :href="item.href || '#'">
{{ item.label }}
</a>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Drawer v-else v-model:open="isOpen">
<DrawerTrigger aria-label="Toggle Menu">
<BreadcrumbEllipsis class="h-4 w-4" />
</DrawerTrigger>
<DrawerContent>
<DrawerHeader class="text-left">
<DrawerTitle>Navigate to</DrawerTitle>
<DrawerDescription>
Select a page to navigate to.
</DrawerDescription>
</DrawerHeader>
<div class="grid gap-1 px-4">
<a
v-for="item of allButLastTwoItems"
:key="item.label"
:href="item.href"
class="py-1 text-sm"
>
{{ item.label }}
</a>
</div>
<DrawerFooter class="pt-4">
<DrawerClose as-child>
<Button variant="outline">
Close
</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</BreadcrumbItem>
<BreadcrumbSeparator />
</template>
<BreadcrumbItem v-for=" item of remainingItems" :key="item.label">
<template v-if="item.href">
<BreadcrumbLink
as-child
class="max-w-20 truncate md:max-w-none"
>
<a :href="item.href">
{{ item.label }}
</a>
</BreadcrumbLink>
<BreadcrumbSeparator />
</template>
<BreadcrumbPage v-else class="max-w-20 truncate md:max-w-none">
{{ item.label }}
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,37 @@
<script lang="ts" setup>
import { SlashIcon } from '@radix-icons/vue'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/lib/registry/new-york/ui/breadcrumb'
</script>
<template>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">
Home
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbLink href="/docs/components/accordion.html">
Components
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</template>

View File

@ -0,0 +1,13 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<nav aria-label="breadcrumb" :class="props.class">
<slot />
</nav>
</template>

View File

@ -0,0 +1,22 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { DotsHorizontalIcon } from '@radix-icons/vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<span
role="presentation"
aria-hidden="true"
:class="cn('flex h-9 w-9 items-center justify-center', props.class)"
>
<slot>
<DotsHorizontalIcon class="h-4 w-4" />
</slot>
<span class="sr-only">More</span>
</span>
</template>

View File

@ -0,0 +1,16 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<li
:class="cn('inline-flex items-center gap-1.5', props.class)"
>
<slot />
</li>
</template>

View File

@ -0,0 +1,19 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { Primitive, type PrimitiveProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = withDefaults(defineProps<PrimitiveProps & { class?: HTMLAttributes['class'] }>(), {
as: 'a',
})
</script>
<template>
<Primitive
:as="as"
:as-child="asChild"
:class="cn('transition-colors hover:text-foreground', props.class)"
>
<slot />
</Primitive>
</template>

View File

@ -0,0 +1,16 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<ol
:class="cn('flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5', props.class)"
>
<slot />
</ol>
</template>

View File

@ -0,0 +1,19 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<span
role="link"
aria-disabled="true"
aria-current="page"
:class="cn('font-normal text-foreground', props.class)"
>
<slot />
</span>
</template>

View File

@ -0,0 +1,21 @@
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { ChevronRightIcon } from '@radix-icons/vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<li
role="presentation"
aria-hidden="true"
:class="cn('[&>svg]:size-3.5', props.class)"
>
<slot>
<ChevronRightIcon />
</slot>
</li>
</template>

View File

@ -0,0 +1,7 @@
export { default as Breadcrumb } from './Breadcrumb.vue'
export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue'
export { default as BreadcrumbItem } from './BreadcrumbItem.vue'
export { default as BreadcrumbLink } from './BreadcrumbLink.vue'
export { default as BreadcrumbList } from './BreadcrumbList.vue'
export { default as BreadcrumbPage } from './BreadcrumbPage.vue'
export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'

View File

@ -85,6 +85,24 @@
],
"type": "components:ui"
},
{
"name": "breadcrumb",
"dependencies": [],
"registryDependencies": [
"utils"
],
"files": [
"ui/breadcrumb/Breadcrumb.vue",
"ui/breadcrumb/BreadcrumbEllipsis.vue",
"ui/breadcrumb/BreadcrumbItem.vue",
"ui/breadcrumb/BreadcrumbLink.vue",
"ui/breadcrumb/BreadcrumbList.vue",
"ui/breadcrumb/BreadcrumbPage.vue",
"ui/breadcrumb/BreadcrumbSeparator.vue",
"ui/breadcrumb/index.ts"
],
"type": "components:ui"
},
{
"name": "button",
"dependencies": [],

View File

@ -1,19 +1,41 @@
{
"name": "breadcrumb",
"dependencies": [],
"registryDependencies": [],
"registryDependencies": [
"utils"
],
"files": [
{
"name": "BreadCrumb.vue",
"content": "<template>\n <ol class=\"flex items-center whitespace-nowrap min-w-0\">\n <slot />\n </ol>\n</template>\n"
"name": "Breadcrumb.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <nav aria-label=\"breadcrumb\" :class=\"props.class\">\n <slot />\n </nav>\n</template>\n"
},
{
"name": "BreadCrumbItem.vue",
"content": "<script setup lang=\"ts\">\nimport { ChevronRight } from 'lucide-vue-next'\n\ninterface BreadCrumbItemProps {\n path?: string\n lastItem?: boolean\n as?: string | object\n}\n\nconst props = withDefaults(defineProps<BreadCrumbItemProps>(), {\n as: 'span',\n})\n</script>\n\n<template>\n <li class=\"text-sm text-muted\">\n <component\n :is=\"props.as\"\n :to=\"props.path\"\n class=\"flex items-center\"\n :class=\"{\n '!font-semibold !text-foreground': $route.path === props.path,\n }\"\n >\n <slot />\n <ChevronRight\n v-if=\"!props.lastItem\"\n class=\"flex-shrink-0 h-3 w-3 text-muted mx-2\"\n />\n </component>\n </li>\n</template>\n"
"name": "BreadcrumbEllipsis.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { MoreHorizontal } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <span\n role=\"presentation\"\n aria-hidden=\"true\"\n :class=\"cn('flex h-9 w-9 items-center justify-center', props.class)\"\n >\n <slot>\n <MoreHorizontal class=\"h-4 w-4\" />\n </slot>\n <span class=\"sr-only\">More</span>\n </span>\n</template>\n"
},
{
"name": "BreadcrumbItem.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <li\n :class=\"cn('inline-flex items-center gap-1.5', props.class)\"\n >\n <slot />\n </li>\n</template>\n"
},
{
"name": "BreadcrumbLink.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport type { PrimitiveProps } from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\ninterface Props extends PrimitiveProps {\n as?: string\n class?: HTMLAttributes['class']\n}\nconst props = withDefaults(defineProps<Props>(), {\n as: 'a',\n})\n</script>\n\n<template>\n <Primitive\n :as=\"as\"\n :as-child=\"asChild\"\n :class=\"cn('transition-colors hover:text-foreground', props.class)\"\n >\n <slot />\n </Primitive>\n</template>\n"
},
{
"name": "BreadcrumbList.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <ol\n :class=\"cn('flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5', props.class)\"\n >\n <slot />\n </ol>\n</template>\n"
},
{
"name": "BreadcrumbPage.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <span\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n :class=\"cn('font-normal text-foreground', props.class)\"\n >\n <slot />\n </span>\n</template>\n"
},
{
"name": "BreadcrumbSeparator.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { ChevronRight } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <li\n role=\"presentation\"\n aria-hidden=\"true\"\n :class=\"cn('[&>svg]:size-3.5', props.class)\"\n >\n <slot>\n <ChevronRight />\n </slot>\n </li>\n</template>\n"
},
{
"name": "index.ts",
"content": "export { default as BreadCrumb } from './BreadCrumb.vue'\nexport { default as BreadCrumbItem } from './BreadCrumbItem.vue'\n"
"content": "export { default as Breadcrumb } from './Breadcrumb.vue'\nexport { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue'\nexport { default as BreadcrumbItem } from './BreadcrumbItem.vue'\nexport { default as BreadcrumbLink } from './BreadcrumbLink.vue'\nexport { default as BreadcrumbList } from './BreadcrumbList.vue'\nexport { default as BreadcrumbPage } from './BreadcrumbPage.vue'\nexport { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'\n"
}
],
"type": "components:ui"

View File

@ -0,0 +1,42 @@
{
"name": "breadcrumb",
"dependencies": [],
"registryDependencies": [
"utils"
],
"files": [
{
"name": "Breadcrumb.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <nav aria-label=\"breadcrumb\" :class=\"props.class\">\n <slot />\n </nav>\n</template>\n"
},
{
"name": "BreadcrumbEllipsis.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { DotsHorizontalIcon } from '@radix-icons/vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <span\n role=\"presentation\"\n aria-hidden=\"true\"\n :class=\"cn('flex h-9 w-9 items-center justify-center', props.class)\"\n >\n <slot>\n <DotsHorizontalIcon class=\"h-4 w-4\" />\n </slot>\n <span class=\"sr-only\">More</span>\n </span>\n</template>\n"
},
{
"name": "BreadcrumbItem.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <li\n :class=\"cn('inline-flex items-center gap-1.5', props.class)\"\n >\n <slot />\n </li>\n</template>\n"
},
{
"name": "BreadcrumbLink.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport type { PrimitiveProps } from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\ninterface Props extends PrimitiveProps {\n as?: string\n class?: HTMLAttributes['class']\n}\nconst props = withDefaults(defineProps<Props>(), {\n as: 'a',\n})\n</script>\n\n<template>\n <Primitive\n :as=\"as\"\n :as-child=\"asChild\"\n :class=\"cn('transition-colors hover:text-foreground', props.class)\"\n >\n <slot />\n </Primitive>\n</template>\n"
},
{
"name": "BreadcrumbList.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <ol\n :class=\"cn('flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5', props.class)\"\n >\n <slot />\n </ol>\n</template>\n"
},
{
"name": "BreadcrumbPage.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <span\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n :class=\"cn('font-normal text-foreground', props.class)\"\n >\n <slot />\n </span>\n</template>\n"
},
{
"name": "BreadcrumbSeparator.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from 'vue'\nimport { ChevronRightIcon } from '@radix-icons/vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <li\n role=\"presentation\"\n aria-hidden=\"true\"\n :class=\"cn('[&>svg]:size-3.5', props.class)\"\n >\n <slot>\n <ChevronRightIcon />\n </slot>\n </li>\n</template>\n"
},
{
"name": "index.ts",
"content": "export { default as Breadcrumb } from './Breadcrumb.vue'\nexport { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue'\nexport { default as BreadcrumbItem } from './BreadcrumbItem.vue'\nexport { default as BreadcrumbLink } from './BreadcrumbLink.vue'\nexport { default as BreadcrumbList } from './BreadcrumbList.vue'\nexport { default as BreadcrumbPage } from './BreadcrumbPage.vue'\nexport { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'\n"
}
],
"type": "components:ui"
}

View File

@ -90,8 +90,8 @@ importers:
specifier: ^0.350.0
version: 0.350.0(vue@3.4.21)
radix-vue:
specifier: ^1.5.0
version: 1.5.0(vue@3.4.21)
specifier: ^1.5.2
version: 1.5.2(vue@3.4.21)
tailwindcss-animate:
specifier: ^1.0.7
version: 1.0.7(tailwindcss@3.4.1)
@ -11166,6 +11166,19 @@ packages:
- vue
dev: false
/radix-vue@1.5.2(vue@3.4.21):
resolution: {integrity: sha512-XyXB6mYm7dthW56LDHG4ttR3x+XtspTi48nSq4vHoHldgGZzAEa5VXlqUCr2J21fNKrt3NIYhIIRLB6kKwWwrA==}
dependencies:
'@floating-ui/dom': 1.6.1
'@floating-ui/vue': 1.0.6(vue@3.4.21)
'@internationalized/date': 3.5.2
fast-deep-equal: 3.1.3
nanoid: 5.0.6
transitivePeerDependencies:
- '@vue/composition-api'
- vue
dev: false
/radix3@1.1.0:
resolution: {integrity: sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==}
dev: true
@ -13049,7 +13062,7 @@ packages:
resolution: {integrity: sha512-3PYWMbN3cSdsciv3fzewskxZFnX61PYq1uNsbvizXDo/8sN4SMrWkYDqWaPdTD3GTEm6wpx7j5flRLg7A5ZXbQ==}
dependencies:
'@vueuse/core': 10.9.0(vue@3.4.21)
radix-vue: 1.5.0(vue@3.4.21)
radix-vue: 1.5.2(vue@3.4.21)
vue: 3.4.21(typescript@5.4.2)
transitivePeerDependencies:
- '@vue/composition-api'