跳到主要内容
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.previous-next-links
层级
基础

概览

Web
tanrei-previous-next-links
schedule
SwiftUI
TanreiPreviousNextLinks
radio_button_unchecked
Jetpack Compose
TanreiPreviousNextLinks
radio_button_unchecked
Flutter
TanreiPreviousNextLinks
radio_button_unchecked
React Native
PreviousNextLinks
radio_button_unchecked

生成自 docs/status/status.json, specs/previous-next-links.spec.json

上一页和下一页

本页底部的上一页/下一页链接就是这个组件。

它用于在各页都有标题的一系列页面之间前后移动:一份指南的各章、一个系列的各篇文章、一个博客的各篇帖子。按页码为同一个列表翻页(搜索结果的各页、表格的各行)是另一个独立的组件——分页:页码说明不了它通向哪里,标题可以。

用法

在 Web 上,上一页/下一页链接是加在你自己的 nav 和锚元素上的类,而不是一个元素。锚元素就在文档里,所以在任何脚本运行之前它们就是链接,爬虫和基于页面锚元素工作的路由都能找到它们。只靠样式表就能画出整个组件。

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

<link rel="stylesheet" href="@tanrei/web/tokens.css" />
<link rel="stylesheet" href="@tanrei/web/icons.css" />
<link rel="stylesheet" href="@tanrei/web/previous-next-links.css" />

<nav class="tanrei-previous-next-links" aria-label="页面">
  <a class="tanrei-previous-next-links-item" data-direction="previous" rel="prev" href="https://example.com/guide/installation/">
    <span class="tanrei-previous-next-links-label">上一页</span>
    <span class="tanrei-previous-next-links-title">安装</span>
  </a>
  <a class="tanrei-previous-next-links-item" data-direction="next" rel="next" href="https://example.com/guide/design-tokens/">
    <span class="tanrei-previous-next-links-label">下一页</span>
    <span class="tanrei-previous-next-links-title">设计令牌</span>
  </a>
</nav>

<!-- 第一页:上一页那一项不写 href,或者干脆省略。下一页保持在原来的位置。 -->
<nav class="tanrei-previous-next-links" aria-label="页面">
  <a class="tanrei-previous-next-links-item" data-direction="previous"></a>
  <a class="tanrei-previous-next-links-item" data-direction="next" rel="next" href="https://example.com/guide/installation/">
    <span class="tanrei-previous-next-links-label">下一页</span>
    <span class="tanrei-previous-next-links-title">安装</span>
  </a>
</nav>

<script type="module">
  // 可选:涟漪和变暗的按下反馈、把“下一页”写在前面时两项顺序的调整,以及调试报告。`@tanrei/web` 也会加载它。
  import '@tanrei/web/previous-next-links';
</script>
import '@tanrei/web/previous-next-links.css';
import '@tanrei/web/previous-next-links';
import { Link as RouterLink } from 'react-router-dom';

<nav className="tanrei-previous-next-links" aria-label="页面">
  {/* 路由的链接会渲染自己的锚元素:把类加在它上面。 */}
  <RouterLink className="tanrei-previous-next-links-item" data-direction="next" rel="next" to="/guide/design-tokens/">
    <span className="tanrei-previous-next-links-label">下一页</span>
    <span className="tanrei-previous-next-links-title">设计令牌</span>
  </RouterLink>
</nav>
属性 在 Web 上
label nav 上的 aria-label
一个项 <a class="tanrei-previous-next-links-item">
direction data-direction="previous" 或 "next",同时写 rel="prev" 或 rel="next"
项的 label <span class="tanrei-previous-next-links-label">
title <span class="tanrei-previous-next-links-title">,写在标签之后
href href
click 锚元素自己的 click

规格

只有下一页时,它保持在原来的位置;只有标签的项

在窄栏中,两项上下排列

  • 一个项就是一个链接,整体可以按下,画成带轮廓的容器:那唯一的一种细线,没有填充,标题用文本颜色。它不带下划线,因为它的边线、箭头和位置已经把它与周围的文本区分开。
  • 箭头由组件提供:上一页那一项的起始边是 arrow_back,下一页那一项的末尾边是 arrow_forward。它们需要 icons.css。
  • 两列等宽。 在第一页上,起始侧的那一列是空的,下一页那一项的位置与它在其他每一页上的位置完全相同。
  • 上下排列。 当上一页/下一页链接得到的宽度小于两个项的最小宽度加上间隙(默认系统下为 496)时,两项上下排列,上一页在上,下一页在下。这由组件自身的宽度决定,而不是窗口的宽度。
  • 标题会换行,绝不截断。 同一行的两项都取较高那一项的高度。没有标题的项只显示方向,采用标题的样式。
  • 从右到左时,上一页位于右侧,箭头指向右;下一页位于左侧,箭头指向左。阅读顺序和焦点顺序仍然是先上一页,后下一页。

构成

属性

属性 类型 默认值 说明
label string "" The accessible name of the landmark ("Pages", "Chapter navigation"), 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.

条目

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

item

One neighbouring page of the sequence: a link to it, named by a direction and its title.

属性 类型 默认值 说明
direction previous | next "next" Which neighbour the item leads to. previous: the page before, placed at the start with the arrow arrow_back. next: the page after, placed at the end with the arrow arrow_forward. A pair of previous and next links holds at most one item of each.
label string "" The direction in the product's words ("Previous", "Next"; "Newer", "Older"). It is drawn above the title and begins the item's accessible name.
title string "" The title of the page the item leads to ("Installation"). Empty, the item shows its direction alone (PNL-7).
href string "" The destination: an address as the platform's links take one. Empty, there is no page on that side and the item is not drawn (PNL-3), so a product can always give both items and leave one without a destination on the first and the last page.
事件 说明
click The item was activated by pointer, touch, Enter or assistive technology. It is emitted before the destination opens; a product that takes the navigation itself (a client-side router) cancels it (PNL-14).
规格 Web SwiftUI Jetpack Compose Flutter React Native
条目 tanrei-previous-next-links-item TanreiPreviousNextLinksItem TanreiPreviousNextLinksItem TanreiPreviousNextLinksItem PreviousNextLinksItem
direction · 属性 data-direction direction direction direction direction
label · 属性 tanrei-previous-next-links-label label label label label
title · 属性 tanrei-previous-next-links-title title title title title
href · 属性 href destination href href href
click · 事件 click action onClick onPressed onPress
备注 A class on the product's own anchor. data-direction is previous or next; the anchor also carries rel="prev" or rel="next". The label and the title are two spans with their classes, in that order. TanreiPreviousNextLinksItem(.next, label: "Next", title: "Design tokens", destination: url, action:); destination is an optional URL, and nil is the empty href. 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 previous or the next prop. onPress receives an event whose preventDefault() keeps the address closed; otherwise Linking.openURL(href).

状态

行为

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

ID 需求
PNL-1 THE previous and next links SHALL be one navigation landmark named by label that holds its items in reading order — the previous item, then the next item, whatever order the product gave them in — and nothing else; WHILE label is empty THE previous and next links SHALL still render, and in debug builds report that the landmark has no accessible name.
PNL-2 WHILE an item's href is a destination THE previous and next links SHALL draw that item 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 previous and next links's to draw or to take over; it SHALL expose the link role, named by the item's label followed by its title, with the arrow hidden from assistive technology, and WHERE the platform's links can say how a destination relates to the page (the web's rel) SHALL say previous for the previous item and next for the next.
PNL-3 IF an item's href is empty or only white space THE previous and next links SHALL draw nothing for that item and expose nothing for it, because the sequence has no page on that side; IF it 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, or direction names a value the previous and next links do not have, or a second item has the direction of an earlier one, THE previous and next links SHALL likewise draw nothing for that item and in debug builds report it. WHILE no item has a destination THE previous and next links SHALL draw nothing, take no room and expose no landmark.
PNL-4 THE previous and next links SHALL lay its row out in two columns of equal width, comp.previous-next-links.gap apart, with the previous item in the column at the start and the next item in the column at the end, each as wide as its column and both as high as the taller of the two; an item that is not drawn SHALL leave its column empty, so that the next item stands at the same place and has the same width on every page of the sequence.
PNL-5 WHERE the layout gives the previous and next links less width than two times comp.previous-next-links.container.min-width plus comp.previous-next-links.gap THE previous and next links SHALL stack its items instead: each drawn item as wide as the previous and next links, the previous item above the next, comp.previous-next-links.gap between them, and no room kept for an item that is not drawn. It SHALL decide this by the width it is given, not by the window's.
PNL-6 THE previous and next links SHALL draw each item as a container with corners comp.previous-next-links.container.shape and an edge comp.previous-next-links.outline.width wide inside it, its content comp.previous-next-links.container.padding from the edge on every side: the arrow in a box comp.previous-next-links.icon.size large — arrow_back at the start edge of the previous item, arrow_forward at the end edge of the next — centred on the item's height, comp.previous-next-links.container.gap from the text, and the text filling the rest of the width, its lines aligned to the start in the previous item and to the end in the next, so that each item's text stands beside its arrow.
PNL-7 THE previous and next links SHALL set an item's label in comp.previous-next-links.label.typescale and, comp.previous-next-links.label.gap under it, its title in comp.previous-next-links.title.typescale; it SHALL wrap both where their language allows a break and, for a run with no such place that is longer than the line, inside the run, and SHALL NOT cut them, draw an ellipsis or scroll. WHILE an item's title is empty THE previous and next links SHALL draw its label alone, in the title's text style and color. WHILE an item's label is empty THE previous and next links SHALL draw its title alone and in debug builds report that the item does not say its direction in words.
PNL-8 WHILE an item is hovered, keyboard-focused or pressed THE previous and next links SHALL render its container, outline, label, title, arrow and opacity from the component tokens of the highest-precedence active state, with precedence pressed over focused over hovered (comp.previous-next-links.item.container.color, comp.previous-next-links.item.outline.color, comp.previous-next-links.item.label.color, comp.previous-next-links.item.title.color and comp.previous-next-links.item.icon.color at rest); focus gained by pointer or touch SHALL NOT select the focused state.
PNL-9 WHEN an item receives keyboard focus THE previous and next links SHALL show the focus ring around that item's 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; focus gained by pointer or touch SHALL NOT show it.
PNL-10 WHEN an item is pressed by pointer, touch or Enter THE previous and next links 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.
PNL-11 WHILE pressed THE previous and next links 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; label, title, icon, outline, 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.previous-next-links.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.
PNL-12 THE previous and next links 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.
PNL-13 THE previous and next links SHALL change an item between its states over comp.previous-next-links.motion.state-duration with comp.previous-next-links.motion.state-easing, and at once where motion is reduced.
PNL-14 WHEN the user activates an item by pointer, touch or Enter THE previous and next links SHALL emit that item's click exactly once and then open its href where the person is, 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 previous and next links SHALL NOT activate an item on Space, which on the web scrolls the page as it does on any link, and SHALL NOT show the pressed state for it; 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 previous and next links SHALL leave them to the platform.
PNL-15 WHERE the visual size of an item is below the minimum target THE previous and next links 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; a platform that cannot tell the input type SHALL use sys.target.touch.
PNL-16 THE previous and next links 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 pages of one sequence replace one another, and an item's colors say what it is and what state it is in.
PNL-17 THE previous and next links SHALL draw each arrow through the platform's icon helper, as a glyph of the system's icon set, in the icon color of its state, 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; it SHALL take no glyph from the product and SHALL draw no path of its own.
PNL-18 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 previous and next links SHALL draw each item's edge, label, title and arrow in the platform's link color, keeping the edge comp.previous-next-links.outline.width wide so that what is pressed stays bounded, and SHALL draw the focus ring in the platform's highlight color.
PNL-19 WHILE the text size is enlarged THE previous and next links SHALL grow each item with its text — both items of a row to the height of the taller — keeping comp.previous-next-links.container.padding, comp.previous-next-links.container.gap, comp.previous-next-links.label.gap, comp.previous-next-links.gap and the arrow at comp.previous-next-links.icon.size, and SHALL still stack by the width it is given (PNL-5).
PNL-20 THE previous and next links 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 previous and next links are shown THE previous and next links SHALL draw itself for the new direction at once, without a motion of its own, keeping its focus.
PNL-21 WHERE the layout direction is right-to-left THE previous and next links SHALL mirror its row and each item's content by logical start and end, so that the previous item stands at the right with its arrow at its right edge and the next item at the left with its arrow at its left edge, and SHALL draw both arrows mirrored left to right, so that the previous item's points to the right and the next item's to the left: the icon helper mirrors them inside their own boxes because the system's icon set marks arrow_back and arrow_forward as mirrored. THE previous and next links SHALL NOT mirror a glyph itself, and the reading and focus order SHALL stay previous, then next.
PNL-22 THE previous and next links SHALL lay out each label and each title 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 previous and next links SHALL still place the text and align its lines by the layout direction and the item's side (PNL-6), not by the text's own.

各平台名称对照

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

规格 Web SwiftUI Jetpack Compose Flutter React Native
组件 tanrei-previous-next-links TanreiPreviousNextLinks TanreiPreviousNextLinks TanreiPreviousNextLinks PreviousNextLinks
label · 属性 aria-label label contentDescription semanticLabel accessibilityLabel
备注 Classes on the product's own elements, as Link is: <nav class="tanrei-previous-next-links" aria-label="Pages"><a class="tanrei-previous-next-links-item" data-direction="previous" rel="prev" href="…"><span class="tanrei-previous-next-links-label">Previous</span><span class="tanrei-previous-next-links-title">Installation</span></a><a class="tanrei-previous-next-links-item" data-direction="next" rel="next" href="…">…</a></nav>, styled by a stylesheet of the package. The anchors are in the document, so they are links before any script runs and for whatever reads the page as built (PNL-2). The stylesheet alone gives the whole component: the two columns are a grid in which each item takes the column of its data-direction, whatever its place in the markup, and an anchor without href is not displayed (PNL-3); stacking is a container query on the nav (PNL-5); the arrows are the items' ::before and ::after in the icon font, mirrored under :dir(rtl); the states and the press-hold are the stylesheet's as they are Link's. The package's script, where it is loaded, adds through its one listener on the document what a stylesheet cannot: the shared press primitive (ripple and dim, PNL-11), the reordering of items given next-first so that the focus order is right, and every debug report. The web is not a custom element here, so packages/tools/src/conventions.js needs an entry for where the implementation lives, as prose has. React: PreviousNextLinks renders the same markup and takes a render prop for a router's link. TanreiPreviousNextLinks(label:previous:next:), each item optional. Each item is built on SwiftUI's Link; action runs before the address opens and returns whether the link should still open it (the environment's OpenURLAction does the opening). The container has the navigation landmark through an accessibility container with label. The row stacks with ViewThatFits measured against the proposed width. TanreiPreviousNextLinks(previous, next, contentDescription, modifier). Compose has no navigation landmark and no link role for a clickable element: the row is a semantics group named by contentDescription, and its README says what is not exposed. Stacking reads the incoming constraints (BoxWithConstraints). TanreiPreviousNextLinks(previous: …, next: …, semanticLabel: …). Semantics(container: true, label:) around the row; each item Semantics(link: true), with linkUrl where the engine has it. Stacking reads the incoming constraints (LayoutBuilder). <PreviousNextLinks accessibilityLabel="Pages" previous={{ label, title, href }} next={…} />. Each item is a Pressable with accessibilityRole="link"; the row has accessibilityRole="navigation" where the platform maps it (the web target) and is a labelled group elsewhere. Stacking reads onLayout. Follows the app's direction where an ancestor's is not known.

令牌

令牌 引用 解析值(浅色)
--tanrei-comp-previous-next-links-container-gap sys.space.space150 12px
--tanrei-comp-previous-next-links-container-min-width — 240px
--tanrei-comp-previous-next-links-container-padding sys.space.space200 16px
--tanrei-comp-previous-next-links-container-shape sys.shape.corner.medium 8px
--tanrei-comp-previous-next-links-focused-container-shape — 8px
--tanrei-comp-previous-next-links-focused-opacity — 1
--tanrei-comp-previous-next-links-gap sys.space.space200 16px
--tanrei-comp-previous-next-links-hovered-container-shape — 8px
--tanrei-comp-previous-next-links-hovered-opacity — 1
--tanrei-comp-previous-next-links-icon-size sys.icon.small 20px
--tanrei-comp-previous-next-links-item-container-color — #000000 · 0%
--tanrei-comp-previous-next-links-item-focused-container-color — #1b1b1b · 10%
--tanrei-comp-previous-next-links-item-focused-icon-color — #4b4b4b
--tanrei-comp-previous-next-links-item-focused-label-color — #4b4b4b
--tanrei-comp-previous-next-links-item-focused-outline-color — #000000 · 8%
--tanrei-comp-previous-next-links-item-focused-state-layer-color — #1b1b1b
--tanrei-comp-previous-next-links-item-focused-title-color — #1b1b1b
--tanrei-comp-previous-next-links-item-hovered-container-color — #1b1b1b · 8%
--tanrei-comp-previous-next-links-item-hovered-icon-color — #4b4b4b
--tanrei-comp-previous-next-links-item-hovered-label-color — #4b4b4b
--tanrei-comp-previous-next-links-item-hovered-outline-color — #000000 · 8%
--tanrei-comp-previous-next-links-item-hovered-state-layer-color — #1b1b1b
--tanrei-comp-previous-next-links-item-hovered-title-color — #1b1b1b
--tanrei-comp-previous-next-links-item-icon-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-previous-next-links-item-label-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-previous-next-links-item-outline-color sys.color.outline-variant #000000 · 8%
--tanrei-comp-previous-next-links-item-pressed-container-color — #1b1b1b · 10%
--tanrei-comp-previous-next-links-item-pressed-icon-color — #4b4b4b
--tanrei-comp-previous-next-links-item-pressed-label-color — #4b4b4b
--tanrei-comp-previous-next-links-item-pressed-outline-color — #000000 · 8%
--tanrei-comp-previous-next-links-item-pressed-state-layer-color — #1b1b1b
--tanrei-comp-previous-next-links-item-pressed-title-color — #1b1b1b
--tanrei-comp-previous-next-links-item-state-layer-color comp.previous-next-links.item.title.color #1b1b1b
--tanrei-comp-previous-next-links-item-title-color sys.color.on-surface #1b1b1b
--tanrei-comp-previous-next-links-label-gap sys.space.space25 2px
--tanrei-comp-previous-next-links-motion-feedback-duration sys.motion.role.feedback 450ms
--tanrei-comp-previous-next-links-motion-state-duration sys.motion.role.state.large 250ms
--tanrei-comp-previous-next-links-motion-state-easing sys.motion.easing.state cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-previous-next-links-outline-width sys.border.hairline 1px
--tanrei-comp-previous-next-links-pressed-container-shape — 8px
--tanrei-comp-previous-next-links-pressed-opacity — 1
--tanrei-comp-previous-next-links-label-typescale sys.typescale.label-small 500 12px/1.3333
--tanrei-comp-previous-next-links-title-typescale sys.typescale.body-large 400 16px/1.625

测试样例

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

生成自 specs/previous-next-links.spec.json, tokens/comp/previous-next-links.tokens.json, design/tokens/

Web 上绘制方式的不同之处

  • 上下排列的形态是由网格自己的列数画出来的,依据的是 nav 得到的宽度。其中不涉及容器查询,也不涉及媒体查询。
  • 没有这个包的脚本时,样式表会画出每一种状态,按下反馈用的是浮层;把下一页写在前面的两项会按正确的顺序绘制,但在焦点顺序中仍然是下一页在前。请把上一页那一项写在前面。
  • 在从右到左的布局中,样式表会把两个箭头都镜像。如果设计系统的图标集没有把这两个名称中的任何一个标记为需要镜像,脚本会取消镜像;没有脚本时,请在这两项上写 data-mirror="never"。
  • 请把上一页/下一页链接放在 .tanrei-prose 之外,或者放在标记了 tanrei-not-prose 的部分之内:长文排版会把它自己的锚元素画成文本链接。

指南

推荐

  • 把它们放在内容之后,每页一次。
  • 在每一页上都写出两项,没有目的地的那一项不写 href。它不会被绘制。
  • 用你的产品自己的说法来写方向:“上一页”和“下一页”,或者“较新的文章”和“较早的文章”。

避免

  • 不要把它们用于不改变地址、只改变显示内容的按钮。每一项都是链接。
  • 不要用它们按页码为列表或表格翻页:那是分页的事。
  • 不要在新标签页中打开相邻的页面。同一个序列里的页面是相互替换的。
  • 不要给这两项加上你自己的字形。

无障碍

角色
navigation
标注
The landmark is named by label, which is required: a page has other navigation, and the name tells this one apart. Each item is a link named by its label and then its title ("Next Design tokens"), both of which are drawn, so the name a person hears holds the words a person sees; the arrow is decorative. Nothing is added to the name.
最小目标
即使外观尺寸更小,点击区域也满足最小目标尺寸。 minimum 32px · pointer 44px · spacing 8px · touch 48px

键盘操作

按键 动作
Tab Moves focus to the previous item, then to the next: each drawn item is a tab stop, as the links of a navigation region are.
Enter Follows the focused item. Space does what it does on any link (on the web it scrolls the page).

备注

  • An item is a link and never a button: it has a destination, and without one it is not drawn. Paging by number — the pages of a list or a result set, with or without an address for each — is Pagination, a component of its own: these links say where they lead by its title, a page number says nothing of the sort.
  • An item is pressed as a whole, so its title is not a second link and is not underlined. A text link is underlined because nothing else tells it from the text beside it; an item is told by its edge, its arrow and its place, none of which is a color. In forced colors the edge and the text take the platform's link color (PNL-18).
  • The reading and focus order is previous, then next, in both layout directions and when the items stack; the visual order follows it (WCAG 1.3.2, 2.4.3).
  • The direction is said in words by label. The arrow repeats it for sighted people and is hidden from assistive technology; an item with an empty label is reported in debug builds.
  • The next item keeps its place when there is no previous page (PNL-4): a person who pages through a sequence finds it where it was.
  • Text must remain readable at 200% text size: titles wrap and are never cut, the items grow, and the row stacks by the width it has (PNL-5, PNL-19).
  • Contrast in the default system: the title is on-surface and the label and the arrow on-surface-variant, both held to 4.5:1 (7:1 in the high-contrast schemes) on every surface by the token invariants. The edge is outline-variant, the one hairline: it is not held to 3:1, and it does not need to be, because the label, the title and the arrow identify the item without it (WCAG 1.4.11 asks 3:1 of what is required to identify a control). 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 previous and next links read the state's tokens and never computes the effect itself.
  • A pair of previous and next links belongs after the content it pages, once per page. A product that prints its pages hides it in print.

生成自 specs/previous-next-links.spec.json, tokens/sys/measure.tokens.json

组件负责的部分

  • 每一项都是浏览器自己的链接,以它的标签加上它的标题命名(“下一页 设计令牌”),两者都会绘制出来。
  • 箭头是装饰性的,并且对辅助技术隐藏。
  • 视觉顺序与阅读顺序一致:先上一页,后下一页;两种书写方向下、两项上下排列时都是如此。
  • 键盘焦点环画在项的周围。标题会换行,项会随读者的文字大小变高。

需要你做的事

  • 用 aria-label 为这个地标命名,使用你的产品的语言。页面上还有别的导航,这个名称把它与它们区分开。Tanrei 自己不提供任何文字。
  • 在锚元素上写 rel="prev" 和 rel="next"。
  • 把上一页那一项写在下一页那一项之前。