跳到主要内容
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
开始使用WebReactSwiftUIJetpack ComposeFlutterReact Native预设你自己的设计系统与 AI 代理一起使用 Tanrei品牌设计令牌设计系统与定制Theme Studio颜色字体排印图标形状层级动效交互状态行为布局无障碍文字颜色令牌字阶令牌形状令牌层级令牌动效令牌状态令牌间距与度量令牌组件按钮主操作按钮分段按钮按钮组带菜单的按钮工具栏复制按钮复选框单选按钮开关纸片(Chip)菜单滑块滑块字段日历DateTimePicker字段组单选组复选框组下拉选择框下拉选择字段菜单栏文件上传文件选择器 进阶放置区文本输入框 进阶文本字段纸片字段字段组合框 进阶组合框字段数字输入框 进阶数字字段颜色输入框 进阶颜色字段一次性验证码输入框 进阶一次性验证码字段嵌入式文本输入框 进阶聊天输入栏卡片分隔线模态层 进阶对话框列表列表行底部面板侧边面板轮播代码块表格弹出框步骤折叠面板描述列表图示应用外壳页头树视图时间线图片预览调整手柄可调整大小的框滚动区域徽标进度指示器计量条数字滚动器加载指示器消息条(Snackbar)工具提示键盘快捷键标签(Tag)行内代码提示块(Callout)头像空状态标签组(Tag group)骨架屏文件项色块跑马灯文本标签页标签页视图应用栏导航栏导航抽屉搜索链接分页上一页/下一页链接步骤条面包屑目录链接卡片FAB 菜单状态Tanrei 是如何构建的参与贡献许可与致谢
首页组件面包屑

面包屑

页面在页面层级结构中的位置,以及沿层级往回走的路。上面的各级是链接,从顶层起依次排列,页面本身排在最后。

content_copy以 Markdown 格式查看
类别
导航
令牌
comp.breadcrumbs
层级
基础

概览

Web
tanrei-breadcrumbs
schedule
SwiftUI
TanreiBreadcrumbs
radio_button_unchecked
Jetpack Compose
TanreiBreadcrumbs
radio_button_unchecked
Flutter
TanreiBreadcrumbs
radio_button_unchecked
React Native
Breadcrumbs
radio_button_unchecked

生成自 docs/status/status.json, specs/breadcrumbs.spec.json

三个层级的面包屑

首页组件面包屑

面包屑显示的是页面在层级结构中的位置,而不是用户来到这里所走的路。在页面位于其他页面之内、深度达到三级或更多的地方使用它。

用法

在 Web 上,面包屑是包在你自己的锚元素外面的一个元素。锚元素留在文档里,所以在任何脚本运行之前它们就已经是链接,爬虫、处理页面上锚元素的路由以及路由自带的链接组件都能找到它们。

有目的地的层级是 <a href>。没有目的地的层级是 <span>:当前页面,或者没有自己页面的层级。

SwiftUI、Compose、Flutter 和 React Native 尚在计划中:本页开头各平台旁边的名称是规格为它们定下的,这些平台目前还没有提供任何实现。

<link rel="stylesheet" href="@tanrei/web/tokens.css" />
<link rel="stylesheet" href="@tanrei/web/icons.css" />
<link rel="stylesheet" href="@tanrei/web/breadcrumbs.css" />

<tanrei-breadcrumbs label="面包屑" overflow-label="显示隐藏的层级">
  <a href="/">首页</a>
  <a href="/components/">组件</a>
  <span aria-current="page">按钮</span>
</tanrei-breadcrumbs>

<!-- 字形放在第一个标签之前,或者单独使用。文本仍然是这一级的名称。 -->
<tanrei-breadcrumbs label="面包屑" overflow-label="显示隐藏的层级">
  <a href="/" data-icon="home" data-icon-only>首页</a>
  <a href="/components/">组件</a>
  <span aria-current="page">按钮</span>
</tanrei-breadcrumbs>

<script type="module">
  import '@tanrei/web';
</script>
import { Breadcrumbs } from '@tanrei/react';
import '@tanrei/web/breadcrumbs.css';
import { Link as RouterLink } from 'react-router-dom';

<Breadcrumbs label="面包屑" overflowLabel="显示隐藏的层级">
  {/* 路由的链接组件渲染它自己的锚元素,并从它的 click 接管导航。 */}
  <RouterLink to="/">首页</RouterLink>
  <RouterLink to="/components/">组件</RouterLink>
  <span aria-current="page">按钮</span>
</Breadcrumbs>
属性 在 Web 上
label label 属性:导航地标的名称
overflow overflow="collapse"(默认)或 overflow="wrap"
overflowLabel overflow-label:溢出按钮的名称
underline underline="always"、"hover" 或 "never"。不写时,面包屑跟随设计系统
一个层级 一个 <a href> 子元素;没有目的地的层级则是一个 <span> 子元素
层级的 label 它的文本
current 最后一个子元素上的 aria-current="page"
icon data-icon="home"
iconOnly data-icon-only
click 锚元素自己的 click

规格

没有页面的层级;作为链接的当前页面;止于父级的面包屑

只在悬停、聚焦或按下时显示的下划线;以及从不显示

首页组件面包屑首页组件面包屑

窄栏里的长面包屑:折叠的,以及换行的

首页文档基础设计令牌组件令牌禁用的容器是怎样推导出来的首页文档基础设计令牌组件令牌禁用的容器是怎样推导出来的
  • 在默认系统中,通向某个地方的层级带下划线。在那里,表明某一级是链接的是下划线,而不是颜色,与句子里的链接一样。没有目的地的层级是次要文本。当前页面的字重更重,用文本颜色,从不带下划线。
  • 什么时候画下划线是一项选择。 underline="hover" 只在某一级处于悬停、键盘聚焦或按下状态时画它。underline="never" 完全不画。不写这个属性时,面包屑跟随 comp.breadcrumbs.underline.visibility,而它又跟随设计系统为所有文本链接所做的选择。只有在链接颜色与文本颜色区分得开的地方,才选择 hover 或 never。强制颜色模式下总是会画出这条线。
  • 当前页面是文本。 指向用户所在页面的链接哪里也去不了,还会给每个页面多加一个 Tab 停靠点。只有当页面的各个视图在同一个地址下切换时,才给它 href。这时它是一个外观相同的链接。如果页面的标题紧接在面包屑下方,可以不写当前页面。
  • 分隔符是组件的:相邻两级之间是 chevron_right。绝不要把分隔符写进标签里。
  • 长的面包屑会折叠中间的部分。 在 collapse 下,面包屑保持在一行里。各级从紧挨第一级的那一级开始收到溢出按钮后面,宽度要求收多少就收多少,然后才是第一级。最后一级永远不会被收走。只有当一行里只剩溢出按钮和它、却仍然放不下时,它的标签才会被截断。
  • 溢出按钮打开一个菜单,里面是被收走的各级,按面包屑中的顺序排列。有目的地的层级在那里同样是链接。菜单的行从不带下划线。
  • wrap 保留每一级,并让面包屑排成多行。任何一行都不会以分隔符开头,也没有标签会被截断。
  • 它按自己的宽度折叠,而不是按窗口的宽度;它的宽度、某个标签或文本大小改变时,它会重新决定。
  • 从右到左时,面包屑从右侧排起,分隔符指向左侧。从左到右书写的名称保持它自己的顺序。

构成

部件 说明
1 root The navigation landmark and, in it, one ordered list of the levels, from the top of the hierarchy to the page. On one line by default.
2 container The shape behind a level that is a link, and behind the overflow button. It has no fill at rest and takes no room in the layout: it is where hover, focus and press are drawn.
3 label A level's text, in the trail's text style.
4 underline The line under the label of a level that is a link, in the label's color. When it is drawn is a choice (BRC-30): at rest in the default system, where it is what says that a level leads somewhere. The current page and a level without a destination have none.
5 icon · 可选 A glyph of the system's icon set that the product names for a level (a house for the top), before the label or in its place. Decorative.
6 separator The glyph chevron_right between two neighbouring levels, drawn by the trail. Decorative; mirrored in a right-to-left layout by the icon helper.
7 overflow-button · 可选 An icon-only button showing more_horiz that stands where levels were taken out of a trail too long for its width, and opens a menu of them.
8 menu · 可选 The menu of the levels that were taken out, in the trail's order: a Tanrei menu, opened from the overflow button.
9 focus-ring The indicator shown for keyboard focus, around a link's or the overflow button's container.

属性

属性 类型 默认值 说明
label string "" The accessible name of the landmark ("Breadcrumbs"), in the product's language. Tanrei ships no words of its own. It tells this landmark from the page's other navigation, so it is required.
overflow collapse | wrap "collapse" What a trail longer than its width does. collapse: it stays on one line and its middle levels go behind the overflow button, as many as the width asks for (BRC-9). wrap: every level stays in the trail, which runs over as many lines as it needs (BRC-15).
overflowLabel string "" The accessible name of the overflow button ("Show hidden levels"), in the product's language. Required while overflow is collapse; ignored while it is wrap.
underline auto | always | hover | never "auto" When the levels that are links are underlined. always: at rest and in every state. hover: while a level is hovered, focused from the keyboard or pressed, and not at rest. never: in no state. Auto takes comp.breadcrumbs.underline.visibility, the design system's answer (always in the default system). It applies to every level of the trail.

条目

该组件重复排列的条目种类。测试样例按顺序列出条目;各平台以各自的惯用方式为每个种类命名。

item

One level of the hierarchy: a link to it, the page the person is on, or the name of a level that has no page.

属性 类型 默认值 说明
label string "" The level's name: the title of its page, as short as the product has it. It is the item's accessible name, drawn or not.
href string "" The destination: an address as the platform's links take one. With one the level is a link; without one it is text — the current page, or a level that has no page of its own (BRC-3).
current boolean false The level is the page the person is on. Only the last item may be current. It is exposed as the current page and drawn heavier, without an underline; give it no href, so that it is text and not a link to where the person already is (BRC-4).
icon string "" The name of a glyph of the system's icon set, drawn before the label ("home" for the top of the hierarchy). Empty: no glyph.
iconOnly boolean false Draws the glyph alone and keeps the label as the accessible name. Ignored while icon is empty.
事件 说明
click A level that is a link was activated by pointer, touch, Enter or assistive technology, in the trail or in the menu. It is emitted before the destination opens; a product that takes the navigation itself (a client-side router) cancels it (BRC-22).
规格 Web SwiftUI Jetpack Compose Flutter React Native
条目 a TanreiBreadcrumbsItem TanreiBreadcrumbsItem TanreiBreadcrumbsItem BreadcrumbsItem
label · 属性 textContent label label label label
href · 属性 href destination href href href
current · 属性 aria-current isCurrent current isCurrent current
icon · 属性 data-icon icon icon icon icon
iconOnly · 属性 data-icon-only iconOnly iconOnly iconOnly iconOnly
click · 事件 click action onClick onPressed onPress
备注 The product's own child of the element, in the document: an <a href> for a level with a destination, a <span> for one without. The label is its text; aria-current="page" marks the current page; data-icon="home" names a glyph and data-icon-only hides the text from sight, not from the name. A value: TanreiBreadcrumbsItem("Components", destination: url, action:); destination is an optional URL. action runs before the address opens and returns whether the link should still open it. A data class; href is nullable. onClick returns false to keep the address closed; otherwise LocalUriHandler.current opens it. A value class; href is nullable. onPressed returns false to keep the address closed; otherwise the opener the app provides opens it. An object of the items prop. onPress receives an event whose preventDefault() keeps the address closed; otherwise Linking.openURL(href).

状态

行为

以 EARS 形式写成的需求。每个平台的实现都按这些 ID 逐条测试。需求原文取自规格文件,原样以英文呈现。

ID 需求
BRC-1 THE breadcrumbs SHALL be one navigation landmark named by label that holds one ordered list of its items, in the order the product gave them — from the top of the hierarchy to the page — each a list item with its position in the list, and nothing else that assistive technology reads but the overflow button; WHILE label is empty THE breadcrumbs SHALL still render, and in debug builds report that the landmark has no accessible name. WHILE it has no item THE breadcrumbs SHALL draw nothing, take no room and expose no landmark.
BRC-2 WHILE an item's href is a destination and its current is false THE breadcrumbs SHALL draw that level as the platform's own link to it (the web's anchor element in the document itself, not in a shadow root; SwiftUI's Link; on Compose, Flutter and React Native an element with the platform's link semantics whose address is opened by the platform's opener), so that whatever the platform gives a link — on the web its context menu, opening in a new tab or window, copying and dragging its address, the address shown before it is followed, a crawler that reads it, and a link that works before any script has run — is the platform's, and not the trail's to draw or to take over; it SHALL expose the link role, named by the item's label, and SHALL draw the label in comp.breadcrumbs.label.typescale and comp.breadcrumbs.item.content.color and, WHILE its underline is shown (BRC-30), with an underline comp.breadcrumbs.underline.width thick, comp.breadcrumbs.underline.offset below the text's baseline, in the label's color of its state, under the text only and not under a glyph. In the default system the underline is shown at rest and in every state: there, in a trail as in a sentence, the underline and not the color says that a level leads somewhere.
BRC-3 WHILE an item has no destination and its current is false THE breadcrumbs SHALL draw that level as text — its label in comp.breadcrumbs.label.typescale and comp.breadcrumbs.label.color, with no underline and no container — which is not focusable, answers no hover, focus or press, has no role of its own and emits nothing: it names a level of the hierarchy that has no page. IF an item's href names a script to run rather than a place to go (the web's javascript: scheme) or cannot be read as an address by the platform THE breadcrumbs SHALL draw that level so too, and in debug builds report it.
BRC-4 WHILE the last item's current is true THE breadcrumbs SHALL expose that level as the current page (on the web aria-current with the value page; on a platform without that state, the selected state) and SHALL draw its label in comp.breadcrumbs.current.content.color, with no underline, at the emphasized weight of its text style — that style's weight plus sys.typescale.emphasis.body — so that it is told from the levels above it by more than its color. WHILE that item has no destination it SHALL be text as BRC-3 says: not focusable, without states and without an event. WHILE it has a destination it SHALL be a link as BRC-2 says that keeps this look and answers hover, focus and press with the tokens of the current part. IF current is true on an item that is not the last THE breadcrumbs SHALL draw that item as if current were false, and in debug builds report it.
BRC-5 THE breadcrumbs SHALL open a destination in the context the person is in and in no other, SHALL draw no mark for a new context and SHALL draw no state for a destination already visited: the levels of one hierarchy replace the page the person is on, and a level's colors say what it is and what state it is in.
BRC-6 THE breadcrumbs SHALL draw one separator between every two neighbouring entries of the trail — levels and the overflow button alike — and none before the first or after the last: the glyph chevron_right of the system's icon set in a box comp.breadcrumbs.separator.size large, in comp.breadcrumbs.separator.color, comp.breadcrumbs.separator.gap from the entry on either side, centred on the line of the label beside it, drawn through the platform's icon helper with sys.icon.family.unselected and sys.icon.fill.unselected, sys.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max. A separator SHALL be hidden from assistive technology, SHALL be no part of a level's name, link or hit area, and SHALL keep its color in every state of the levels beside it.
BRC-7 WHILE an item's icon names a glyph THE breadcrumbs SHALL draw it before the label in the reading direction, in a box comp.breadcrumbs.icon.size large, comp.breadcrumbs.container.gap from the label, centred on the label's line, in the color of the level's label and state, through the icon helper as BRC-6 draws a separator, hidden from assistive technology. WHILE iconOnly is also true THE breadcrumbs SHALL draw the glyph alone, with no label and no underline, its container a square one line of the trail's text high around it, and SHALL keep the item's label as its accessible name. WHILE an item's label is empty THE breadcrumbs SHALL still render it, and in debug builds report that the level has no name.
BRC-8 WHILE overflow is collapse THE breadcrumbs SHALL set the trail on one line, each label on one line, as wide as its entries need and no wider than the layout gives it, aligned to the start, and SHALL NOT wrap or scroll it.
BRC-9 WHILE overflow is collapse and the trail is wider than the width the layout gives it THE breadcrumbs SHALL take levels out of the trail and draw the overflow button once, in the place of the first level it took out: first the levels between the first and the last, beginning with the one next to the first and going on toward the last, each only if what is left still does not fit; then, if the first level, the button and the last level still do not fit, the first level as well, so that the button begins the trail. It SHALL NOT take out the last level, SHALL take out no more levels than the width asks for, and SHALL measure the trail with its separators and gaps, by the width it is given and not by the window's.
BRC-10 THE breadcrumbs SHALL draw the overflow button as the glyph more_horiz of the system's icon set in a box comp.breadcrumbs.icon.size large, in comp.breadcrumbs.overflow.content.color, drawn as BRC-6 draws a separator, in a container that is a square one line of the trail's text high with corners comp.breadcrumbs.container.shape; it SHALL be one list item of the trail holding one focusable element with the button role, named by overflowLabel, that says it opens a menu and whether that menu is open, and WHILE overflowLabel is empty SHALL still render and in debug builds report that the button has no accessible name. WHILE no level is taken out THE breadcrumbs SHALL draw no overflow button.
BRC-11 WHEN the user activates the overflow button by pointer, touch, Enter or Space THE breadcrumbs SHALL open a menu anchored to it, below it with the start edges aligned, that lists the levels taken out in the trail's order, each named by its label and showing its glyph where it has one: a level with a destination as an item that is a link to it, a level without one as a disabled item. What the menu draws, how focus enters it and moves in it, and how it closes are the menu's own (its spec's behaviours), and WHEN it closes without a level having been followed THE breadcrumbs SHALL return focus to the overflow button.
BRC-12 WHEN the width the layout gives the trail, a label, the text size or the layout direction changes THE breadcrumbs SHALL decide again which levels are taken out, at once and without a motion of its own; a level that fits again SHALL return to its place in the trail. WHEN a level that holds keyboard focus is taken out THE breadcrumbs SHALL move focus to the overflow button, and WHEN the overflow button is removed while it holds focus or its menu is open THE breadcrumbs SHALL close the menu and move focus to the first level that returned.
BRC-13 WHILE a level is taken out of the trail THE breadcrumbs SHALL keep it out of the list assistive technology reads and out of the focus order, reached through the menu alone; WHERE the platform's links are elements of a document (the web) THE breadcrumbs SHALL keep that level's link in the document, hidden, so that the whole trail is there for whatever reads the page as built and before any script has run.
BRC-14 WHILE overflow is collapse and the overflow button with the last level alone is still wider than the width the layout gives, or the trail has one level that is, THE breadcrumbs SHALL cut that level's label with an ellipsis at the end of its own direction (BRC-28), keeping the button, the separator and a glyph whole; the full label SHALL remain what assistive technology reads.
BRC-15 WHILE overflow is wrap THE breadcrumbs SHALL keep every level in the trail and draw no overflow button: it SHALL break the trail onto as many lines as it needs, comp.breadcrumbs.row-gap apart and aligned to the start, only after a separator, so that a separator ends a line and never begins one; a label longer than a line SHALL wrap where its language allows a break and, for a run with no such place, inside the run, and SHALL NOT be cut.
BRC-16 WHILE a level that is a link or the overflow button is hovered, keyboard-focused or pressed THE breadcrumbs SHALL render its container, its content — the label with its underline and glyph, or the button's glyph — and its opacity from the component tokens of its part (item, current, overflow) in the highest-precedence active state, with precedence pressed over focused over hovered; focus gained by pointer or touch SHALL NOT select the focused state. The container SHALL be the box of the content, with corners comp.breadcrumbs.container.shape, and SHALL take no room and move nothing beside it.
BRC-17 WHEN a level that is a link or the overflow button receives keyboard focus THE breadcrumbs SHALL show the focus ring around its container without animation — the system's focus indicator, sys.focus.offset from the container, sys.focus.outer-width wide in the focus-ring color, with the inner stroke of sys.focus.inner-width where the system has one — and, for a label that runs over several lines of a wrapped trail, around its part of each line; focus gained by pointer or touch SHALL NOT show it.
BRC-18 WHEN a level that is a link is pressed by pointer, touch or Enter, or the overflow button by pointer, touch, Enter or Space, THE breadcrumbs SHALL show the pressed state without delay and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner.
BRC-19 WHILE pressed THE breadcrumbs SHALL answer as sys.behavior.pressed-feedback names: overlay applies the pressed tokens to the whole container at once; ripple grows the pressed state layer from the point of contact (from the center for keyboard activation); dim applies the pressed opacity to the whole control and draws no state layer; none draws no answer to the press. Under ripple and dim only the container color stays with the state under the press; content, opacity and shape still come from the pressed tokens. Under none every part stays with the state under the press. The ripple grows over comp.breadcrumbs.motion.feedback-duration with motion.state-easing, fades over motion.state-duration with motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced.
BRC-20 THE breadcrumbs SHALL ease its container corners by sys.shape.corner-smoothing (0 is a quarter circle, 0.6 the iOS continuous corner; a platform with only the OS curve draws it for any amount above 0) and show its keyboard focus as sys.behavior.focus-style names (ring or glow); a platform that cannot draw a choice SHALL fall back to the first value and state that in its README.
BRC-21 THE breadcrumbs SHALL change a level or the overflow button between its states over comp.breadcrumbs.motion.state-duration with comp.breadcrumbs.motion.state-easing, and at once where motion is reduced.
BRC-22 WHEN the user activates a level that is a link in the trail by pointer, touch or Enter THE breadcrumbs SHALL emit that item's click exactly once and then open its href, unless the product cancelled that click, in which case it SHALL open nothing: the product's own router has taken the navigation. It SHALL NOT hold the navigation back for sys.motion.duration.press-hold. THE breadcrumbs SHALL NOT activate a link in the trail on Space, which on the web scrolls the page as it does on any link, and SHALL NOT show the pressed state for it; a level listed in the menu is the menu's link item, whose keys and activation are the menu's own (MNU-53, MNU-54: its click is emitted once and can be cancelled, the menu closes, then the destination opens, and Space activates it as it does every row of a menu); WHERE the platform gives its links other keys or gestures (on the web a modified or a middle click that opens a new tab, on Apple platforms a long press that previews) THE breadcrumbs SHALL leave them to the platform.
BRC-23 WHERE the visual size of a level that is a link or of the overflow button is below the minimum target THE breadcrumbs SHALL extend its hit area on both axes to sys.target.touch for touch input and sys.target.pointer for fine pointers, without changing its visual size or the room it takes, and on the axis of the trail no further than halfway to the entry beside it, so that no two hit areas overlap; a platform that cannot tell the input type SHALL use sys.target.touch.
BRC-24 WHERE the platform draws with a person's own forced colors (the web's forced-colors mode, and a platform's equivalent where it has one) THE breadcrumbs SHALL draw a level that is a link, with its underline and glyph, in the platform's link color, the current page, a level without a destination and the separators in its text color, the overflow button's glyph in its button text color, and the focus ring in its highlight color, and SHALL draw the underline of a level that is a link at rest, whatever underline and the tokens it follows say: the colors are then the person's, and nothing holds a link's color apart from a text level's.
BRC-25 WHILE the text size is enlarged THE breadcrumbs SHALL grow with its text — its labels, its containers and its hit areas — keeping comp.breadcrumbs.separator.gap, comp.breadcrumbs.container.gap, comp.breadcrumbs.underline.width, comp.breadcrumbs.underline.offset, comp.breadcrumbs.row-gap and its glyphs at comp.breadcrumbs.icon.size and comp.breadcrumbs.separator.size, and SHALL decide again what fits (BRC-12).
BRC-26 THE breadcrumbs SHALL take its layout direction from where it is used — the direction of the nearest ancestor that sets one, and the platform's own where none does — and SHALL have no direction setting of its own; WHEN that direction changes while the breadcrumbs is shown THE breadcrumbs SHALL draw itself for the new direction at once, without a motion of its own, keeping its focus and whether its menu is open.
BRC-27 WHERE the layout direction is right-to-left THE breadcrumbs SHALL lay the trail out from the right — the top of the hierarchy at the right and the page at the left, a level's glyph at the right of its label, the menu opening with its right edge on the button's — and SHALL draw each separator mirrored left to right, pointing to the left, the way the trail reads: the icon helper mirrors it inside its own box because the system's icon set marks chevron_right as mirrored. It SHALL draw a level's own glyph mirrored exactly when the icon set marks that glyph's name or the product forces mirroring for that use, and unmirrored when the product forbids it. THE breadcrumbs SHALL NOT mirror a glyph itself, and the reading and focus order SHALL stay from the top of the hierarchy to the page.
BRC-28 THE breadcrumbs SHALL lay out each label as text of its own direction, isolated from the text around it: it takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right name, a number with its sign or unit and a version keep their own order in a right-to-left layout and reorder nothing beside them; THE breadcrumbs SHALL still place the label by the layout direction, not by the text's own, and SHALL cut a label that does not fit (BRC-14) at the end of its own direction, so that a left-to-right label in a right-to-left layout loses its right end and never its beginning.
BRC-29 WHEN overflow names a value the breadcrumbs does not have THE breadcrumbs SHALL behave as collapse, and in debug builds report the unknown value.
BRC-30 THE breadcrumbs SHALL show the underline of every level that is a link as its underline prop names: WHILE underline is auto, as comp.breadcrumbs.underline.visibility names, which follows sys.behavior.link-underline unless a design system sets the trail apart; WHILE underline is always, hover or never, as that value names, whatever the tokens say. always draws the line at rest and in every state; hover draws none at rest and draws it WHILE the level is hovered, keyboard-focused or pressed, the line arriving and leaving with that state as BRC-16 renders it and moving no level; never draws none in any state, and hover, focus and press are still shown by the container, the label color and the focus ring. The links of the overflow menu are menu items and are never underlined. WHEN underline, or the token it follows, changes THE breadcrumbs SHALL draw the other form at once, keeping its focus and what it has collapsed; WHEN underline names a value the breadcrumbs does not define THE breadcrumbs SHALL treat it as auto and in debug builds report the unknown value. A platform that cannot draw a choice SHALL fall back to the first value, always, and state that in its README.
BRC-31 WHERE the platform has ARIA attributes (the web), WHEN the product sets an aria- attribute on the host, by the attribute or by the ARIA property that reflects it, THE breadcrumbs SHALL move it to the data-aria- attribute of the same name, so that the host is no second node with its name, description or state, and SHALL expose it on its navigation landmark (BRC-1) — an id reference by the elements it names in the host's tree or a tree around it, a description after its own. WHILE label is not empty it is the landmark's name, over a name given so; WHILE label is empty, a name given so is the landmark's name and SHALL NOT be reported as having none in debug builds. WHEN the product removes the aria- attribute or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaDescribedByElements…) to null, THE breadcrumbs SHALL take it off that element.

各平台名称对照

对等并不意味着 API 完全相同。同一份契约,由各平台以自己的惯用方式表达。

规格 Web SwiftUI Jetpack Compose Flutter React Native
组件 tanrei-breadcrumbs TanreiBreadcrumbs TanreiBreadcrumbs TanreiBreadcrumbs Breadcrumbs
label · 属性 label label contentDescription semanticLabel accessibilityLabel
overflow · 属性 overflow overflow overflow overflow overflow
overflowLabel · 属性 overflowLabel overflowLabel overflowContentDescription overflowSemanticLabel overflowAccessibilityLabel
underline · 属性 underline underline underline underline underline
备注 An element around the product's own anchors, which stay in the document (BRC-2, BRC-13): <tanrei-breadcrumbs label="Breadcrumbs" overflow-label="Show hidden levels"><a href="/">Home</a><a href="/components/">Components</a><span aria-current="page">Button</span></tanrei-breadcrumbs>. It is an element and not a class, as Link and Previous and next links are, because collapsing by width has to measure, which a stylesheet cannot do. The shadow root holds the landmark (<nav aria-label>), the ordered list with one <li> and one slot for each child (assigned by the element), the separators, and the overflow <li> with its button and a tanrei-menu whose items are links to the hidden levels; a hidden level's <li> is not displayed, and its anchor is still in the document. Before the element is defined, and with scripting off, a rule of the package's stylesheet for tanrei-breadcrumbs:not(:defined) draws the children as the wrap form — every level, separators from the icon font, links underlined — so the trail is complete and usable without script, without the landmark. overflow-label is the attribute of overflowLabel. The levels in the trail take the Link stylesheet's rules for a standalone link with this component's tokens. The menu's items are the menu's link items (MNU-53 to MNU-57). React: Breadcrumbs renders the element and its children and takes a render prop for a router's link. underline="always | hover | never" on the element; without it the trail follows --tanrei-comp-breadcrumbs-underline-visibility, read as the Link reads its own (a container style query, and data-underline-system on the document's root where the browser has none). The slotted anchors are styled by the element's ::slotted rules, so the choice needs nothing on the anchors themselves. TanreiBreadcrumbs(label:overflowLabel:overflow:items:). Levels are built on SwiftUI's Link; the trail measures itself in a custom Layout and collapses there; the menu is TanreiMenu. The container is an accessibility container named by label; the current page has the isSelected trait. Not built on this platform yet: underline, an optional value of the same enumeration the Link takes; absent is auto. TanreiBreadcrumbs(items, contentDescription, overflowContentDescription, overflow, modifier). A custom Layout (or SubcomposeLayout) measures and collapses; the menu is TanreiMenu. Compose has no navigation landmark and no link role for a clickable element: the row is a semantics group with collectionInfo, the current page is selected, and the README says what is not exposed. Not built on this platform yet: underline, an optional value of the same enumeration the Link takes; absent is auto. TanreiBreadcrumbs(items: …, semanticLabel: …, overflowSemanticLabel: …, overflow: …). A MultiChildRenderObjectWidget (or CustomMultiChildLayout) measures and collapses; the menu is TanreiMenu. Semantics(container: true, label:) around the row; each link Semantics(link: true), the current page selected. Not built on this platform yet: underline, an optional value of the same enumeration the Link takes; absent is auto. <Breadcrumbs accessibilityLabel="Breadcrumbs" overflowAccessibilityLabel="Show hidden levels" items={[…]} />. Each link is a Text with accessibilityRole="link"; the trail measures its levels with onLayout and collapses in a second pass; the menu is Menu. accessibilityState carries selected for the current page. Follows the app's direction where an ancestor's is not known. Not built on this platform yet: underline, an optional value of the same enumeration the Link takes; absent is auto.

令牌

令牌 引用 解析值(浅色)
--tanrei-comp-breadcrumbs-container-gap sys.space.space50 4px
--tanrei-comp-breadcrumbs-container-shape sys.shape.corner.extra-small 3px
--tanrei-comp-breadcrumbs-current-container-color — #000000 · 0%
--tanrei-comp-breadcrumbs-current-content-color sys.color.on-surface #1b1b1b
--tanrei-comp-breadcrumbs-current-focused-container-color — #1b1b1b · 10%
--tanrei-comp-breadcrumbs-current-focused-content-color — #1b1b1b
--tanrei-comp-breadcrumbs-current-focused-state-layer-color — #1b1b1b
--tanrei-comp-breadcrumbs-current-hovered-container-color — #1b1b1b · 8%
--tanrei-comp-breadcrumbs-current-hovered-content-color — #1b1b1b
--tanrei-comp-breadcrumbs-current-hovered-state-layer-color — #1b1b1b
--tanrei-comp-breadcrumbs-current-pressed-container-color — #1b1b1b · 10%
--tanrei-comp-breadcrumbs-current-pressed-content-color — #1b1b1b
--tanrei-comp-breadcrumbs-current-pressed-state-layer-color — #1b1b1b
--tanrei-comp-breadcrumbs-current-state-layer-color comp.breadcrumbs.current.content.color #1b1b1b
--tanrei-comp-breadcrumbs-focused-container-shape — 3px
--tanrei-comp-breadcrumbs-focused-opacity — 1
--tanrei-comp-breadcrumbs-hovered-container-shape — 3px
--tanrei-comp-breadcrumbs-hovered-opacity — 1
--tanrei-comp-breadcrumbs-icon-size sys.icon.extra-small 16px
--tanrei-comp-breadcrumbs-item-container-color — #000000 · 0%
--tanrei-comp-breadcrumbs-item-content-color sys.color.link #1b1b1b
--tanrei-comp-breadcrumbs-item-focused-container-color — #1b1b1b · 10%
--tanrei-comp-breadcrumbs-item-focused-content-color — #1b1b1b
--tanrei-comp-breadcrumbs-item-focused-state-layer-color — #1b1b1b
--tanrei-comp-breadcrumbs-item-hovered-container-color — #1b1b1b · 8%
--tanrei-comp-breadcrumbs-item-hovered-content-color — #1b1b1b
--tanrei-comp-breadcrumbs-item-hovered-state-layer-color — #1b1b1b
--tanrei-comp-breadcrumbs-item-pressed-container-color — #1b1b1b · 10%
--tanrei-comp-breadcrumbs-item-pressed-content-color — #1b1b1b
--tanrei-comp-breadcrumbs-item-pressed-state-layer-color — #1b1b1b
--tanrei-comp-breadcrumbs-item-state-layer-color comp.breadcrumbs.item.content.color #1b1b1b
--tanrei-comp-breadcrumbs-label-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-breadcrumbs-motion-feedback-duration sys.motion.role.feedback 450ms
--tanrei-comp-breadcrumbs-motion-state-duration sys.motion.role.state.compact 200ms
--tanrei-comp-breadcrumbs-motion-state-easing sys.motion.easing.state cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-breadcrumbs-overflow-container-color — #000000 · 0%
--tanrei-comp-breadcrumbs-overflow-content-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-breadcrumbs-overflow-focused-container-color — #4b4b4b · 10%
--tanrei-comp-breadcrumbs-overflow-focused-content-color — #4b4b4b
--tanrei-comp-breadcrumbs-overflow-focused-state-layer-color — #4b4b4b
--tanrei-comp-breadcrumbs-overflow-hovered-container-color — #4b4b4b · 8%
--tanrei-comp-breadcrumbs-overflow-hovered-content-color — #4b4b4b
--tanrei-comp-breadcrumbs-overflow-hovered-state-layer-color — #4b4b4b
--tanrei-comp-breadcrumbs-overflow-pressed-container-color — #4b4b4b · 10%
--tanrei-comp-breadcrumbs-overflow-pressed-content-color — #4b4b4b
--tanrei-comp-breadcrumbs-overflow-pressed-state-layer-color — #4b4b4b
--tanrei-comp-breadcrumbs-overflow-state-layer-color comp.breadcrumbs.overflow.content.color #4b4b4b
--tanrei-comp-breadcrumbs-pressed-container-shape — 3px
--tanrei-comp-breadcrumbs-pressed-opacity — 1
--tanrei-comp-breadcrumbs-row-gap sys.space.space50 4px
--tanrei-comp-breadcrumbs-separator-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-breadcrumbs-separator-gap sys.space.space50 4px
--tanrei-comp-breadcrumbs-separator-size sys.icon.extra-small 16px
--tanrei-comp-breadcrumbs-underline-offset sys.space.space25 2px
--tanrei-comp-breadcrumbs-underline-visibility sys.behavior.link-underline 0
--tanrei-comp-breadcrumbs-underline-width sys.border.hairline 1px
--tanrei-comp-breadcrumbs-label-typescale sys.typescale.body 400 14px/1.5714

测试样例

作为基准的渲染结果。所有平台都以相同的 ID 为每个样例截取快照,以便相互比较。

生成自 specs/breadcrumbs.spec.json, tokens/comp/breadcrumbs.tokens.json, design/tokens/

Web 上绘制方式的不同之处

  • 在元素定义之前,以及禁用脚本时,样式表画出的是换行的形态:每一级,连同它们的分隔符。宽度放得下的面包屑在元素定义时不会发生位移。地标、列表和折叠则随元素一起到来。
  • 在菜单里选择一个层级,就是在你自己的锚元素上的一次 click,随后浏览器跟随这个锚元素,除非你取消了这次 click。路由的链接组件在那里接管导航的方式,与在面包屑里完全一样。
  • 换行的标签是一个框:焦点环画在这个框的周围,而不是画在它在每一行上的那一部分周围。
  • 带字形的层级按布局的方向排列,所以在从右到左的面包屑中,带字形的从左到右的标签不会采用它自己的方向。
  • 层级的字形和样式表画出的分隔符需要 icons.css。没有它时,它们的位置会留着,里面什么也不画。
  • 请把面包屑放在 .tanrei-prose 之外,或者给它标上 tanrei-not-prose:长文排版会把自己的锚元素画成文本链接。

指南

推荐

  • 把面包屑放在页面标题的上方,每个页面一个。
  • 从层级结构的顶层到当前页面依次列出各级,使用页面自己的名称。
  • 没有自己页面的层级,让它保持为文本。

避免

  • 不要用面包屑来显示用户走过的步骤。它显示的是页面在哪里。
  • 除了最后一级之外,不要把任何一级标记为当前页面。
  • 不要在新标签页中打开某一级。同一个层级结构里的各级,替换的是用户所在的页面。
  • 不要手工隐藏层级。在每一级都必须始终显示的地方,请使用 overflow="wrap"。

无障碍

角色
navigation
标注
The landmark is named by label, which is required. Each level is named by its label, drawn or not (iconOnly); its glyph is decorative. The current page carries the current state; nothing is added to its name. The overflow button is named by overflowLabel, which is required while overflow is collapse, and says that it opens a menu. Separators are hidden from assistive technology.
最小目标
即使外观尺寸更小,点击区域也满足最小目标尺寸。 minimum 32px · pointer 44px · spacing 8px · touch 48px

键盘操作

按键 动作
Tab Moves focus through the levels that are links and the overflow button, in the trail's order: each is a tab stop, as the links of a navigation region are. Text levels and levels behind the button are passed.
Enter Follows the focused link; on the overflow button, opens the menu. Space does what it does on any link (on the web it scrolls the page).
Space On the overflow button, opens the menu.
Arrow keys, Home, End, Escape In the open menu, as the menu's spec says: move among the hidden levels; Escape closes it and returns focus to the button.

备注

  • The current page is text by default, not a link. A link to the page a person is on leads nowhere, and adds a tab stop to every page of a product; as text it is still read in its place in the list, with the current state. A product that needs it to be a link (a page whose views change under one address) gives the item a destination, and it is then a link with the same look (BRC-4). A product whose page heading stands right under the trail may leave the current page out: the trail then ends at the parent, and no item is current.
  • In the default system a level that is a link is underlined, and the current page and a level without a page are not. That difference, with the heavier weight of the current page, is what tells them apart; color is not asked to (WCAG 1.4.1). The link color there is the primary's, which no scheme holds apart from the text color, so it could not.
  • A design system or a product may choose hover or never for the trail (BRC-30). A level that is a link is then told from a level that is text by its color, so the build holds the link color 3:1 apart from comp.breadcrumbs.label.color in every scheme where the choice is not always (an error in the default system, a warning in a product's layer). A trail whose every level above the current page is a link has no text level to be confused with, and the current page stays heavier; the check holds all the same, because one level without a page is enough. Forced colors draw the underline whatever was chosen (BRC-24).
  • The trail is a list of links in a landmark, not a toolbar: every link is a tab stop, and the arrow keys do nothing outside the menu.
  • Collapsing hides nothing from a person: every level taken out is in the menu, one press away, and the button says that it opens a menu. A trail that should never hide a level sets overflow to wrap. On the web the hidden levels' anchors stay in the document (BRC-13).
  • The last label is cut only when the button and it alone do not fit (BRC-14). The current page is usually the heading right under the trail, so the cut text is on the page in full; a product where it is not uses wrap.
  • The target. A level is a link that stands by itself, so its hit area is extended to sys.target without changing what is drawn (BRC-23), bounded halfway to its neighbours. Short labels beside each other keep the spacing WCAG 2.5.8 asks: a separator with its two gaps is 24 wide under the default system.
  • Text must remain readable at 200% text size: the trail grows with its text and collapses or wraps by the width it has; nothing has a fixed height (BRC-25).
  • Contrast in the default system: sys.color.link, on-surface and on-surface-variant are each held to 4.5:1 (7:1 in the high-contrast schemes) on every surface by the token invariants; the overflow glyph and the separators are on-surface-variant. The focus ring is held to 3:1 against every surface.
  • How a state looks is a value decision of the active design system (a state-layer mix in Tanrei, a dim or no hover at all elsewhere). The trail reads the state's tokens and never computes the effect itself.
  • A trail shows where a page is in the hierarchy, not the way a person came. A product that publishes the same hierarchy as structured data for search engines writes that itself, from the same items.

生成自 specs/breadcrumbs.spec.json, tokens/sys/measure.tokens.json

组件负责的部分

  • 面包屑是一个导航地标,里面是一个有序列表。每一级是一个列表项,每个链接都是浏览器自己的链接。
  • 当前页面带有你写下的 aria-current="page"。它的名称里不会添加任何东西。
  • 分隔符和字形对辅助技术隐藏。
  • 被收走的层级不会被朗读,也不在焦点顺序里。它在菜单里,按一下就能到,它的锚元素也仍在文档里。
  • 溢出按钮会说明它会打开一个菜单,以及菜单是否打开。
  • 链接的点击区域达到最小目标,而不改变画出来的样子。
  • 获得焦点的层级被收走时,焦点移到溢出按钮上。溢出按钮消失时,焦点移到重新出现的第一个层级上。

需要你做的事

  • 用 label 为这个地标命名,使用你的产品的语言。页面上还有别的导航,这个名称把它与它们区分开。Tanrei 不自带任何文字。
  • overflow 为 collapse 时,用 overflow-label 为溢出按钮命名,或者用 setWords({ breadcrumbsOverflowLabel }) 为整个产品只给一次。
  • 用 aria-current="page" 标记当前页面,并且只标在最后一级上。
  • 给只显示为一个字形的层级写上文本。文本就是它的名称。