wui
组件

面包屑 Breadcrumb

显示当前页面在应用信息架构中的层级路径,帮助用户快速感知位置并返回上层页面。

第三方依赖 · lucide-react第三方依赖 · radix-ui

基础用法

最简单的面包屑导航。使用 BreadcrumbList、BreadcrumbItem、BreadcrumbLink、BreadcrumbSeparator 与 BreadcrumbPage 组合层级:

Loading…

安装与引入

通过 CLI 自动添加组件,或手动复制源码至项目中:

pnpm dlx @wui-design/cli@latest add @wui/breadcrumb
安装基础依赖与图标库
pnpm add radix-ui lucide-react clsx tailwind-merge
复制组件源码到 components/ui/breadcrumb.tsx
components/ui/breadcrumb.tsx
import * as React from "react"
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
import { Slot } from "radix-ui"

import { cn } from "@/lib/utils"

/** 面包屑导航容器,默认提供可访问名称。 */
function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
  return <nav aria-label="面包屑导航" data-slot="breadcrumb" {...props} />
}

/** 面包屑项目列表。 */
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
  return (
    <ol
      data-slot="breadcrumb-list"
      className={cn(
        "text-muted-foreground m-0 flex list-none flex-wrap items-center gap-1.5 p-0 text-sm sm:gap-2.5",
        className
      )}
      {...props}
    />
  )
}

/** 单个面包屑项目。 */
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
  return (
    <li
      data-slot="breadcrumb-item"
      className={cn(
        "m-0 inline-flex min-w-0 items-center gap-1.5 p-0",
        className
      )}
      {...props}
    />
  )
}

export interface BreadcrumbLinkProps extends React.ComponentProps<"a"> {
  /** 将样式与属性合并到唯一子元素,适合组合路由链接。 */
  asChild?: boolean
}

/** 可跳转的面包屑链接。 */
function BreadcrumbLink({
  asChild = false,
  className,
  ...props
}: BreadcrumbLinkProps) {
  const Comp = asChild ? Slot.Root : "a"

  return (
    <Comp
      data-slot="breadcrumb-link"
      className={cn(
        "hover:text-foreground focus-visible:ring-ring/40 rounded-sm no-underline outline-none transition-colors duration-200 focus-visible:ring-[3px]",
        className
      )}
      {...props}
    />
  )
}

/** 当前页面,自动标记 `aria-current="page"`。 */
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      aria-current="page"
      data-slot="breadcrumb-page"
      className={cn("text-foreground font-medium", className)}
      {...props}
    />
  )
}

/** 相邻面包屑之间的装饰性分隔符。 */
function BreadcrumbSeparator({
  children,
  className,
  ...props
}: React.ComponentProps<"li">) {
  return (
    <li
      aria-hidden="true"
      data-slot="breadcrumb-separator"
      role="presentation"
      className={cn("m-0 p-0 [&>svg]:size-3.5", className)}
      {...props}
    >
      {children ?? <ChevronRightIcon />}
    </li>
  )
}

/** 表示中间路径被折叠的省略项。 */
function BreadcrumbEllipsis({
  className,
  ...props
}: React.ComponentProps<"span">) {
  return (
    <span
      data-slot="breadcrumb-ellipsis"
      className={cn("flex size-7 items-center justify-center", className)}
      {...props}
    >
      <MoreHorizontalIcon aria-hidden="true" className="size-4" />
      <span className="sr-only">更多层级</span>
    </span>
  )
}

export {
  Breadcrumb,
  BreadcrumbEllipsis,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
}

属性 Props

继承原生 <nav> 元素的全部 HTML 属性:

属性类型默认值说明
aria-labelstring"面包屑导航"用于屏幕阅读器识别导航地标的可访问名称。
classNamestring—应用于外层 nav 元素的额外 CSS 类名。

继承原生 <a> 元素的全部 HTML 属性:

属性类型默认值说明
hrefstring—目标跳转链接地址。
asChildbooleanfalse启用后将样式与属性合并到唯一的子元素(如 Next.js `<Link>`)。
classNamestring—应用于链接元素的额外 CSS 类名。

当前所在页面的文本容器,自动附带 aria-current="page" 语义:

属性类型默认值说明
childrenReact.ReactNode—当前页面的标题或内容展示。
classNamestring—应用于当前页标签的额外 CSS 类名。

用于相邻面包屑项目之间的装饰性分隔符:

属性类型默认值说明
childrenReact.ReactNode<ChevronRightIcon />自定义分隔符图标或字符。若不传则默认使用右箭头图标。
classNamestring—应用于分隔符 `<li>` 元素的额外 CSS 类名。

用于表示中间长路径被折叠的省略号占位符:

属性类型默认值说明
classNamestring—应用于省略号图标容器的额外 CSS 类名。

事件 Events

面包屑各子元素均继承原生 HTML 事件:

属性类型默认值说明
onClick(event: React.MouseEvent<HTMLAnchorElement>) => void—用户点击可跳转链接项时触发,可用于 SPA 客户端路由拦截或埋点追踪。
onFocus(event: React.FocusEvent<HTMLAnchorElement>) => void—链接项通过键盘 Tab 或鼠标聚焦时触发。
onKeyDown(event: React.KeyboardEvent<HTMLAnchorElement>) => void—在链接项聚焦状态下按下按键时触发。

使用场景与设计规范

Breadcrumb 用于表达有层级关系的纵深路径结构(例如:首页 > 控制台 > 集群管理 > 节点详情):

  • 辅助导航而非主导航:面包屑旨在辅助用户了解“我在哪里”以及“如何返回上级”,不能代替顶部 Navbar 或左侧 Sidebar 等核心主导航系统。
  • 当前页不可点击:末尾的当前页面项必须使用 BreadcrumbPage(纯文本容器并内置 aria-current="page"),不应赋予链接跳转属性,避免无意义的页面重载。
  • 层级过深时合理折叠:当路径层级超过 4~5 层或在移动端等小屏幕上时,应使用 BreadcrumbEllipsis 折叠中间层级,或配合 DropdownMenu 提供便捷跳转。
  • 路径命名与页面标题一致:面包屑中的每一级文案应与对应目标页面的实际主标题保持一致,降低用户的认知负荷。

场景示例

搭配图标指示

在面包屑各级节点前加入上下文图标(如首页图标、文件夹图标、配置图标),提高视觉识别效率:

Loading…

自定义分隔符

支持通过在 <BreadcrumbSeparator> 内部传入自定义图标(如斜杠 <SlashIcon>、推进箭头 <ArrowRightIcon>)或文本字符(如 •):

Loading…

折叠长路径与下拉菜单

对于深层级文件目录或多层资源拓扑,将省略号与 DropdownMenu 结合,既节省屏幕横向宽度,又保留快速跨级导航的能力:

Loading…

简单折叠占位

使用 BreadcrumbEllipsis 纯展示性折叠路径:

Loading…

路径进出动效与展开折叠

在文件浏览器等路径频繁变化的场景中,可以用 motion.create 包装 BreadcrumbItem 与 BreadcrumbSeparator,配合 AnimatePresence 让新层级从左侧滑入、返回上级时多余层级淡出,其余项平滑补位。层级超过 4 级时中间路径折叠为省略号按钮,点击后原地展开:

Loading…

启用 asChild 属性,组件会自动将类名与可访问属性合并至第三方路由链接上,避免生成无效嵌套标签:

import Link from "next/link"
import { BreadcrumbItem, BreadcrumbLink } from "@/registry/ui/breadcrumb"

<BreadcrumbItem>
  <BreadcrumbLink asChild>
    <Link href="/dashboard/projects">项目列表</Link>
  </BreadcrumbLink>
</BreadcrumbItem>

无障碍与交互 Accessibility

  • 语义地标 Landmark:根组件自动渲染为 <nav aria-label="面包屑导航">,屏幕阅读器用户可通过快捷键直接跳转至该导航地标。
  • 列表结构语义:内部采用 <ol> 与 <li> 的有序列表结构,精确传达出页面从上至下的父子层级顺序。
  • 当前页语义标注:BreadcrumbPage 自动携带 aria-current="page" 属性,盲文与语音读屏器会自动播报“当前页面”。
  • 装饰元素隔离:BreadcrumbSeparator 内置 aria-hidden="true" 和 role="presentation";BreadcrumbEllipsis 仅隐藏图标,保留 sr-only 的「更多层级」文案,放入按钮或下拉触发器时可被正确播报(也可在触发器上用 aria-label 覆盖)。
  • 键盘焦点轮廓:BreadcrumbLink 具备高对比度的 Focus Ring 焦点态轮廓,支持通过 Tab 键快速顺序遍历所有有效链接。