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

概览

Web
tanrei-divider
schedule
SwiftUI
TanreiDivider
schedule
Jetpack Compose
TanreiDivider
schedule
Flutter
TanreiDivider
schedule
React Native
Divider
schedule

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

在列表和工具栏中

收件箱归档回收站
format_boldformat_italiclink

用法

Web 和 React 的示例展示的是当前的规格。SwiftUI、Compose、Flutter 和 React Native 待跟进:它们提供的仍是上一版分隔线,只能画实线,也不接受单条分隔线自己的长度或粗细。在跟上之前,这些平台的示例展示的都是上一版。

<tanrei-divider></tanrei-divider>
<tanrei-divider inset="start"></tanrei-divider>

<!-- 与文本从 72 px 处开始的列表对齐。 -->
<tanrei-divider inset="start" inset-length="72"></tanrei-divider>

<!-- 优惠券上方的撕线,以及一条较轻的章节分隔。 -->
<tanrei-divider line-style="dashed" line-cap="round"></tanrei-divider>
<tanrei-divider line-style="wavy" amplitude="4" wavelength="24"></tanrei-divider>

<!-- 只把这一条分隔线加粗:它的点、线段和波浪保持原有比例。 -->
<tanrei-divider thickness="2"></tanrei-divider>
<tanrei-divider line-style="dotted" line-cap="round" thickness="4"></tanrei-divider>

<!-- 工具栏的分组是有含义的:把分隔线作为 separator 暴露出来。 -->
<div role="toolbar" aria-label="格式" style="display: flex">
  <tanrei-button variant="text" label="粗体"><span slot="icon">format_bold</span></tanrei-button>
  <tanrei-divider orientation="vertical" decorative="false"></tanrei-divider>
  <tanrei-button variant="text" label="插入链接"><span slot="icon">link</span></tanrei-button>
</div>

<script type="module">
  import '@tanrei/web/components/divider';
</script>
import { Divider } from '@tanrei/react';

<Divider />
<Divider inset="start" insetLength={72} />
<Divider lineStyle="dashed" lineCap="round" />
<Divider lineStyle="wavy" amplitude={4} wavelength={24} />
<Divider lineStyle="dotted" lineCap="round" thickness={4} />
<Divider orientation="vertical" decorative={false} />
import Tanrei

VStack(spacing: 0) {
  inboxRow
  TanreiDivider(inset: .start)
  archiveRow
}

// 方向要明确写出,不从外层的栈推断。
HStack { formattingButtons; TanreiDivider(axis: .vertical, isDecorative: false); insertLinkButton }
import androidx.compose.foundation.gestures.Orientation
import io.github.chnotchy.tanrei.components.TanreiDivider
import io.github.chnotchy.tanrei.components.TanreiDividerInset

Column {
    InboxRow()
    TanreiDivider(inset = TanreiDividerInset.Start)
    ArchiveRow()
}

// 垂直分隔线会撑满行的高度,所以要给行一个高度。
Row(Modifier.height(IntrinsicSize.Min)) {
    FormattingButtons()
    TanreiDivider(orientation = Orientation.Vertical, decorative = false)
    InsertLinkButton()
}
import 'package:tanrei/tanrei.dart';

Column(
  children: <Widget>[
    inboxRow,
    const TanreiDivider(inset: TanreiDividerInset.start),
    archiveRow,
  ],
);

// IntrinsicHeight 让垂直分隔线取得行的高度。
IntrinsicHeight(
  child: Row(
    children: <Widget>[
      ...formattingButtons,
      const TanreiDivider(axis: Axis.vertical, excludeFromSemantics: false),
      insertLinkButton,
    ],
  ),
);
import { Divider, IconButton } from '@tanrei/react-native';

<Divider />
<Divider inset="start" />

<View style={{ flexDirection: 'row' }}>
  <IconButton accessibilityLabel="粗体" onPress={toggleBold}>format_bold</IconButton>
  <Divider orientation="vertical" decorative={false} />
  <IconButton accessibilityLabel="插入链接" onPress={insertLink}>link</IconButton>
</View>

规格

方向和缩进

线型

粗细:单条分隔线自己的粗细,较粗的图案配圆形端点

点线和虚线的两端总是一个完整的点或线段:分隔线在保证最小间隔的前提下画出尽可能多的点或线段,再把每个间隔加宽相同的量。因此无论朝哪个方向、长度是多少,两端看起来都一样。波浪线由圆弧组成,并被拉伸成整数个波,所以它起于中线、止于中线。波浪线分隔线比其他线型高:高度是振幅的两倍加上线的粗细,默认是 5,而不是 1。

点、线段和波浪的长度都是由线的粗细推导出的令牌,所以把分隔线画得更粗的设计系统会得到更大的图案,而外观不变。thickness 对单条分隔线做同样的事:凡是读取粗细的地方,它都代替令牌,点、线段和波浪则保持与它的比例。缩进不随之缩放。单条分隔线自己的属性(insetLength、thickness、dashLength、gap、amplitude、wavelength)按给定的值、以平台的单位直接使用,任何调节量都不会缩放它们。负值或非有限值,以及为 0 的 thickness、dashLength 或 wavelength,会回退到令牌的值,并会在调试构建中报告。当前线型不会画出的属性会被忽略。

构成

构成

绘制在 Web 包所绘的测试样例 horizontal 之上。
部件 说明
1 line The one line, horizontal or vertical: solid, dotted, dashed or wavy. Its thickness is the system's, or the one given for this divider. It is the whole component: there is no container, and no space around it.

属性

属性 类型 默认值 说明
orientation horizontal | vertical "horizontal" Horizontal separates stacked content and spans the container's width; vertical separates content in a row and spans its height.
inset none | start | both "none" Shortens the line to align with content: none spans the full length, start leaves the inset at the start (to line up with an inset list's text), both leaves it at both ends (a middle divider).
insetLength number null The length of the inset for this divider, in the platform's unit (CSS px, pt, dp, logical pixels); null takes comp.divider.line.inset. Used only while inset is start or both: set it to line the divider up with content whose inset differs from the rest of the product's lists.
thickness number null How thick this divider's line is, in the platform's unit (CSS px, pt, dp, logical pixels); null takes comp.divider.line.thickness. Set it where one divider of a product carries more weight than the rest (the line under a page's header, a break between two sections of a long form); a product whose every divider is heavier changes the token in its layer instead.
lineStyle solid | dotted | dashed | wavy "solid" How the line is drawn: solid, a row of dots, a row of dashes, or a wave. Most dividers are solid; the others mark a different kind of boundary in the same product (a tear line, the edge of something provisional, a light section break).
lineCap butt | round "butt" How the line's ends, and every dot's and dash's ends, are drawn: butt ends square at the length, round ends in a half-disc inside it (round dots, rounded dashes). The difference shows only on a line thicker than a hairline.
dashLength number null The length of one dash of a dashed line, in the platform's unit; null takes comp.divider.line.dash.length. Ignored by the other styles.
gap number null The least space between two dots of a dotted line or two dashes of a dashed line, in the platform's unit; null takes comp.divider.line.dot.gap or comp.divider.line.dash.gap. Ignored by solid and wavy.
amplitude number null How far a wavy line's crests lie from its midline, in the platform's unit; null takes comp.divider.line.wave.amplitude. Ignored by the other styles.
wavelength number null The length of one wave of a wavy line, a crest and a trough, in the platform's unit; null takes comp.divider.line.wave.wavelength. Ignored by the other styles.
decorative boolean true Hides the divider from assistive technology. Set it to false only when the grouping is meaningful (a toolbar's or a menu's groups): the divider is then exposed as a separator.

状态

行为

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

ID 需求
DIV-1 THE divider SHALL draw one line of comp.divider.line.thickness, or of thickness while that is not null (DIV-16), in comp.divider.line.color, in the style lineStyle names (DIV-9 to DIV-12), along the full inline size of its container when orientation is horizontal, and along the full block size of its container when orientation is vertical.
DIV-2 THE divider SHALL take exactly comp.divider.line.thickness on its cross axis, or, WHERE lineStyle is wavy, twice its amplitude (DIV-12) plus comp.divider.line.thickness, whatever its length; it SHALL add no margin or padding of its own, and the space on either side of the line belongs to the layout that places it.
DIV-3 WHERE inset is start THE divider SHALL shorten the line by insetLength, or by comp.divider.line.inset while insetLength is null, at its start (the inline-start of a horizontal divider, the top of a vertical one), and WHERE inset is both it SHALL shorten the line by that length at each end; the inset stretch SHALL draw nothing, the style of DIV-9 to DIV-12 SHALL be laid out over the stretch that remains, and where the insets leave no length the divider SHALL draw nothing.
DIV-4 WHERE the layout direction is right-to-left THE divider SHALL apply the start inset of a horizontal divider at its right end and SHALL start a horizontal wavy line at its right end, mirroring it; a vertical divider's inset and wave SHALL NOT change with the direction.
DIV-5 WHILE decorative is true THE divider SHALL be hidden from assistive technology and SHALL NOT be focusable.
DIV-6 WHILE decorative is false THE divider SHALL expose the separator role and its orientation to assistive technology, SHALL have no accessible name of its own, and SHALL NOT be focusable.
DIV-7 WHEN orientation, inset, lineStyle or lineCap names a value that the divider does not define THE divider SHALL render with the default value, and in debug builds report the unknown value.
DIV-8 THE divider SHALL draw its line at least one device pixel thick; WHERE lineStyle is solid, dotted or dashed it SHALL align the line's two edges across its axis to the device pixel grid, so that the line is never spread over two partial rows or columns of pixels, and WHERE lineStyle is wavy it SHALL draw the curve antialiased.
DIV-9 WHERE lineStyle is solid THE divider SHALL draw the line as one unbroken stroke over the whole drawn stretch.
DIV-10 WHERE lineStyle is dotted THE divider SHALL draw a row of dots, each comp.divider.line.thickness long and comp.divider.line.thickness across, separated by at least gap, or comp.divider.line.dot.gap while gap is null; it SHALL draw as many dots as fit the drawn stretch with that gap between them, the first at the stretch's start and the last at its end, and SHALL widen every gap by the same amount to make them meet those ends; WHERE only one dot fits it SHALL draw that dot at the stretch's center.
DIV-11 WHERE lineStyle is dashed THE divider SHALL draw a row of dashes, each dashLength long (comp.divider.line.dash.length while dashLength is null, and never shorter than comp.divider.line.thickness) and comp.divider.line.thickness across, separated by at least gap, or comp.divider.line.dash.gap while gap is null; it SHALL draw as many dashes as fit the drawn stretch with that gap between them, the first at the stretch's start and the last at its end, and SHALL widen every gap by the same amount to make them meet those ends; WHERE only one dash fits it SHALL draw one dash, no longer than the stretch, at the stretch's center.
DIV-12 WHERE lineStyle is wavy THE divider SHALL stroke a wave about the midline of its cross axis at comp.divider.line.thickness, made of circular arcs that each span half a wavelength and alternate from one side of the midline to the other, meeting on the midline without a corner; the wavelength is wavelength, or comp.divider.line.wave.wavelength while wavelength is null, stretched or shrunk so that a whole number of waves (at least one, the nearest number) fills the drawn stretch; each arc's crest SHALL lie amplitude, or comp.divider.line.wave.amplitude while amplitude is null, from the midline to the stroke's center, but never more than a quarter of the stretched wavelength (a half circle); the wave SHALL start and end on the midline, and its first arc SHALL rise toward the top of a horizontal divider and toward the left of a vertical one.
DIV-13 WHERE lineCap is round THE divider SHALL end the solid line, every dot, every dash and the wave in half-discs of diameter comp.divider.line.thickness that lie inside the lengths DIV-9 to DIV-12 give them, so that a dot is a disc and no rounded end reaches into an inset or past the container; the wave's rounded ends SHALL be drawn at its first and last points, laid out over the drawn stretch shortened by half comp.divider.line.thickness at each end. WHERE lineCap is butt every end SHALL be square and flush with those lengths.
DIV-14 WHEN thickness, insetLength, dashLength, gap, amplitude or wavelength is null THE divider SHALL use the token that prop names; IF one of them is not a finite number, or is negative, or thickness, dashLength or wavelength is 0, THE divider SHALL use that token instead and in debug builds report the value; a value it uses SHALL be used as given, in the platform's unit, and not scaled by any dial; a prop the current lineStyle does not draw SHALL be ignored and not reported.
DIV-15 THE divider 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 divider is shown THE divider SHALL draw itself for the new direction at once, without a motion of its own, keeping what it shows and its state.
DIV-16 WHILE thickness is not null THE divider SHALL use it wherever DIV-1, DIV-2 and DIV-10 to DIV-13 name comp.divider.line.thickness — the line's extent across its axis, the side of a dot, the width of a dash and its least length, the wave's stroke, the diameter of a round cap and the divider's own size across its axis — and SHALL scale each pattern length it takes from a token rather than from a prop (comp.divider.line.dot.gap, comp.divider.line.dash.length, comp.divider.line.dash.gap, comp.divider.line.wave.amplitude and comp.divider.line.wave.wavelength) by thickness divided by comp.divider.line.thickness, so that a thicker divider keeps the pattern's proportions, as a layer that thickens the line keeps them; a pattern length given by a prop SHALL be used as given. DIV-8 holds for it: a thickness below one device pixel is drawn one device pixel thick. The thickness changes nothing that assistive technology is told, and comp.divider.line.inset and insetLength are not scaled.

各平台名称对照

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

规格 Web SwiftUI Jetpack Compose Flutter React Native
组件 tanrei-divider TanreiDivider TanreiDivider TanreiDivider Divider
orientation · 属性 orientation axis orientation axis orientation
inset · 属性 inset inset inset inset inset
insetLength · 属性 insetLength insetLength insetLength insetLength insetLength
thickness · 属性 thickness thickness thickness thickness thickness
lineStyle · 属性 lineStyle lineStyle lineStyle lineStyle lineStyle
lineCap · 属性 lineCap lineCap cap strokeCap lineCap
dashLength · 属性 dashLength dashLength dashLength dashLength dashLength
gap · 属性 gap gap gap gap gap
amplitude · 属性 amplitude amplitude amplitude amplitude amplitude
wavelength · 属性 wavelength wavelength wavelength wavelength wavelength
decorative · 属性 decorative isDecorative decorative excludeFromSemantics decorative
备注 Not an <hr>: an hr is horizontal only and always a separator. The host takes role="separator" and aria-orientation when decorative is false (set to false by decorative="false" or the property), and aria-hidden="true" otherwise. Attributes are line-style, line-cap, inset-length, dash-length, gap, amplitude and wavelength; the lengths are numbers of CSS px. A solid line stays a border (DIV-8). A dotted or dashed line is not border-style: dotted | dashed, whose dash lengths and spacing each engine chooses and which has no round cap: it is drawn from the tokens (for example a mask repeated with mask-repeat: space over a box one gap longer than the line, which places whole dashes at both ends and widens the gaps as DIV-10 and DIV-11 say). A wavy line cannot be a border at all: it is an SVG path of arcs in the shadow root, measured on resize (DIV-12). In forced-colors mode every style is drawn in the system's text color, as the border is. SwiftUI's own Divider takes its axis from the enclosing stack; TanreiDivider(axis: .horizontal) states it (default .horizontal) so a divider looks the same wherever it is placed and its snapshot is deterministic. isDecorative: false adds the separator semantics SwiftUI's Divider does not have. Ships the previous revision (solid only). Owes DIV-1 to DIV-4, DIV-7 and DIV-8 as revised, and DIV-9 to DIV-14: lineStyle, lineCap: CGLineCap (.butt, .round) and the lengths as CGFloat?, drawn as a Path stroked with StrokeStyle(lineWidth:lineCap:dash:) (arcs with addArc). One composable with orientation: Orientation (foundation's Orientation.Horizontal / .Vertical, as Modifier.scrollable takes it) instead of Material's two composables HorizontalDivider and VerticalDivider. Ships the previous revision (solid only). Owes DIV-1 to DIV-4, DIV-7 and DIV-8 as revised, and DIV-9 to DIV-14: lineStyle, cap: StrokeCap (StrokeCap.Butt, StrokeCap.Round, as Stroke names it) and the lengths as Dp?, drawn on a Canvas with PathEffect.dashPathEffect for dots and dashes and Path.arcTo for the wave. One widget with axis: Axis instead of Flutter's Divider and VerticalDivider. inset is an enum resolved from comp.divider.line.inset, not Flutter's indent / endIndent lengths; insetLength replaces that length for one divider at both ends it applies to. excludeFromSemantics (as Image and GestureDetector name it) has the same polarity as decorative and defaults to true. Ships the previous revision (solid only). Owes DIV-1 to DIV-4, DIV-7 and DIV-8 as revised, and DIV-9 to DIV-14: lineStyle, strokeCap: StrokeCap (StrokeCap.butt, StrokeCap.round, as Paint names it) and the lengths as double?, drawn by a CustomPainter; dart:ui has no dash effect, so each dot and dash is its own segment, and the wave is Path.arcToPoint. Decorative: accessible={false} and importantForAccessibility="no-hide-descendants". Not decorative: role="separator"; how far iOS and Android announce it (neither has a native separator trait) is for the package's README to state. Ships the previous revision (solid only). Owes DIV-1 to DIV-4, DIV-7 and DIV-8 as revised, and DIV-9 to DIV-14, drawn with views only (the package takes no SVG): not borderStyle: 'dotted' | 'dashed', whose spacing is the OS's and which has no length or cap; each dot and dash is a view (a round cap is its corner radius), and the wave is the package's Arc primitive, one arc per half wave, which is why DIV-12 builds the wave from circular arcs.

令牌

令牌 引用 解析值(浅色)
--tanrei-comp-divider-line-color sys.color.outline-variant #000000 · 8%
--tanrei-comp-divider-line-dash-gap — 4px
--tanrei-comp-divider-line-dash-length — 4px
--tanrei-comp-divider-line-dot-gap — 2px
--tanrei-comp-divider-line-inset sys.space.space200 16px
--tanrei-comp-divider-line-thickness sys.border.hairline 1px
--tanrei-comp-divider-line-wave-amplitude — 2px
--tanrei-comp-divider-line-wave-wavelength — 16px

测试样例

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

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

指南

何时使用

仅靠留白无法让边界清楚的地方,才使用分隔线:密集列表的行与行之间、设置页面的各个部分之间、工具栏中各组操作之间。如果两组之间的间距或表面的变化已经表明一组在哪里结束,就不要画线。线越少的布局越容易浏览。

同一种细线

分隔线的线就是设计系统的细线:颜色是 sys.color.outline-variant,宽度是细线的宽度。在默认系统中,用户看到的其他细线也是这个颜色:outlined 按钮的边线、纸片的轮廓、菜单各组之间的线、导航栏或导航抽屉的边线、列表行下方的线。它们各自保留自己的令牌,而默认系统给它们同一个值,于是一个屏幕上只有一种线。你放置的分隔线不需要自己的颜色就能与它们一致。

组件自行分隔其部件的地方

有些组件会自行把自己的部件分开,在那里不要再加分隔线:

  • 菜单会把一个组与它旁边的内容分开。
  • 相连的按钮组和带菜单的按钮会把自己的两半分开。
  • 导航抽屉会在要求分隔线的部分(divider)之前画一条分隔线。
  • 列表的行会在自己下方画线(divider),从行内文本开始的位置画起。

同一个组件内部的部件如何区分,是整个设计系统的一项统一选择:在相接处画一条线(这是默认),或者留出一段空白间隙。组件可以通过自己的令牌偏离系统的选择,单个实例则可以通过 separation 属性偏离:菜单、按钮组、带菜单的按钮和进度指示器都有这个属性。选择间隙时,这些组件完全不画线,所以你手动加上的分隔线会成为仅剩的一条线,也就不再与周围一致。

分隔线组件本身不在这项选择之内。你放在自己内容之间的 <tanrei-divider> 始终是一条线。

如何选择缩进

缩进 用途
None 横跨整个容器的边界:各部分之间、页眉下方。
Start 行首有图标或头像的列表中,行与行之间。线从文本开始的位置画起,于是前置的那一列看起来连成一体。
Both 组内的一处分隔,不应看起来像容器的边界:中间分隔线。

只有当分隔线必须与某些内容对齐,而这些内容的缩进又与产品中其他列表不同时,才设置 insetLength。inset 在哪一侧缩进,它就作用于哪一侧;inset 为 none 时它不起作用。

如何选择线型

线型 用途
Solid 几乎所有分隔线。它是默认值。
Dashed 同一产品中另一种性质的边界:优惠券上方的撕线、暂定内容的边缘。
Dotted 比实线更轻的分隔。它只覆盖自身长度的三分之一左右,所以颜色相同时看起来更淡。
Wavy 一处章节分隔,需要让人看出它与周围的实线是不同性质的边界。它在垂直于轴线的方向上比其他线型占用更多空间。

圆形端点(lineCap="round")让每个点成为圆点、每条线段成为两端圆润的短条,并把实线或波浪线的两端变圆。圆润的端点不超出线的长度,所以缩进仍然精确。在默认的细线上,圆形端点是看不出来的:它是为有自己 thickness 的分隔线准备的,也是为把线画得更粗的设计系统准备的。

推荐

  • 分隔线周围的间距由布局提供:栈的间距、列表的 gap。分隔线自己不加任何间距,所以绝不会让间距加倍。
  • 在列表和卡片中让它保持装饰性(默认)。行本身已经说明了自己从哪里开始、到哪里结束。
  • 只有当分组对用户有含义时,才把 decorative 设为 false,例如工具栏或菜单的分组。
  • 在整个产品中,同一种边界只用一种线型,这样虚线的含义始终相同。

避免

  • 不要在每两个元素之间都画线。先用间距,间距不够的地方再用分隔线。
  • 不要把分隔线用作容器的边框或轮廓。它没有容器,也没有形状。
  • 不要为了赋予含义而把它加粗或上色。thickness 是为需要足够空间才看得清的图案准备的,或者用来让一条线与周围较粗的线一致。分隔线的颜色不受对比度要求的约束,因为它所分隔的内容必须在没有它的情况下也能被理解。
  • 不要在自行分隔部件的组件内部再加分隔线,例如菜单的各组之间或列表的行与行之间。请使用该组件自己的属性。
  • 不要在滚动框的边缘放分隔线来表示后面还有内容。滚动区域会标示这条边,只在边外还有内容时显示,并采用设计系统选定的形式。
  • 不要让线型独自承载含义。如果虚线表示“沿此处剪开”,也要用文字说明。
  • 不要靠它充当标题。两个表单之间的“— 或 —”是两条分隔线加一个标签,传达含义的是标签。

无障碍

角色
separator
标注
A divider has no accessible name. Decorative (the default), it is not in the accessibility tree; otherwise it is a separator whose orientation is exposed, and the groups on either side carry their own names.
最小目标
即使外观尺寸更小,点击区域也满足最小目标尺寸。 minimum 32px · pointer 44px · spacing 8px · touch 48px

键盘操作

按键 动作

备注

  • Not interactive: a divider has no hit area, so the minimum target holds without extending anything. It never receives focus, even when it is exposed as a separator (a focusable separator is a splitter, which is a different component).
  • The line is decorative for contrast purposes: comp.divider.line.color is not held to 3:1, because the content it separates must be understandable without it. A dotted or dashed line covers less of its length and reads fainter than a solid one in the same color; that is accepted for the same reason. In the default system the line is sys.color.outline-variant, the one hairline color every line of the system shares, between 1.19:1 and 3.83:1 against the surface roles depending on the scheme: visible, and never the only thing that tells two groups apart.
  • The line's style carries nothing to assistive technology: a dotted, dashed or wavy divider that is not decorative is the same separator as a solid one. A product that gives a style a meaning (a tear line, a provisional section) states that meaning in text.
  • Text size does not change the line: it is not text.

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

组件负责的部分

  • 为装饰性(默认)时,它在每个平台上都对辅助技术隐藏。
  • 不是装饰性时,它在 Web 上作为带方向的 separator 暴露。Apple 平台、Android 和 Flutter 没有 separator 角色:在这些平台上,它留在无障碍树中,没有名称,并尽各平台所能传达信息。
  • 它永远不可聚焦,也不接受输入,所以绝不会妨碍两侧的控件。
  • 它的线至少有一个设备像素粗。实线、点线和虚线在垂直于轴线的方向上对齐到像素网格,所以绝不会模糊;波浪线则以抗锯齿方式绘制。
  • 线型不向辅助技术传达任何信息:非装饰性的点线、虚线或波浪线分隔线,与实线是同一个 separator。
  • 在 Web 上,强制颜色模式会用系统的文本颜色重画每一种线型。

需要你做的事

  • 你赋予线型的任何含义(例如撕线),都要用文字说明。辅助技术不会传达线型,而且点线和虚线看起来比实线更淡。
  • 当分组有意义时,给每个组一个自己的名称。separator 没有名称,所以它说不出这些组是什么。
  • 不要用分隔线来承载页面的结构。那是标题和地标的事;线只能被看见。