Skip to content

Smart breadcrumb ​

A breadcrumb built from the matched route records. No per-page configuration.

Open in demo
Open in demo

Usage ​

Drop it in a layout's #breadcrumb slot and it reads the current route. Every matched record carrying a meta.title becomes a crumb, and the last one is plain text rather than a link, because that is where you already are.

ts
{
  path: '/crm/customers',
  meta: { title: 'Customers' },
}

meta.breadcrumb overrides meta.title for the crumb only, which is how a route can have a long page title and a short crumb.

Dynamic labels ​

meta.breadcrumb may be a function, and it may be async. That is how a record's own name becomes the crumb:

ts
{
  path: '/crm/customers/:id',
  meta: {
    breadcrumb: async route => (await fetchCustomer(route.params.id)).name,
  },
}

Labels resolve into a map keyed by route path, and the trail reacts when they land, so the crumb fills in without the page waiting for it.

A string meta.title or meta.breadcrumb goes through uiText, so a translation key is translated and a literal is left alone. A value returned by a function is a runtime value, a record's name, and is passed through untouched. See Internationalization.

Hiding it ​

Any matched record with meta.hideBreadcrumb hides the whole trail, so a section can opt out at its parent rather than on every child.

The component also renders nothing when no crumb has a label, so a route with no titles leaves no empty bar behind.

API ​

Source: src/shared/components/common/SmartBreadcrumb.vue

Props ​

None. It reads the route.

Emits ​

None.

Slots ​

None.

Route meta it reads ​

KeyTypeDescription
meta.titlestringThe crumb, unless meta.breadcrumb is set. Resolved through uiText.
meta.breadcrumbstring | (route) => string | Promise<string>Overrides the crumb. A function may be async.
meta.hideBreadcrumbbooleanOn any matched record, hides the whole trail.

Accessibility ​

  • It renders a real breadcrumb: a <nav aria-label="breadcrumb"> around an ordered list.
  • The last crumb carries aria-current="page", so the reader is told which one they are on.
  • Separators are role="presentation" and aria-hidden, so the trail is not read as a run of slashes.