Breadcrumb

Displays the path to the current page.
Installation
Expand

npx @left4code/cosmic-ui-cli@latest add breadcrumb
 
Expand

This writes the component and everything it imports, then installs the packages it needs. Run npx @left4code/cosmic-ui-cli@latest initfirst if you haven't already (it detects Vue automatically).

No state machine here - a breadcrumb trail doesn't need one, it's plain semantic markup (nav > ol > li). Vue SFCs can't export multiple components from one file, so Breadcrumb is a folder instead of a single file — copy all of it into your project.

components/ui/breadcrumb/BreadcrumbRoot.vue
Expand

<script setup lang="ts">
// Astro forwards a slot="preview" used to route this island into a named
// slot as a genuine prop on whatever Vue renders at the top of that island.
// Without opting out of attribute inheritance, Vue falls that unrecognized
// prop through onto this root DOM node - and SSR and the client hydration
// script disagree on whether to do that, so it becomes a hydration mismatch
// on every page that mounts this component directly (as every demo does).
defineOptions({ inheritAttrs: false });
defineProps<{ class?: string }>();
</script>

<template>
  <nav aria-label="breadcrumb" :class="$props.class">
    <slot />
  </nav>
</template>
 
Expand
components/ui/breadcrumb/BreadcrumbList.vue
Expand

<script setup lang="ts">
import { twMerge } from "tailwind-merge";

const { class: className } = defineProps<{ class?: string }>();
</script>

<template>
  <ol :class="twMerge(['flex flex-wrap items-center gap-2', className])">
    <slot />
  </ol>
</template>
 
Expand
components/ui/breadcrumb/BreadcrumbItem.vue
Expand

<script setup lang="ts">
import { twMerge } from "tailwind-merge";

const { class: className } = defineProps<{ class?: string }>();
</script>

<template>
  <li :class="twMerge(['flex items-center gap-2', className])">
    <slot />
  </li>
</template>
 
Expand
components/ui/breadcrumb/BreadcrumbLink.vue
Expand

<script setup lang="ts">
import { twMerge } from "tailwind-merge";

const { href, class: className } = defineProps<{ href: string; class?: string }>();
</script>

<template>
  <a :href="href" :class="twMerge(['text-foreground/50 hover:text-foreground', className])">
    <slot />
  </a>
</template>
 
Expand
components/ui/breadcrumb/BreadcrumbPage.vue
Expand

<script setup lang="ts">
import { twMerge } from "tailwind-merge";

const { class: className } = defineProps<{ class?: string }>();
</script>

<template>
  <span aria-current="page" :class="twMerge(['text-foreground', className])">
    <slot />
  </span>
</template>
 
Expand
components/ui/breadcrumb/BreadcrumbSeparator.vue
Expand

<script setup lang="ts">
import { ChevronRight } from "@lucide/vue";
import { twMerge } from "tailwind-merge";

const { class: className } = defineProps<{ class?: string }>();
</script>

<template>
  <li role="presentation" aria-hidden="true" :class="twMerge(['text-foreground/30', className])">
    <ChevronRight class="size-3.5" />
  </li>
</template>
 
Expand
components/ui/breadcrumb/index.ts
Expand

export { default as BreadcrumbRoot } from "./BreadcrumbRoot.vue";
export { default as BreadcrumbList } from "./BreadcrumbList.vue";
export { default as BreadcrumbItem } from "./BreadcrumbItem.vue";
export { default as BreadcrumbLink } from "./BreadcrumbLink.vue";
export { default as BreadcrumbPage } from "./BreadcrumbPage.vue";
export { default as BreadcrumbSeparator } from "./BreadcrumbSeparator.vue";
 
Expand

Update the import paths to match your project setup.

Usage
Expand

import {
  BreadcrumbRoot,
  BreadcrumbList,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
 
Expand
Expand

<BreadcrumbRoot>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/docs">Docs</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
    </BreadcrumbItem>
  </BreadcrumbList>
</BreadcrumbRoot>
 
Expand
Powered by synthetic caffeine · Deployed by Left4code · Signal traceable on GitHub.