SwBreadcrumb
SwBreadcrumb is a headless breadcrumb navigation: driven by an items array (first→last) of { name, to? }. Middle items with to render as SwLink (real <a>, SEO / a11y friendly); the last item = current page is always rendered as a non-clickable <span> + aria-current="page" (NN/g & Google breadcrumb guidance), even if a to is given.
schema is on by default — it calls useSchemaOrg(defineBreadcrumb(...)) from the same items to emit BreadcrumbList structured data, making the visible breadcrumb and the JSON-LD a single source of truth so the two never drift apart. When enabled, do not also hand-write defineBreadcrumb on the page.
Visuals follow the "minimal necessary baseline" (inline layout + separator + current-page emphasis); font size / color / hover are overridden by the applier.
Link color: breadcrumb links are rendered by SwLink and default to the primary color. To use a muted color, set the CSS variable
--sw-link-color: var(--muted-foreground)on a container (cascades via the variable). Do not write.sw-link { color }(equal specificity gambles on CSS source order; dev/prod can flip).
Basic usage
Omit to on the last item to mark it the current page (you may still give to — used only for JSON-LD; it stays non-clickable):
Basic three-level breadcrumb
<script setup lang="ts">
const crumbs = [
{ name: 'Home', to: '/' },
{ name: 'Shorts', to: '/shorts' },
{ name: 'Trending' },
]
</script>
<template>
<SwBreadcrumb :items="crumbs" />
</template>
Custom separator
separator prop changes the separator text; the #separator slot can hold any content:
separator prop / #separator slot
Custom item rendering
The #item slot fully takes over per-item rendering, exposing { item, isLast } in scope:
#item slot customization
BreadcrumbList JSON-LD (schema)
schema defaults to true: the component emits BreadcrumbList structured data from the same items (item = each entry's to, omitted when the last entry has no to). This keeps the visible breadcrumb and the structured data a single source of truth, avoiding the "page hand-writes defineBreadcrumb while the visible UI drifts" problem.
- Pages using
SwBreadcrumb(withschemaon) must not also hand-writeuseSchemaOrg(defineBreadcrumb(...)), or output is duplicated. - When the page manages structured data itself, pass
:schema="false"to render only the visible UI.
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
items | SwBreadcrumbItem[] | ✓ | — | Breadcrumb chain (first→last). Last item = current page, auto non-clickable + aria-current |
schema | boolean | true | Also emit BreadcrumbList JSON-LD (single source with the visible UI). Don't hand-write defineBreadcrumb when on | |
separator | string | '/' | Separator text (overridable via the #separator slot) | |
ariaLabel | string | '面包屑' | aria-label for the <nav> |
SwBreadcrumbItem: { name: string; to?: string }. Omitting to = non-clickable; the last item is always the current page regardless of to (to only feeds the JSON-LD item).
Slots
| Name | Scope | Description |
|---|---|---|
separator | — | Custom separator (overrides the separator prop) |
item | { item, isLast } | Custom per-item rendering. Falls back to default link / current-page rendering |
Notes
- Last item is always the current page: non-clickable +
aria-current="page"(even withto), per NN/g / Google breadcrumb guidance. - Single source, no drift: when
schemais on, the visible UI and JSON-LD come from oneitems; don't hand-writedefineBreadcrumbon the page. - Link color: override the
--sw-link-colorvariable; don't write.sw-link { color }. - No built-in visual brand: only minimal inline + separator + current-page styles; the rest is overridden by the applier (target
.sw-breadcrumb).