Breadcrumb

Displays the path to the current resource using a hierarchy of links.

Basic
With Dropdown
With Link

Installation

Install the dependencies

pnpm add cn

Copy the component

Copy the following files into src/lib/components/ui/breadcrumb.

src/lib/components/ui/breadcrumb/Breadcrumb.svelte
<script lang="ts">
  import type { BreadcrumbProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: BreadcrumbProps = $props();
</script>
<nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} class={cn('', classProp)}>
  {@render children?.()}
</nav>
src/lib/components/ui/breadcrumb/BreadcrumbEllipsis.svelte
<script lang="ts">
  import type { BreadcrumbEllipsisProps } from './types.js';
  import { cn } from 'cn';
  import MoreHorizontalIcon from '@lucide/svelte/icons/more-horizontal';
  let { class: classProp, ...props }: BreadcrumbEllipsisProps = $props();
</script>
<span data-slot="breadcrumb-ellipsis" role="presentation" aria-hidden="true" {...props} class={cn('size-5 [&>svg]:size-4 flex items-center justify-center', classProp)}>
  <MoreHorizontalIcon
  />
  <span class="sr-only">More</span>
</span>
src/lib/components/ui/breadcrumb/BreadcrumbItem.svelte
<script lang="ts">
  import type { BreadcrumbItemProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: BreadcrumbItemProps = $props();
</script>
<li data-slot="breadcrumb-item" {...props} class={cn('gap-1 inline-flex items-center', classProp)}>
  {@render children?.()}
</li>
src/lib/components/ui/breadcrumb/BreadcrumbLink.svelte
<script lang="ts">
  import type { BreadcrumbLinkProps, BreadcrumbLinkState } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, render, ...props }: BreadcrumbLinkProps = $props();
  const state: BreadcrumbLinkState = { slot: 'breadcrumb-link' };
  const hostProps = $derived({ 'data-slot': state.slot, ...props, class: cn('hover:text-foreground transition-colors', classProp) });
</script>
{#if render}
  {@render render(hostProps, state, children)}
{:else}
  <a {...hostProps}>{@render children?.()}</a>
{/if}
src/lib/components/ui/breadcrumb/BreadcrumbList.svelte
<script lang="ts">
  import type { BreadcrumbListProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: BreadcrumbListProps = $props();
</script>
<ol data-slot="breadcrumb-list" {...props} class={cn('text-muted-foreground gap-1.5 text-sm flex flex-wrap items-center wrap-break-word', classProp)}>
  {@render children?.()}
</ol>
src/lib/components/ui/breadcrumb/BreadcrumbPage.svelte
<script lang="ts">
  import type { BreadcrumbPageProps } from './types.js';
  import { cn } from 'cn';
  let { children, class: classProp, ...props }: BreadcrumbPageProps = $props();
</script>
<span data-slot="breadcrumb-page" role="link" aria-disabled="true" aria-current="page" {...props} class={cn('text-foreground font-normal', classProp)}>
  {@render children?.()}
</span>
src/lib/components/ui/breadcrumb/BreadcrumbSeparator.svelte
<script lang="ts">
  import type { BreadcrumbSeparatorProps } from './types.js';
  import { cn } from 'cn';
  import ChevronRightIcon from '@lucide/svelte/icons/chevron-right';
  let { children, class: classProp, ...props }: BreadcrumbSeparatorProps = $props();
</script>
<li data-slot="breadcrumb-separator" role="presentation" aria-hidden="true" {...props} class={cn('[&>svg]:size-3.5', classProp)}>
  {#if children}
    {@render children()}
  {:else}
    <ChevronRightIcon
      class=""
    />
  {/if}
</li>
src/lib/components/ui/breadcrumb/types.ts
import type { HTMLAnchorAttributes, HTMLAttributes, HTMLLiAttributes, HTMLOlAttributes } from 'svelte/elements';
import type { RenderSnippet } from '../shared/render.js';

export type BreadcrumbProps = HTMLAttributes<HTMLElement>;
export type BreadcrumbListProps = HTMLOlAttributes;
export type BreadcrumbItemProps = HTMLLiAttributes;
export type BreadcrumbLinkState = { slot: 'breadcrumb-link' };
export type BreadcrumbLinkProps = HTMLAnchorAttributes & { render?: RenderSnippet<BreadcrumbLinkState, HTMLAnchorElement> };
export type BreadcrumbPageProps = HTMLAttributes<HTMLSpanElement>;
export type BreadcrumbSeparatorProps = HTMLLiAttributes;
export type BreadcrumbEllipsisProps = HTMLAttributes<HTMLSpanElement>;
src/lib/components/ui/shared/render.ts
import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';

/**
 * Replaces a part's default element, like the `render` snippets of Sveltery Base.
 * Spread `props` onto the host element and render `children` inside it.
 * `Host` is the element the part renders by default, so its typed event handlers carry over.
 */
export type RenderSnippet<State, Host extends HTMLElement = HTMLElement> = Snippet<[props: HTMLAttributes<Host>, state: State, children: Snippet | undefined]>;
src/lib/components/ui/breadcrumb/index.ts
export { default as Breadcrumb } from './Breadcrumb.svelte';
export { default as BreadcrumbList } from './BreadcrumbList.svelte';
export { default as BreadcrumbItem } from './BreadcrumbItem.svelte';
export { default as BreadcrumbLink } from './BreadcrumbLink.svelte';
export { default as BreadcrumbPage } from './BreadcrumbPage.svelte';
export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.svelte';
export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.svelte';
export type {
  BreadcrumbProps, BreadcrumbListProps, BreadcrumbItemProps, BreadcrumbLinkProps, BreadcrumbLinkState,
  BreadcrumbPageProps, BreadcrumbSeparatorProps, BreadcrumbEllipsisProps,
} from './types.js';

Update the import paths

Change the imports to match your project setup.

Usage

<script lang="ts">
  import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '$lib/components/ui/breadcrumb';
</script>
<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem>
      <BreadcrumbLink href="/">Home</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbLink href="/components">Components</BreadcrumbLink>
    </BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem>
      <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
    </BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>