代码演示
如何引入
import { Breadcrumb } from '@fibrous/semi-ui-react';
基本用法
代码
import { Breadcrumb } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
return (
<Breadcrumb>
<Breadcrumb.Item>Semi-ui</Breadcrumb.Item>
<Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
<Breadcrumb.Item>Default</Breadcrumb.Item>
</Breadcrumb>
);
}带图标的
支持标题只显示图标或者同时显示图标和文本。
代码
import { IconHome, IconArticle } from '@fibrous/semi-icons-react';
import { Breadcrumb } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
return (
<Breadcrumb>
<Breadcrumb.Item icon={<IconHome size="small" />} />
<Breadcrumb.Item icon={<IconArticle size="small" />}>Breadcrumb</Breadcrumb.Item>
<Breadcrumb.Item>With Icon</Breadcrumb.Item>
</Breadcrumb>
);
}尺寸
默认为 compact,设置属性为 false 可使图标和文字尺寸增加。
代码
import { IconHome } from '@fibrous/semi-icons-react';
import { Breadcrumb } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
// Several breadcrumbs on one page are told apart by aria-label
return (
<div>
<Breadcrumb compact aria-label="紧凑面包屑">
<Breadcrumb.Item icon={<IconHome size="small" />} />
<Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
<Breadcrumb.Item>Loose</Breadcrumb.Item>
</Breadcrumb>
<br />
<Breadcrumb compact={false} aria-label="宽松面包屑">
<Breadcrumb.Item icon={<IconHome size="small" />} />
<Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
<Breadcrumb.Item>Loose</Breadcrumb.Item>
</Breadcrumb>
</div>
);
}自定义的分隔符
默认为 /。
代码
import { IconArrowRight } from '@fibrous/semi-icons-react';
import { Breadcrumb, Tag } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
// Several breadcrumbs on one page are told apart by aria-label
return (
<div>
<Breadcrumb separator=">" aria-label="文字分隔符">
<Breadcrumb.Item>Semi-ui</Breadcrumb.Item>
<Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
<Breadcrumb.Item>Default</Breadcrumb.Item>
</Breadcrumb>
<br />
<Breadcrumb separator={<IconArrowRight size="small" />} aria-label="图标分隔符">
<Breadcrumb.Item>Semi-ui</Breadcrumb.Item>
<Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
<Breadcrumb.Item>Default</Breadcrumb.Item>
</Breadcrumb>
<br />
<Tag>{`v>=1.16.0`}</Tag>
<br />
<Breadcrumb aria-label="单项分隔符">
<Breadcrumb.Item separator=":">Semi-ui</Breadcrumb.Item>
<Breadcrumb.Item>Breadcrumb</Breadcrumb.Item>
<Breadcrumb.Item>Default</Breadcrumb.Item>
</Breadcrumb>
</div>
);
}截断逻辑
当级别名字溢出设定宽度后省略截断。可以通过 showTooltip 属性设置相关参数。默认宽度150px,鼠标悬停时显示 Tooltip 完整显示级别名称。Breadcrumb.Item 的子节点为数字时(含 0)按文字处理,同样参与截断与 Tooltip。
省略但不显示Tooltip
不截断
从标题中间开始省略
自定义 Tooltip 参数
代码
import { Breadcrumb, Typography } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
const routes = ['首页', '当这个页面标题很长很长很长时需要省略', '详情页'];
const { Text } = Typography;
// Several breadcrumbs on one page are told apart by aria-label
return (
<>
<Text size="small">默认行为</Text>
<Breadcrumb routes={routes} aria-label="默认行为" />
<br />
<Text size="small">省略但不显示Tooltip</Text>
<Breadcrumb showTooltip={false} routes={routes} aria-label="省略但不显示Tooltip" />
<br />
<Text size="small">不截断</Text>
<Breadcrumb showTooltip={{ width: 'auto' }} routes={routes} aria-label="不截断" />
<br />
<Text size="small">从标题中间开始省略</Text>
<Breadcrumb showTooltip={{ ellipsisPos: 'middle' }} routes={routes} aria-label="从标题中间开始省略" />
<br />
<Text size="small">自定义 Tooltip 参数</Text>
<Breadcrumb showTooltip={{ opts: { position: 'topLeft' } }} routes={routes} aria-label="自定义 Tooltip 参数" />
</>
);
}当路径层级超过 maxItemCount(默认 4)个,默认折叠第 2 项到第 n-m+1 项(n 为层级总数,m 为 maxItemCount,序号从 1 计,最多到倒数第二项),点击省略号展开显示全部级别;如果过长则自动换行。首项、当前项与末项始终可见。activeIndex 指向会被折叠的项时,当前项保持可见:当前项之前与之后各是一段候选折叠项,折叠项更多的一段被折叠(相等时折叠之前的一段),因此始终只有一个省略号;候选为空时不折叠,此时可见的项可能多于 maxItemCount。可以通过 maxItemCount 来控制超过多少个级别进行折叠。
代码
import { Breadcrumb } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
return (
<Breadcrumb>
<Breadcrumb.Item>首页</Breadcrumb.Item>
<Breadcrumb.Item>当层级很多的时候</Breadcrumb.Item>
<Breadcrumb.Item>又一层</Breadcrumb.Item>
<Breadcrumb.Item>再一层</Breadcrumb.Item>
<Breadcrumb.Item>上上一层</Breadcrumb.Item>
<Breadcrumb.Item>上一层</Breadcrumb.Item>
<Breadcrumb.Item>详情页</Breadcrumb.Item>
</Breadcrumb>
);
}自定义省略号区域
组件内部提供了两种省略号区域渲染的类型,可通过 moreType 来设置,moreType 的可选值为 default 和 popover。
代码
import { Breadcrumb } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
return (
<Breadcrumb moreType="popover">
<Breadcrumb.Item>首页</Breadcrumb.Item>
<Breadcrumb.Item>当层级很多的时候</Breadcrumb.Item>
<Breadcrumb.Item>又一层</Breadcrumb.Item>
<Breadcrumb.Item>再一层</Breadcrumb.Item>
<Breadcrumb.Item>上上一层</Breadcrumb.Item>
<Breadcrumb.Item>上一层</Breadcrumb.Item>
<Breadcrumb.Item>详情页</Breadcrumb.Item>
</Breadcrumb>
);
}如果想要为省略号区域自定义其他形式的渲染,则可以使用 renderMore() 方法。
代码
import React, { type ReactNode } from 'react';
import { IconMore } from '@fibrous/semi-icons-react';
import { Breadcrumb, Popover } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
const separator = '-'; // 拼接 restItem 用的分隔符
const renderMore = (restItem: ReactNode[]) => {
const content = (
<>
{restItem.map((item: ReactNode, idx: number) => (
<React.Fragment key={`restItem-${idx}`}>
{item}
{idx !== restItem.length - 1 && <span style={{ color: 'var(--semi-color-text-2)', marginRight: '6px' }}>{separator}</span>}
</React.Fragment>
))}
</>
);
return (
<Popover content={content} style={{ padding: 12 }} showArrow>
<IconMore tabIndex={-1} />
</Popover>
);
};
return (
<Breadcrumb renderMore={renderMore} onClick={(item, e) => console.log(item, e)}>
<Breadcrumb.Item>首页</Breadcrumb.Item>
<Breadcrumb.Item>当层级很多的时候</Breadcrumb.Item>
<Breadcrumb.Item>又一层</Breadcrumb.Item>
<Breadcrumb.Item>再一层</Breadcrumb.Item>
<Breadcrumb.Item>上上一层</Breadcrumb.Item>
<Breadcrumb.Item>上一层</Breadcrumb.Item>
<Breadcrumb.Item>详情页</Breadcrumb.Item>
</Breadcrumb>
);
}路由对象
Breadcrumb 支持通过 routes 传入路由对象 route: { name, path, href, icon } 或字符串组成的数组。可以配合 renderItem 来渲染节点。通过这样实现的 Breadcrumb 同样会进行截断处理。
- name 为展示的名称,不传入时为空字符串。当 route 为字符串时,默认将字符串设置为名称。
- path 为路由路径
- href 为链接目的地,挂载在 a 标签上。
- icon 为标签的显示图标
代码
import { IconHome, IconArticle } from '@fibrous/semi-icons-react';
import { Breadcrumb } from '@fibrous/semi-ui-react';
export default function BreadcrumbDemo() {
// Several breadcrumbs on one page are told apart by aria-label
return (
<div>
<Breadcrumb routes={['Semi-ui', 'Breadcrumb', 'Default']} aria-label="字符串路由" />
<br />
<Breadcrumb
aria-label="带图标的路由"
routes={[
{
path: '/',
href: '/',
icon: <IconHome aria-label="首页" size="small" />,
},
{
path: '/breadcrumb',
href: '/zh-CN/navigation/breadcrumb',
name: 'breadcrumb',
icon: <IconArticle size="small" />,
},
'with icon',
]}
/>
<br />
<Breadcrumb routes={['首页', '当这个页面标题很长时需要省略', '详情页']} aria-label="长标题路由" />
</div>
);
}API 参考
Breadcrumb
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| activeIndex | 受控的当前项序号,从 0 开始计数;未设置时最后一项为当前项。 | number | - |
| aria-label | 导航的可访问名称;未设置时使用语言包中的文案。 | React.AriaAttributes['aria-label'] | - |
| autoCollapse | 超出 maxItemCount 时是否自动折叠为省略号。 | boolean | true |
| children | Breadcrumb.Item 子节点;传入非空的 routes 时不渲染 children。 | ReactNode | - |
| className | 根元素 nav 的类名。 | string | - |
| compact | 是否使用紧凑尺寸,影响文字与 Semi 图标的尺寸。 | boolean | true |
| maxItemCount | 级别数超过该值后折叠,首项、当前项与末项始终可见。 | number | 4 |
| moreType | 内置省略号区域的渲染类型,可选 default 或 popover;提供 renderMore 时以 renderMore 为准。 | MoreType | "default" |
| onClick | 单击某项时调用。routes 写法收到该项的路由对象,字符串路由为 { name };Breadcrumb.Item 写法收到 { name, href },name 为该项的子节点。第二个参数为原生 MouseEvent。传入后,没有 href、未设置 noLink 且不是当前项的项也可以用 Enter 键操作。 | Type(route: BreadcrumbItemInfo | RouteProps, event: React.MouseEvent) => void | - |
| ref | 根元素 nav 的引用。 | TypeReact.Ref<HTMLElement> | - |
| renderItem | 自定义每一项的内容,配合 routes 使用,参数为该项的路由对象;字符串路由为 { name }。 | Type(route: RouteProps) => React.ReactNode | - |
| renderMore | 自定义省略号区域的内容,参数为被折叠的项,已去掉分隔符;提供时以它为准。 | Type(restItem: Array<React.ReactNode>) => React.ReactNode | - |
| routes | 路由信息,由路由对象或字符串组成的数组;不为空时按它渲染各项,不再渲染 children。路由对象的字段见下方 Route。 | TypeArray<RouteProps | string> | [] |
| separator | 自定义分隔符,可以是文字或 React 节点。 | React.ReactNode | "/" |
| showTooltip | 标题溢出时是否展示 Tooltip 及相关配置:width 为截断宽度,数字按 px 计算;ellipsisPos 为截断位置,end 或 middle;opts 为传给 Tooltip 的属性,不含 content,未设置时为 { autoAdjustOverflow: true, position: 'top' }。传 false 时不展示 Tooltip,标题仍按 width 截断。 | boolean | showToolTipProps | { width: 150, ellipsisPos: 'end' } |
| style | 根元素 nav 的内联样式。 | React.CSSProperties | - |
id、data-* 等其他原生属性落在根元素 nav 上。
Breadcrumb.Item
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| active | 是否为当前项,由 Breadcrumb 设置,使用方不应传入。 | boolean | - |
| children | 标题内容。数字与字符串会被截断并展示 Tooltip,其他节点原样渲染。 | ReactNode | - |
| className | 包裹该项的外层 span 的类名。 | string | - |
| href | 链接的目的地,挂载在 a 标签上;当前项不渲染为链接。 | string | - |
| icon | 标题前的图标。Semi 图标未设置 size 时,按 Breadcrumb 的 compact 取 small 或 default。 | React.ReactNode | - |
| noLink | 移除 hover 和 active 样式;没有 href 的项也不再可以用键盘操作。 | boolean | - |
| onClick | 单击时调用,参数同 Breadcrumb 的 onClick:routes 写法收到该项的路由对象,children 写法收到 { name, href };第二个参数为原生 MouseEvent。 | Type(item: BreadcrumbItemInfo | RouteProps, e: React.MouseEvent) => void | - |
| ref | 包裹该项的外层 span 的引用。 | TypeReact.Ref<HTMLSpanElement> | - |
| route | Breadcrumb 按 routes 渲染时传入的该项路由对象,作为 onClick 的参数;使用方不应传入。 | RouteProps | - |
| separator | 该项之后的分隔符,覆盖 Breadcrumb 的 separator,可以是文字或 React 节点。 | React.ReactNode | - |
| shouldRenderSeparator | 是否渲染该项之后的分隔符,由 Breadcrumb 按位置与折叠状态设置,使用方不应传入;缺省为 true。 | boolean | - |
| style | 包裹该项的外层 span 的内联样式。 | CSSProperties | - |
id、data-* 等其他原生属性落在包裹该项的外层 span 上。
使用方给 Breadcrumb.Item 设置的 key 会保留,带 key 的 Item 重排后内部状态跟随 key 移动。只有 Breadcrumb.Item 子节点会收到 active、shouldRenderSeparator,其他元素与文本原样渲染。
Route
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| href | 链接目的地 | string | - |
| icon | 标签的显示图标 | ReactNode | - |
| name | 路由名 | string | - |
| path | 路由路径 | string | - |
路由还可以带 noLink、separator 与 onClick,作用与 Breadcrumb.Item 的同名属性相同。data-* 字段会传给对应的项。
Accessibility
- Breadcrumb 支持传入
aria-label来表示该 Breadcrumb 作用 - Breadcrumb 会对当前项设置
aria-current='page'
文案规范
- 每个页面链接都应该很简短,并且清楚地反映它链接到的位置或链接的实体
- 按句子大小写书写
设计变量
| Sass 变量 | 值 | 用法 |
|---|---|---|
| $transition_duration-breadcrumb_link-text | var(--semi-transition_duration-none) | 面包屑文字-文字-动画持续时间 |
| $transition_function-breadcrumb_link-text | var(--semi-transition_function-easeIn) | 面包屑文字-文字-过渡曲线 |
| $transition_delay-breadcrumb_link-text | var(--semi-transition_delay-none) | 面包屑文字-文字-延迟时间 |
| $transform_scale-breadcrumb_link-text | var(--semi-transform_scale-none) | 面包屑文字-放大 |
| $spacing-breadcrumb_item_wrap-marginY | $spacing-extra-tight | |
| $spacing-breadcrumb_item_wrap-marginRight | $spacing-extra-tight | |
| $spacing-breadcrumb_item-marginRight | $spacing-extra-tight | |
| $spacing-breadcrumb_item_text-marginLeft | $spacing-extra-tight | |
| $spacing-breadcrumb_restItem-marginRight | $spacing-tight | |
| $color-breadcrumb_default-text-default | var(--semi-color-text-2) | |
| $color-breadcrumb_default-text-hover | var(--semi-color-link) | |
| $color-breadcrumb_default-text-active | var(--semi-color-link-hover) | |
| $color-breadcrumb_active-text-default | var(--semi-color-text-0) | |
| $color-breadcrumb_active-text-active | var(--semi-color-text-0) | |
| $color-breadcrumb_sepearator_default-icon-default | var(--semi-color-text-2) | |
| $color-breadcrumb-restItem-text-default | var(--semi-color-text-2) | |
| $font-breadcrumb_default-fontWeight | $font-weight-regular | |
| $font-breadcrumb_active-fontWeight | $font-weight-bold | |
| $font-breadcrumb_compact-fontSize | $font-size-small | |
| $font-breadcrumb_loose-fontSize | $font-size-regular |