Breadcrumb

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

In active development for Expo Web. Because Expo apps also run on the web, breadcrumb is still being refined for web layouts (hover states, truncation, and keyboard focus). It works on native today, but the web styling and API may still change.

Installation

npx lovdacn@latest add breadcrumb

(You can also use the shortened lvcn alias, e.g., npx lvcn@latest add breadcrumb.)

Registry dependencies: icon, text, utils

Usage

import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Text } from "@/components/ui/text"

export function Example() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink onPress={() => {}}>
            <Text>Home</Text>
          </BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbLink onPress={() => {}}>
            <Text>Components</Text>
          </BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbPage>Breadcrumb</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  )
}

With Expo Router

Use asChild on BreadcrumbLink to render an Expo Router Link (or any pressable) as the breadcrumb link:

import { Link } from "expo-router"

<BreadcrumbItem>
  <BreadcrumbLink asChild>
    <Link href="/">
      <Text>Home</Text>
    </Link>
  </BreadcrumbLink>
</BreadcrumbItem>

Anatomy

PartDescription
BreadcrumbThe navigation wrapper.
BreadcrumbListThe ordered list of items; sets muted text styling.
BreadcrumbItemA single item (link or page).
BreadcrumbLinkA pressable link. Supports asChild.
BreadcrumbPageThe current page (non-interactive).
BreadcrumbSeparatorThe divider between items (defaults to a chevron; pass children to override).
BreadcrumbEllipsisA collapsed-items indicator.

Complexity: mobile vs. desktop

Breadcrumbs are a desktop-first pattern, and they get awkward on phones — plan for it.

Why they're hard on mobile

  • Horizontal space. A trail like Home / Projects / Acme / Settings / Billing overflows a phone width and either wraps to two lines or scrolls sideways (a poor, easily-missed affordance).
  • Tiny tap targets. Cramming many links onto one line makes each one small; separators can be mis-tapped.
  • Redundancy. Native mobile apps navigate with a back gesture/button + a screen title, so a full trail often duplicates what the header + back already convey.

Best methods

  • Prefer a title + back on phones. Show the current page title in the top bar (that's what the blocks in this library do) and rely on the platform back gesture. Reserve the full breadcrumb for tablet/desktop widths.

  • Collapse the middle. If you must show a trail on mobile, keep only the root and the current page and replace the middle with BreadcrumbEllipsis (optionally opening a menu):

    <BreadcrumbList>
      <BreadcrumbItem>
        <BreadcrumbLink onPress={goHome}><Text>Home</Text></BreadcrumbLink>
      </BreadcrumbItem>
      <BreadcrumbSeparator />
      <BreadcrumbItem>
        <BreadcrumbEllipsis />
      </BreadcrumbItem>
      <BreadcrumbSeparator />
      <BreadcrumbItem>
        <BreadcrumbPage>Billing</BreadcrumbPage>
      </BreadcrumbItem>
    </BreadcrumbList>
  • Render responsively. Gate the trail on width with useWindowDimensions() (e.g. show it at >= 768, show a title otherwise) instead of letting it wrap.

  • Keep targets comfortable. Give links ≥ 44px of touchable height and keep BreadcrumbSeparator / BreadcrumbEllipsis non-interactive.

Platform

Targets Expo / React Native with NativeWind or Uniwind. BreadcrumbLink uses a Pressable (or a slotted child via asChild) instead of an anchor, and the separator/ellipsis icons come from lucide-react-native.