Breadcrumb

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

Examples

Basic

PropDefaultTypeDescription
items[]arrayAn array of Links wrapped around the Button component, inheriting all its props and slots.
Preview
Code

Variant & Color

PropDefaultTypeDescription
breadcrumb-activetext-primary{variant}-{color}The active breadcrumb variant and color.
breadcrumb-inactivetext-muted{variant}-{color}The inactive breadcrumb variant and color.
Preview
Code

Separator

PropDefaultTypeDescription
separatori-radix-icons-chevron-rightstringThe separator icon.
Preview
Code

Size

Adjust the breadcrumb size without limits. Use breakpoints (e.g., sm:sm, xs:lg) for responsive sizes or states (e.g., hover:lg, focus:3xl) for state-based sizes.

PropDefaultTypeDescription
sizesmstringAdjusts the overall size of the breadcrumb component.
_breadcrumbLink.sizesmstringCustomizes the size of each breadcrumb link.
_breadcrumbSeparator.sizesmstringModifies the size of the breadcrumb separator.
Preview
Code

Slots

NamePropsDescription
defaultitemThe breadcrumb item
separatoritemThe separator
rootitemsThe root breadcrumb
listitemThe list of items
Preview
Code

Presets

shortcuts/breadcrumb.ts
type BreadcrumbPrefix = 'breadcrumb'

export const staticBreadcrumb: Record<`${BreadcrumbPrefix}-${string}` | BreadcrumbPrefix, string> = {
  // config
  'breadcrumb': '',
  'breadcrumb-active': 'breadcrumb-active-text-primary',
  'breadcrumb-inactive': 'breadcrumb-inactive-text-muted',
  'breadcrumb-separator-icon': 'i-radix-icons-chevron-right',
  'breadcrumb-elipsis-icon': 'i-radix-icons-dots-horizontal',

  // components
  'breadcrumb-root': '',
  'breadcrumb-list': 'flex flex-wrap items-center break-words text-muted',
  'breadcrumb-link': 'transition-colors font-normal',
  'breadcrumb-item': 'inline-flex items-center gap-1.5',

  // TODO
  'breadcrumb-ellipsis': 'flex items-center justify-center',
}

export const dynamicBreadcrumb = [
  // states
  [
    /^breadcrumb-active-([^-]+)-([^-]+)$/,
    ([, variant = 'text', color = 'primary']) =>
      `data-[state=active]:btn-${variant}-${color}`,
  ],
  [
    /^breadcrumb-inactive-([^-]+)-([^-]+)$/,
    ([, variant = 'text', color = 'muted']) =>
      `data-[state=inactive]:btn-${variant}-${color}`,
  ],
]

export const breadcrumb = [
  ...dynamicBreadcrumb,
  staticBreadcrumb,
]

Props

types/breadcrumb.ts
import type { HTMLAttributes } from 'vue'
import type { NButtonProps } from './button'

interface BaseExtensions { class?: HTMLAttributes['class'] }

export interface NBreadcrumbProps extends BaseExtensions, Pick<NBreadcrumbLinkProps, 'breadcrumbActive' | 'breadcrumbInactive'> {
  /**
   * List of items to display in the breadcrumb.
   *
   * @example
   * items: [{ label: 'Home', to: '/' }, { label: 'About', to: '/about' }]
   */
  items: Partial<NButtonProps>[]
  separator?: NBreadcrumbSeparatorProps['icon']
  ellipsis?: NBreadcrumbEllipsisProps['icon']
  /**
   * Allows you to change the size of the input.
   *
   * @default sm
   *
   * @example
   * size="sm" | size="2cm" | size="2rem" | size="2px"
   */
  size?: string

  // maxItems?: number

  // sub-components
  _breadcrumbSeparator?: Partial<NBreadcrumbSeparatorProps>
  _breadcrumbItem?: Partial<NBreadcrumbItemProps>
  _breadcrumbRoot?: Partial<NBreadcrumbRootProps>
  _breadcrumbList?: Partial<NBreadcrumbListProps>
  _breadcrumbLink?: Partial<NBreadcrumbLinkProps>
  _breadcrumbEllipsis?: Partial<NBreadcrumbEllipsisProps>

  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/breadcrumb.ts
   */
  una?: NBreadcrumbUnaProps
}

export interface NBreadcrumbRootProps extends BaseExtensions {
  una?: Pick<NBreadcrumbUnaProps, 'breadcrumbRoot'>
}

export interface NBreadcrumbItemProps extends BaseExtensions {
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/breadcrumb.ts
   */
  una?: Pick<NBreadcrumbUnaProps, 'breadcrumbItem'>
}

export interface NBreadcrumbSeparatorProps extends BaseExtensions {
  /**
   * Custom separator icon.
   */
  icon?: string
  /**
   * Allows you to change the size of the input.
   *
   * @default sm
   *
   * @example
   * size="sm" | size="2cm" | size="2rem" | size="2px"
   */
  size?: string
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/breadcrumb.ts
   */
  una?: Pick<NBreadcrumbUnaProps, 'breadcrumbSeparator' | 'breadcrumbSeparatorIcon'>
}

export interface NBreadcrumbListProps extends BaseExtensions {
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/breadcrumb.ts
   */
  una?: Pick<NBreadcrumbUnaProps, 'breadcrumbList'>
}

export interface NBreadcrumbLinkProps extends BaseExtensions, NButtonProps {
  active?: boolean
  breadcrumbActive?: string
  breadcrumbInactive?: string
}

export interface NBreadcrumbEllipsisProps extends BaseExtensions {
  /**
   * Custom separator icon.
   */
  icon?: string
  /**
   *  /**
   * Allows you to change the size of the input.
   *
   * @default sm
   *
   * @example
   * size="sm" | size="2cm" | size="2rem" | size="2px"
   */
  size?: string
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/breadcrumb.ts
   */
  una?: Pick<NBreadcrumbUnaProps, 'breadcrumbEllipsis' | 'breadcrumbEllipsisIcon'>
}

interface NBreadcrumbUnaProps {
  breadcrumb?: HTMLAttributes['class']
  breadcrumbRoot?: HTMLAttributes['class']
  breadcrumbItem?: HTMLAttributes['class']
  breadcrumbEllipsis?: HTMLAttributes
  breadcrumbEllipsisIcon?: HTMLAttributes['class']
  breadcrumbList?: HTMLAttributes['class']
  breadcrumbSeparator?: HTMLAttributes['class']
  breadcrumbSeparatorIcon?: HTMLAttributes['class']
}

Components

Breadcrumb.vue
BreadcrumbRoot.vue
BreadcrumbList.vue
BreadcrumbLink.vue
BreadcrumbItem.vue
BreadcrumbSeparator.vue
BreadcrumbEllipsis.vue
<script lang="ts" setup>
import type { NBreadcrumbProps } from '../../../types'
import { cn } from '../../../utils'
import BreadcrumbItem from './BreadcrumbItem.vue'
import BreadcrumbLink from './BreadcrumbLink.vue'
import BreadcrumbList from './BreadcrumbList.vue'
import BreadcrumbRoot from './BreadcrumbRoot.vue'
import BreadcrumbSeparator from './BreadcrumbSeparator.vue'

const props = defineProps<NBreadcrumbProps>()
</script>

<template>
  <BreadcrumbRoot
    :class="cn(
      'breadcrumb',
      props.class,
      props.una?.breadcrumb,
    )"
    :una
    :size
    v-bind="_breadcrumbRoot"
  >
    <slot name="root" :items="items">
      <BreadcrumbList
        :una
        :size
        v-bind="_breadcrumbList"
      >
        <template
          v-for="(item, i) in props.items"
          :key="i"
        >
          <slot name="list" :item="item">
            <BreadcrumbItem
              :una
              :size
              v-bind="_breadcrumbItem"
            >
              <slot name="item" :item="item">
                <BreadcrumbLink
                  :active="i === items.length - 1"
                  :breadcrumb-active="props.breadcrumbActive"
                  :breadcrumb-inactive="props.breadcrumbInactive"
                  :size
                  v-bind="{
                    ...item,
                    ..._breadcrumbLink,
                  }"
                >
                  <slot :item="item" />
                </BreadcrumbLink>
              </slot>
            </BreadcrumbItem>
            <BreadcrumbSeparator
              v-if="i < props.items!.length - 1"
              :icon="props.separator"
              :size
              :una
              v-bind="_breadcrumbSeparator"
            >
              <slot name="separator" />
            </BreadcrumbSeparator>
          </slot>
        </template>
      </BreadcrumbList>
    </slot>
  </BreadcrumbRoot>
</template>