SvBreadcrumb

A navigation trail that shows where the current page sits in your app's hierarchy.

SvBreadcrumb renders an ordered list of crumbs. Each item is a link (when you give it an href), a button (when you give it an onClick), or plain text. The last item is the current page and is never interactive - it carries aria-current="page". Long trails collapse their middle into an expandable ellipsis so a deep path never overflows the bar. Every color comes from the grid's --sg-* tokens, so it matches your grid and forms in light and dark.

Basic usage

<script lang="ts">
  import { SvBreadcrumb } from '@svgrid/grid'
</script>

<SvBreadcrumb items={[
  { label: 'Home', href: '/' },
  { label: 'Orders', href: '/orders' },
  { label: '#1024' },
]} />

Props

Prop Type Default Description
items ReadonlyArray<BreadcrumbItem> - The crumbs, root first. The last is the current page.
separator string / Glyph drawn between crumbs (e.g. a chevron).
maxItems number - Collapse the middle to an ellipsis when the trail exceeds this.
ariaLabel string Breadcrumb Accessible name for the <nav> landmark.

BreadcrumbItem (exported): { label: string; href?: string; onClick?: () => void; icon?: string }. Pass href for a real link, onClick for a router push, or neither for static text. icon is any string (emoji, char, or font-icon glyph) rendered before the label.

Patterns

Router navigation without full page loads

Use onClick instead of href when you drive navigation through a client-side router, so no full document load happens:

<SvBreadcrumb items={[
  { label: 'Home', onClick: () => goto('/') },
  { label: 'Reports', onClick: () => goto('/reports') },
  { label: 'Q3' },
]} />

Collapsing deep trails

Set maxItems and long paths keep the first crumb, an ellipsis button, and the last two. Clicking the ellipsis expands the full trail:

<SvBreadcrumb maxItems={4} items={deepPath} />

Icons in crumbs

Give any crumb an icon for a leading glyph, handy for a home root:

<SvBreadcrumb items={[{ label: 'Home', href: '/', icon: '🏠' }, { label: 'Team' }]} />

Building the trail from a route

Derive the crumbs from the current path so the trail always matches where the router is. Give every crumb but the last an onClick that pushes the matching sub-path; leave the last one plain so it renders as the current page:

<script lang="ts">
  import { SvBreadcrumb, type BreadcrumbItem } from '@svgrid/grid'
  import { page } from '$app/state'
  import { goto } from '$app/navigation'

  const titles: Record<string, string> = { orders: 'Orders', items: 'Items' }

  // /orders/1024/items -> Home / Orders / 1024 / Items
  const crumbs = $derived.by<BreadcrumbItem[]>(() => {
    const segments = page.url.pathname.split('/').filter(Boolean)
    return [
      { label: 'Home', icon: '🏠', onClick: () => goto('/') },
      ...segments.map((seg, i) => {
        const label = titles[seg] ?? seg
        if (i === segments.length - 1) return { label }
        const href = '/' + segments.slice(0, i + 1).join('/')
        return { label, onClick: () => goto(href) }
      }),
    ]
  })
</script>

<SvBreadcrumb items={crumbs} maxItems={4} separator="›" />

Tip: when collapsed, the trail always keeps the first crumb plus the last two, so maxItems only changes the display once you have more than three crumbs. Set it a step above your typical depth so shallow pages never sprout an ellipsis.

Accessibility

See also