图示
把一样供人观看的东西——图片、图表、样张或实时示例——放在它自己的展示区里,可以带外框,也可以不带;配一段说明文字说出它展示的是什么,还可以在上方加标题和你自己的控件,在下方接一个相连的块。
- 类别
- 容器
- 令牌
comp.figure- 层级
- 基础
- Web
tanrei-figureschedule - SwiftUI
TanreiFigureradio_button_unchecked - Jetpack Compose
TanreiFigureradio_button_unchecked - Flutter
TanreiFigureradio_button_unchecked - React Native
Figureradio_button_unchecked
生成自 docs/status/status.json, specs/figure.spec.json
Outlined、filled 和 plain
图示展示一样供人观看而不是阅读的东西:文章里的图片、报告里的图表、某项设置将产生的效果的预览、一份样张。它把这样东西与周围区分开,并说明它是什么。本站实时示例外面的框就是图示。
它不是卡片。卡片把关于同一个主题的内容和操作组织在一起,并且可以整体被按下。图示只展示一样东西,从不能被按下,说明文字放在外框之外。
在 Web 上,它是包在原生 <figure> 外面的 <tanrei-figure>。这个元素没有 shadow root,所以图示和它的 <figcaption> 都是文档自己的:不运行脚本时、爬虫和阅读模式都能读到它们,并且由浏览器为图示命名。其他平台尚未实现。
<link rel="stylesheet" href="@tanrei/web/figure.css" />
<tanrei-figure>
<figure>
<div data-part="frame">
<header>
<p data-part="title">各季度收入</p>
<div data-part="actions">
<tanrei-button variant="text" label="在新标签页中打开"><span slot="icon">open_in_new</span></tanrei-button>
</div>
</header>
<div data-part="stage">
<img src="revenue.svg" alt="柱状图:收入在每个季度都有增长。" />
</div>
</div>
<figcaption>每个地区都有增长,北部增长最快。</figcaption>
</figure>
</tanrei-figure>
<script type="module">
import '@tanrei/web/components/figure';
</script>import { Figure } from '@tanrei/react';
import '@tanrei/web/figure.css';
<Figure variant="plain">
<figure>
<img src={photo.src} alt={photo.alt} />
<figcaption>{photo.caption}</figcaption>
</figure>
</Figure>@tanrei/web/figure.css 在任何脚本运行之前就画出整个图示,所以满是图示的页面在脚本到达时不会发生位移。元素自己也会把同一份样式表加进页面。
| 部件 | 在 Web 上 |
|---|---|
| 外框 | <div data-part="frame">,<figure> 的第一个子元素。里面是页眉、展示区和附加块。 |
| 标题 | 外框的 <header> 里带 data-part="title" 的元素:一个 <p>,或者页面大纲所需要的标题元素。 |
| 操作 | <header> 里的 <div data-part="actions">,包住你自己的控件。 |
| 展示区 | <div data-part="stage">,包住要展示的东西。 |
| 附加块 | 展示区之后任何带 data-part="attachment" 的元素:代码块、表格、描述列表。 |
| 说明文字 | <figcaption>,写在外框之后。 |
除展示区以外,每个部件都是可选的。单独一个 <img>、<picture>、<video>、<svg> 或 <canvas> 可以代替展示区元素;完全没有外框元素的图示,也就是 Markdown 渲染器输出的 <figure><img …><figcaption>…</figcaption></figure>,同样会被绘制:这时图片就是它自己的外框。
如果 <tanrei-figure> 里没有 <figure>,元素在定义时会给它加上一个。它的子元素成为展示区,用 slot 指明部件(title、actions、caption、attachment)的子元素除外。headline 和 caption 属性会被写成标题和说明文字。
<tanrei-figure headline="变体" caption="一个 filled 按钮。">
<tanrei-button variant="filled">保存</tanrei-button>
</tanrei-figure>这种写法更短,但要等脚本运行之后才会绘制。在页面不能发生位移的地方,以及使用自己掌管元素子节点的框架(React)时,请自己写出各个部件,因为元素会移动这些子节点。
标题、控件、相连的块和说明文字
变体
<tanrei-button variant=“filled”>Filled</tanrei-button>不内缩:展示的东西一直延伸到外框的边缘
比展示区更宽:在展示区内滚动,展示区成为一个焦点停靠点
网格、点阵、向中心淡出的网格,以及棋盘格
构成
| 部件 | 说明 |
|---|---|
1 container | The frame: the shape that holds the header, the stage and the attachment, with a card's corners. Filled with the surface and edged in the outlined look, filled with a quiet tone in the filled look, and neither filled nor edged in the plain look. It carries no state: nothing about it answers a pointer, a press or focus. |
2 outline · 可选 | The outlined look's edge: one hairline inside the frame. |
3 header · 可选 | The row at the top of the frame that holds the title and the actions. Drawn only where the figure has one of them. |
4 title · 可选 | A short line that names what is shown, at the start of the header. Text, never a heading by itself. |
5 actions · 可选 | The product's own controls at the end of the header (which variant, which theme, open it elsewhere). The figure lays them out and nothing else. |
6 stage | Where the thing shown stands: the product's content, padded inside the frame or reaching its edges, scaled down where it can shrink and scrolled sideways inside the stage where it cannot. |
7 pattern · 可选 | The ground pattern behind what is shown, where the product asks for one: grid lines, a dot grid, a grid that fades toward the centre, or a checkerboard, drawn across the stage's box over the frame's fill and under the content. Decoration only. |
8 attachment · 可选 | The product's block joined under the stage, inside the frame: the code an example was made from, the data of a chart, the facts about a specimen. |
9 divider · 可选 | The line between the header and the stage and between the stage and the attachment, while the separation is a divider and the look has a frame. |
10 caption · 可选 | The text below the frame that says what is shown, in secondary text on the surface the figure sits on. |
11 focus-ring · 可选 | The system's focus indicator inside the stage's edge, drawn only while the stage scrolls and has keyboard focus. |
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | "" | The title: a short line above the stage that names what is shown ("Variants", "Revenue by quarter"). Plain text, never a heading; the title slot takes the product's own content in its place. It is the figure's accessible name where it is given. |
caption | string | "" | The caption: the text below the frame that says what is shown. The caption slot takes the product's own content in its place (a caption with a link, inline code or a tag). It is the figure's accessible name where there is no title, and its description where there is one. |
label | string | "" | The accessible name of a figure that draws neither a title nor a caption, in the product's language. Never drawn. Ignored where a title or a caption is given. |
variant | outlined | filled | plain | "outlined" | How the stage is set apart. outlined: the surface inside one hairline, the default. filled: a quiet tone and no edge, where one more line would crowd the page. plain: no fill, no edge, no padding and no line, for a picture that is its own frame. A design system may add values. |
inset | boolean | true | Whether the stage is padded inside the frame. True for a specimen or a live example, which needs room around it; false for a picture, a chart or a map that should reach the frame's edges and be clipped by its corners. The plain look has no frame to be inset from and is never padded. |
separation | auto | divider | gap | "auto" | How the parts inside the frame are told apart. auto takes comp.figure.separation, which follows the system's choice. divider draws a line between the header and the stage and between the stage and the attachment, the attachment flush with the frame. gap draws no line and stands the attachment inside the frame with its own shape. The plain look has no frame and draws neither. |
pattern | none | grid | dots | grid-fade | checkerboard | "none" | The ground pattern drawn behind what is shown, across the stage. none: the plain fill, the default. grid: lines in both directions, the ground of a layout or a design canvas. dots: a dot at every crossing of that grid, a quieter ground for a drawing or a diagram. grid-fade: the grid, clear around the centre and growing toward the edges, so that a specimen at the centre stands on the plain fill and the grid frames it. checkerboard: small squares, the ground that shows where a picture is transparent. Decoration only: it says nothing to assistive technology, and the plain look and forced colors draw none. |
插槽
| 插槽 | 说明 |
|---|---|
default | What is shown, in the stage: a picture, a video, a chart, a diagram, a specimen, a live example of the product's own components. The figure does not style, crop, mirror or operate it. |
title | The product's own title content in place of the title prop: text with inline content, or a heading of the level the page's outline needs. The figure draws it in the title's style and changes neither its role nor its level. |
actions | The controls at the end of the header: the product's own icon-only Buttons, tabs, a select or links. The figure lays them out in a row and does nothing else to them. |
caption | The product's own caption content in place of the caption prop: text with links, inline code, a keyboard shortcut or a tag. |
attachment | The block joined under the stage, inside the frame: a code block, a table, a description of the specimen. It is the product's component and keeps its own styles. |
状态
行为
以 EARS 形式写成的需求。每个平台的实现都按这些 ID 逐条测试。需求原文取自规格文件,原样以英文呈现。
| ID | 需求 |
|---|---|
FIG-1 | THE figure SHALL draw, from top to bottom, a frame that holds its header where it has one (FIG-7), its stage and its attachment where it has one (FIG-11), and below the frame its caption where it has one (FIG-10); the frame SHALL have corners comp.figure.container.shape eased by sys.shape.corner-smoothing, SHALL clip what it holds to those corners, SHALL be exactly as tall as what it holds, with no height and no minimum height of its own, and SHALL draw no elevation. |
FIG-2 | WHILE variant is outlined THE figure SHALL fill its frame with comp.figure.outlined.container.color and draw an edge comp.figure.outline.width wide in comp.figure.outline.color inside the frame's size, following its corners, without changing the frame's size or the place of what it holds; WHILE variant is filled it SHALL fill the frame with comp.figure.filled.container.color and draw no edge; WHILE variant is plain it SHALL draw no fill (comp.figure.plain.container.color), no edge, no padding and no line, so that what is shown is its own frame, and SHALL still clip the stage to comp.figure.container.shape. |
FIG-3 | THE figure SHALL place the content of its default slot in the stage and draw nothing of its own there, between the frame's fill and that content or over it, but the ground pattern the product asks for (FIG-26), under the content. WHILE inset is true and variant is not plain THE stage SHALL be padded by comp.figure.stage.padding-block above and below and comp.figure.stage.padding-inline before and after; WHILE inset is false or variant is plain THE stage SHALL have no padding, so that the content reaches the frame's edges. WHILE variant is outlined or filled THE figure SHALL hand the content comp.figure.content.color as the platform's inherited foreground and SHALL place content narrower or shorter than the stage at the stage's centre; WHILE variant is plain it SHALL hand no color and SHALL place content narrower than the stage at the stage's start edge, in line with the text around the figure. Several pieces of content SHALL be stacked in the order given with no space of the figure's between them: how several specimens are arranged is the product's layout. |
FIG-4 | WHEN content that has proportions of its own and can shrink — a picture, a video, a drawing — is wider than the stage's inner width THE figure SHALL scale it down to that width with its proportions kept (PRS-15), and SHALL NOT scale any content above its own size, crop it or stretch it: an aspect ratio and how a picture fills a box are the content's own. |
FIG-5 | WHEN content that cannot shrink is wider than the stage's inner width THE stage SHALL scroll it sideways inside its own box, beginning at the start edge and with that content placed at the start edge rather than at the centre, the stage's inline padding scrolling with the content so that its last part can be brought clear of the frame's edge; the header, the attachment and the caption SHALL NOT scroll with it, the figure SHALL never be wider than its layout and SHALL never make what holds it scroll sideways, and THE stage SHALL NOT scroll up and down: it is as tall as its content. |
FIG-6 | WHILE the stage scrolls (FIG-5) THE stage SHALL be one stop in the focus order, before anything inside it that takes focus, exposed as a group that carries the figure's name (FIG-16); WHILE it has keyboard focus it SHALL draw the system's focus indicator inside its edge — sys.focus.outer-width wide in the color role focus-ring, set in from the edge by sys.focus.offset so that nothing clips it, following the frame's corners where the stage meets them, and never animated — and the left and right arrow keys, Home and End SHALL scroll it as the platform scrolls a region, the arrow keys moving the view left and right in either layout direction; focus gained by pointer or touch SHALL NOT show the indicator; WHILE the stage does not scroll it SHALL NOT be a stop in the focus order and SHALL expose no group of its own. |
FIG-7 | WHERE the figure has a title (FIG-8) or content in its actions slot THE figure SHALL draw a header at the top of the frame: one row with the title at the start and the actions at the end, comp.figure.header.gap apart, padded by comp.figure.header.padding-block above and below, by comp.figure.header.padding-inline at the start, and at the end by comp.figure.header.padding-inline-end-with-actions where it holds actions and by comp.figure.header.padding-inline where it does not; the title SHALL take the room the actions leave and wrap inside it, the actions SHALL keep their own sizes, and WHEN the actions and one word of the title no longer fit in one row THE actions SHALL move to a row of their own below the title, at the start edge, comp.figure.header.gap below it. WHERE the figure has neither THE figure SHALL draw no header, no space for one and no line under one. |
FIG-8 | THE figure SHALL draw its title — the content of the title slot where it holds any, and the title prop otherwise — in comp.figure.title.typescale and comp.figure.title.color, wrapping and never cut; the title prop SHALL be exposed as plain text and never as a heading, and content given in the title slot SHALL keep the role and the level the product gave it (a heading stays the heading it is) while it is drawn in the title's style. IF both the prop and the slot are given THE slot SHALL be drawn and the prop ignored. THE figure SHALL set the title's letter-spacing by the script of its text, as every title is set (PRS-20): no negative letter-spacing WHERE its language is Chinese, Japanese or Korean, and none WHERE its script joins its letters or stacks marks on them. |
FIG-9 | THE figure SHALL lay out the content of its actions slot in one row at the end of the header, in the order given, comp.figure.header.gap apart, each centred on the height of that row, and SHALL do nothing else to it: the controls keep their own sizes, colors, states, focus indicators, targets and names, the figure listens to none of their events, and what they change in the stage — its theme, its direction, the variant on show — is the product's own doing. |
FIG-10 | WHERE the figure has a caption — the content of the caption slot where it holds any, and the caption prop otherwise — THE figure SHALL draw it below the frame, comp.figure.caption.gap from it, at the figure's start edge, in comp.figure.caption.typescale and comp.figure.caption.color, wrapping inside the figure's inline size and never cut or limited to a number of lines; inline content the product gives in the slot (inline code, a keyboard shortcut, a tag) SHALL sit on the caption's baseline and keep its own styles, and a link in it SHALL be underlined at rest (PRS-17). IF both the prop and the slot are given THE slot SHALL be drawn and the prop ignored. THE caption SHALL be below the frame in every look and SHALL have no other place: text above the stage is the title. |
FIG-11 | WHERE the attachment slot holds content THE figure SHALL place it inside the frame, below the stage, across the frame's whole inline size, with no padding of the figure's around it, clipped by the frame's lower corners, and joined to the stage as the separation names (FIG-13); THE figure SHALL add no style to anything inside it: a block there that has a frame of its own (a code block, a table) is the product's to give in the form that suits the join. |
FIG-12 | THE figure SHALL tell the parts inside its frame apart as its separation names: WHILE separation is auto, as comp.figure.separation names, which follows sys.behavior.separation unless a design system sets it apart; WHILE separation is divider or gap, as that value names, whatever the tokens say. WHEN separation, or the token it follows, changes THE figure SHALL draw the other form at once, without animation, keeping the stage's scroll position; WHEN separation names a value the figure does not define THE figure 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, divider, and state that in its README. |
FIG-13 | WHILE the separation is divider and variant is not plain THE figure SHALL draw a line comp.figure.divider.thickness thick in comp.figure.divider.color across the frame's whole inline size between the header and the stage and between the stage and the attachment, wherever both parts of a pair are present, and SHALL place the attachment flush against that line and the frame's edges; WHILE the separation is gap and variant is not plain THE figure SHALL draw no line, SHALL leave the header's own padding as the only space between the header and the stage, and SHALL set the attachment in by comp.figure.attachment.gap from the stage above it and from the frame's inline and lower edges, where the attachment keeps the shape it has by itself. |
FIG-14 | WHILE variant is plain THE figure SHALL draw no line whatever the separation is, SHALL draw the header without inline padding so that the title begins at the figure's start edge, comp.figure.caption.gap above the stage, and SHALL place the attachment comp.figure.attachment.gap below the stage across the figure's whole inline size, where it keeps the shape it has by itself. |
FIG-15 | THE figure SHALL NOT take pointer, touch or keyboard input of its own, apart from the scrolling of FIG-5 and FIG-6, and SHALL NOT change anything it draws under a pointer, a press or focus: its frame, header, title and caption have no hovered, focused, pressed, selected or disabled state, it draws no state layer and no ripple, and it emits no event. Input over the stage, the actions and the attachment SHALL reach the content placed there, which stays as operable, as focusable and in the same focus order — the actions, then the stage's content, then the attachment's, then anything in the caption — as it would be outside a figure. |
FIG-16 | THE figure SHALL be exposed to assistive technology as a figure, or as a named group where the platform has no such role, whose name is its title where it has one, its caption where it has a caption and no title, and label otherwise; WHERE it has both a title and a caption THE caption SHALL be exposed as the figure's description and still be read as text in its place; THE figure SHALL NOT draw label. Everything in the header, the stage, the attachment and the caption SHALL stay exposed in that reading order, and THE figure SHALL neither supply nor replace the text alternative of a picture placed in the stage: that is the picture's own. IF title, caption and label are all empty THE figure SHALL be exposed without a name and in debug builds report that a figure has no name. |
FIG-17 | WHEN the title, the caption, the look, inset or the content of a slot changes THE figure SHALL draw and expose the new value at once, without a motion, keeping the stage's scroll position where the content still reaches it, and SHALL NOT announce the change by itself. |
FIG-18 | THE figure SHALL lay itself out as a block in the flow of its container: it SHALL take the whole inline size the container gives it — a page, a column of prose, a cell of the product's grid, a card, a tab's panel alike — with its start edge on the start edge of the text around it; it SHALL bring no outer space of its own (PRS-15: the space between it and its neighbours is its container's), SHALL never be wider than its container, and SHALL have no minimum width, no maximum width and no measure of its own. THE figure SHALL NOT float beside the text, stick to an edge while the content scrolls or raise itself above the page: where it stands, and how several figures are arranged side by side, is the product's layout. |
FIG-19 | WHILE the text size is enlarged THE figure SHALL grow its title and its caption with it, keep its paddings, gaps and lines, wrap, and grow in height; it SHALL cut nothing and set no fixed height, SHALL lose no content when the reader raises line height, paragraph spacing, letter spacing or word spacing, and SHALL need no sideways scrolling of what holds it at a width of 320 points with text at 200 %: the actions move below the title (FIG-7) and content that cannot shrink scrolls inside the stage (FIG-5). |
FIG-20 | 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 figure SHALL draw an edge comp.figure.outline.width wide in the platform's text color inside its frame in the outlined and the filled looks, so that a look whose fill the mode removes is still a bounded stage, and no edge in the plain look, which has none to lose; it SHALL draw the lines of FIG-13 in that text color, its title and caption in that text color, links in the platform's link color and still underlined, and the focus indicator of FIG-6 in the platform's own color for focus, and no ground pattern (FIG-26) in any look, so that nothing but the person's own background stands behind the content; what is shown in the stage is the content's own to adapt. |
FIG-21 | WHERE the layout direction is right-to-left THE figure SHALL mirror the order of its header and apply its paddings by logical start and end, so that the title is at the right and the actions are at the left; SHALL draw the caption from the right edge; SHALL begin the stage's sideways scroll (FIG-5) at the right edge; and SHALL place a plain figure's narrow content (FIG-3) at the right edge. Top and bottom SHALL NOT change. THE figure SHALL NOT mirror, reorder or realign what is shown in the stage or in the attachment: a picture is never mirrored, and the direction of a live example is its own. |
FIG-22 | THE figure 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 figure is shown THE figure SHALL draw itself for the new direction at once, without a motion of its own, keeping what it shows. A direction the product sets on the stage's content alone (a live example drawn right-to-left inside a left-to-right page) SHALL change that content and nothing of the figure's. |
FIG-23 | THE figure SHALL lay out its title and its caption as text of their own direction, each isolated from the other and from the text around the figure: each takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right name, an identifier, a number with its unit, a version and a date keep their own order in a right-to-left layout; THE figure SHALL still place each by the layout direction, not by the text's own, and SHALL wrap them, never cut them. |
FIG-24 | WHEN variant names a value that the active design system does not have THE figure SHALL render with the default variant's tokens, and in debug builds report the unknown value. |
FIG-25 | IF the default slot holds nothing THE figure SHALL draw nothing, take no space and expose nothing, and in debug builds report that a figure shows nothing: a title, a caption or an attachment alone is not a figure. IF label is not empty while a title or a caption is given THE figure SHALL ignore label. |
FIG-26 | WHILE pattern is not none and variant is not plain THE figure SHALL draw a ground pattern in comp.figure.pattern.color across the stage's whole box, over the frame's fill and under the stage's content, centred on the stage and still while the content scrolls (FIG-5): WHILE pattern is grid, lines comp.figure.pattern.line-thickness wide every comp.figure.pattern.spacing across and down; WHILE pattern is dots, dots comp.figure.pattern.dot-size across at the same spacing; WHILE pattern is grid-fade, that grid, clear from the stage's centre to comp.figure.pattern.clear-extent of the way to its edges and growing from there to full strength at its corners; WHILE pattern is checkerboard, squares of side comp.figure.pattern.checkerboard-size, alternately the frame's fill and comp.figure.pattern.color. The pattern SHALL be decoration: it SHALL take no input, be exposed to no assistive technology, be the same in either layout direction, and be covered by the content wherever the content is opaque. WHILE variant is plain THE figure SHALL draw no pattern, because the plain look has no stage to draw one on. IF pattern names a value the figure does not define THE figure SHALL draw none, and in debug builds report the unknown value. |
各平台名称对照
对等并不意味着 API 完全相同。同一份契约,由各平台以自己的惯用方式表达。
| 规格 | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| 组件 | tanrei-figure | TanreiFigure | TanreiFigure | TanreiFigure | Figure |
title · 属性 | headline | title | title | title | title |
caption · 属性 | caption | caption | caption | caption | caption |
label · 属性 | label | accessibilityLabel | contentDescription | semanticLabel | accessibilityLabel |
variant · 属性 | variant | variant | variant | variant | variant |
inset · 属性 | inset | isInset | inset | inset | inset |
separation · 属性 | separation | separation | separation | separation | separation |
pattern · 属性 | pattern | pattern | pattern | pattern | pattern |
| 备注 | Form: <tanrei-figure> is a custom element with **no shadow root**, wrapped around a native <figure> that stays in the light DOM, so that the figure and its caption are the document's own — read without script, by a crawler, by reader modes and by a screen reader as a figure with its <figcaption> (once the element is defined it names the figure by that caption itself, aria-labelledby, unless the product gave the <figure> an aria-label: one engine does not take the name from the caption): <tanrei-figure><figure><div data-part="frame"><header><p data-part="title">…</p><div data-part="actions">…</div></header><div data-part="stage">…</div><div data-part="attachment">…</div></div><figcaption>…</figcaption></figure></tanrei-figure>; every part but the stage is optional, and a lone <img>, <picture>, <video>, <svg> or <canvas> in place of the stage element is its own stage. Everything drawn comes from one stylesheet, @tanrei/web/figure.css, whose selectors start at tanrei-figure and are wrapped in :where(); it styles the page before the element is defined and without script, so a page of figures does not move when the script arrives, and the element adopts the same sheet into the root it is connected to. Props are attributes of the wrapper: variant, separation, pattern, label; inset is a boolean property that defaults to true and its attribute is the inverse flush, as the card's (an HTML boolean attribute cannot default to true). The title is the headline attribute (HTML's global title would show a tooltip over the whole figure, as on the callout); headline and caption are conveniences for a figure built by script or by the React wrapper, for which the element writes the parts above itself around its children. What the element adds once defined: aria-labelledby on the native figure naming the title where there are both a title and a caption, and aria-describedby naming the caption; aria-label from label; tabindex="0", role="group" and the same name on the stage while it scrolls sideways, removed when it does not (FIG-6); the resolved separation as a data-separation attribute where a container style query cannot be used; and the debug reports. A native <figure> with one <figcaption> and no title needs none of that. The ground pattern (FIG-26) is the stage's own background-image, a set of CSS gradients of the --tanrei-comp-figure-pattern-* tokens over a background-color of the look's fill, so it takes no element, no input and no place in the accessibility tree, stays in place while the stage scrolls, and stands behind a transparent lone picture too; the fading grid is the grid under a radial gradient of the fill. Under forced-colors: active the frame takes a CanvasText border in the outlined and filled looks, and the stage draws no pattern (FIG-20). Pictures take max-inline-size: 100% and block-size: auto (FIG-4). | TanreiFigure(title:caption:variant:isInset:separation:pattern:) { content } actions: { … } attachment: { … }, with titleContent: and captionContent: view builders for the two slots. The stage is a horizontal ScrollView only while its content is wider than it. SwiftUI has no figure trait: the view is an accessibility container (accessibilityElement(children: .contain)) whose label is the title, or the caption, or accessibilityLabel, with the caption as its hint where there is a title. The content's foreground is set with foregroundStyle in the outlined and filled looks. The ground pattern (FIG-26) is to be drawn with a Canvas behind the stage's content; not yet written. | TanreiFigure(title, caption, contentDescription, variant, inset, separation, pattern, actions = { … }, attachment = { … }) { content }, with titleContent and captionContent lambdas for the two slots. No clickable. The stage takes horizontalScroll only while its content is wider than it. A traversal group (semantics { isTraversalGroup = true }) with the name as its content description; Compose has no figure role. The content color is provided through LocalContentColor in the outlined and filled looks. The ground pattern (FIG-26) is to be drawn with Modifier.drawBehind on the stage; not yet written. | TanreiFigure(title:, caption:, semanticLabel:, variant:, inset:, separation:, pattern:, actions:, attachment:, child:), with titleWidget: and captionWidget: for the two slots. One Semantics(container: true, label:) around the parts, which stay in the tree. The stage is a horizontal SingleChildScrollView only while its child is wider than it. The content's default text and icon styles are set in the outlined and filled looks. The ground pattern (FIG-26) is to be a CustomPaint painter behind the stage's child; not yet written. | <Figure title="Variants" caption="…" actions={…} attachment={…}>…</Figure>; title and caption take a string or a node (the two slots). A View that is not itself accessible, so its children stay reachable, with accessibilityLabel on a wrapping group where the platform exposes one. The stage is a horizontal ScrollView only while its content is wider than it. Follows the app's direction where an ancestor's is not known. The content color is given through Tanrei's text context in the outlined and filled looks. pattern takes the same five values; the ground pattern (FIG-26) is to be drawn with an SVG pattern behind the stage's content; not yet written. |
令牌
| 令牌 | 引用 | 解析值(浅色) |
|---|---|---|
--tanrei-comp-figure-attachment-gap | sys.space.space100 | 8px |
--tanrei-comp-figure-caption-color | sys.color.on-surface-variant | |
--tanrei-comp-figure-caption-gap | sys.space.space100 | 8px |
--tanrei-comp-figure-container-shape | sys.shape.corner.medium | 8px |
--tanrei-comp-figure-content-color | sys.color.on-surface | |
--tanrei-comp-figure-divider-color | sys.color.outline-variant | |
--tanrei-comp-figure-divider-thickness | sys.border.hairline | 1px |
--tanrei-comp-figure-filled-container-color | sys.color.surface-container | |
--tanrei-comp-figure-header-gap | sys.space.space100 | 8px |
--tanrei-comp-figure-header-padding-block | sys.space.space100 | 8px |
--tanrei-comp-figure-header-padding-inline | sys.space.space200 | 16px |
--tanrei-comp-figure-header-padding-inline-end-with-actions | sys.space.space100 | 8px |
--tanrei-comp-figure-outline-color | sys.color.outline-variant | |
--tanrei-comp-figure-outline-width | sys.border.hairline | 1px |
--tanrei-comp-figure-outlined-container-color | sys.color.surface | |
--tanrei-comp-figure-pattern-checkerboard-size | sys.space.space100 | 8px |
--tanrei-comp-figure-pattern-clear-extent | — | 0.3 |
--tanrei-comp-figure-pattern-color | sys.color.surface-container-highest | |
--tanrei-comp-figure-pattern-dot-size | — | 3px |
--tanrei-comp-figure-pattern-line-thickness | sys.border.hairline | 1px |
--tanrei-comp-figure-pattern-spacing | sys.space.space300 | 24px |
--tanrei-comp-figure-plain-container-color | — | |
--tanrei-comp-figure-separation | sys.behavior.separation | 0 |
--tanrei-comp-figure-stage-padding-block | sys.space.space400 | 32px |
--tanrei-comp-figure-stage-padding-inline | sys.space.space300 | 24px |
--tanrei-comp-figure-title-color | sys.color.on-surface | |
--tanrei-comp-figure-caption-typescale | sys.typescale.body-small | 400 13px/1.5385 |
--tanrei-comp-figure-title-typescale | sys.typescale.heading-6 | 500 14px/1.4286 |
测试样例
作为基准的渲染结果。所有平台都以相同的 ID 为每个样例截取快照,以便相互比较。
variant: outlined (27)
outlined
label: A specimen caption
caption: The medium corner, on a card. title
title: Variants title-caption
title: Revenue by quarter caption: Every region grew; the north grew fastes… title-slot
slots: title caption-slot
slots: caption actions
title: Variants slots: actions actions-only
label: A specimen slots: actions flush
caption: The harbour at low tide. inset: false title-flush
title: Harbour caption: The harbour at low tide. inset: false attachment
title: Variants slots: attachment separation-divider
title: Variants caption: A filled button and its markup. separation: divider slots: actions, attachment separation-gap
title: Variants caption: A filled button and its markup. separation: gap slots: actions, attachment long-caption
caption: Measured on the default system at standa… long-title-actions
title: Every variant of the button at each of i… slots: actions actions-rtl
title: الأشكال caption: زرّ ممتلئ وزرّ محدَّد. direction: rtl slots: actions ltr-title-rtl
title: tanrei-button v0.1 caption: comp.button.container.height.medium: 40p… direction: rtl attachment-rtl
title: الأشكال separation: divider direction: rtl slots: attachment pattern-grid
label: A specimen pattern: grid pattern-dots
label: A specimen pattern: dots pattern-grid-fade
label: A specimen pattern: grid-fade pattern-checkerboard
label: A specimen pattern: checkerboard title-pattern-grid-fade
title: Variants caption: A filled button and its markup. pattern: grid-fade slots: actions, attachment pattern-dots-rtl
title: الأشكال pattern: dots direction: rtl docs-demo
title: Variants, sizes and disabled pattern: grid-fade slots: actions docs-demo-code
title: Variants separation: divider pattern: grid-fade slots: actions, attachment docs-demo-system
title: Single choice, with glyphs, glyphs alone caption: Drawn under m3-like, a system that ships… pattern: grid-fade variant: filled (8)
filled
label: A specimen variant: filled filled-caption
caption: The medium corner, on a card. variant: filled filled-title-caption
title: Revenue by quarter caption: Every region grew; the north grew fastes… variant: filled filled-flush
caption: The harbour at low tide. variant: filled inset: false filled-attachment
caption: A filled button and its markup. variant: filled slots: attachment filled-separation-gap
title: Variants variant: filled separation: gap slots: attachment filled-pattern-grid
label: A specimen variant: filled pattern: grid filled-pattern-dots
label: A specimen variant: filled pattern: dots variant: plain (7)
plain
label: A specimen variant: plain plain-caption
caption: The medium corner, on a card. variant: plain plain-title-attachment
title: Variants caption: A filled button and its markup. variant: plain slots: attachment plain-caption-rtl
caption: الميناء عند الجزر. variant: plain direction: rtl plain-pattern-grid
caption: The plain look draws no pattern. variant: plain pattern: grid docs-specimen
caption: medium · 8px variant: plain docs-picture
caption: The review gallery, with one component's… variant: plain 生成自 specs/figure.spec.json, tokens/comp/figure.tokens.json, design/tokens/
variant |
绘制什么 | 用于 |
|---|---|---|
outlined(默认) |
一道细线围住的表面。 | 样张、实时示例、示意图。 |
filled |
一层柔和的色调,没有边线。 | 线条已经很多的页面;带阴影的东西的底面。 |
plain |
没有填充,没有边线,没有内边距,没有线。 | 自身就是外框的图片;网格里的样张。 |
outlined 外观用表面颜色填充,而不是留空。无论图示放在什么面板里,你自己的组件都保有它们的令牌所保证的对比度。
title(在 Web 上是headline属性)是外框内页眉里的一行短文字。它说出展示的是什么。caption位于外框下方,靠起始边,用次要文本的样式。它会换行,绝不截断。- 没有位置设置。展示区上方的文字就是标题。说明文字只有一个位置。
- 标题是纯文本,不是标题元素。如果页面大纲在那里需要一个标题元素,就写一个带
data-part="title"的标题元素:图示按标题的样式绘制它,并保留它的角色和级别。
- 操作是你自己的控件,位于页眉的末尾:选哪个变体、哪个主题,或者在别处打开。图示把它们排成一行,除此之外什么都不做。这一行太窄时,它们会移到标题下方。
- 附加块是你自己的块,位于展示区下方、外框之内:生成示例所用的代码、图表的数据。
separation |
绘制什么 |
|---|---|
auto(默认) |
设计系统选定的方式:在默认系统中是线。 |
divider |
页眉下方和附加块上方各一道线,附加块与外框贴齐。 |
gap |
不画线。附加块位于外框之内,向内缩进 8,保有自己的形状。 |
inset(默认为 true)给展示区加上内边距:上下各 32,两侧各 24。在 Web 上,flush去掉内边距,于是图片、图表或地图一直延伸到外框的边缘,并被外框的圆角裁剪。- 图片按原有比例缩小,绝不放大。
- 无法收缩的内容在展示区内横向滚动。图示绝不会比它的容器更宽。
- 比带外框的展示区更窄的内容会居中。在 plain 外观下,它从文本的边缘开始。
- 展示区与其中的内容一样高。几个示例在里面怎样排列,是你的布局的事。
pattern |
绘制什么 | 用于 |
|---|---|---|
none(默认) |
只有外观本身的填充。 | 大多数图示;铺满展示区的图片。 |
grid |
横竖每隔 24 一条细线。 | 对照网格展示的组件或布局。 |
dots |
在该网格的每个交点上画一个点。 | 放在更安静底纹上的绘图或图解。 |
grid-fade |
中心周围留空、向四角逐渐加深的网格。 | 大展示区中央的样本。本站的实时示例就用它。 |
checkerboard |
边长 8 的方格,填充色和底纹颜色交替。 | 可能带透明部分的图片或图标。 |
- 底纹是装饰。它画在内容后面,用表面层级中一种安静的颜色,提高对比度时也不会变得更醒目。
- 内容横向滚动时它保持不动,两种书写方向下都一样。
- plain 外观没有可以绘制底纹的展示区,所以不画。强制颜色模式会去掉它。
- 不要在展示区周围自己画底纹。从这里选择一种,或者通过
comp.figure.pattern令牌改变它的样式。
- 图示占满得到的宽度,不带任何外部间距。在长文排版中,它按块来留间距,并占满长文排版的整个宽度,而它的说明文字像文本块一样受行长限制。
- 并排的几个图示是你自己的网格。图示占满它所在的格子。
- 写一段说明图示用意的说明文字:写“每个地区的收入都有增长”,而不是“图表”。
- 给图片提供它自己的替代文本。说明文字不能代替它。
- 应该效仿或应该避免的示例,在说明文字的开头用一个小号 Tag 标出来,并写上相应的词:“推荐”“避免”。
- 不要用图示把相关的内容和操作组织在一起。那是卡片。
- 不要让图示可以被按下。点了会打开别的东西的图片,应该是包住图片的链接。
- 不要用外框的颜色来表示一个示例是对还是错。图示没有语义状态。
- 角色
figure- 标注
- The figure is named by its title, or by its caption where it has no title, or by label where it draws neither. With both a title and a caption, the title is the name and the caption the description. A picture in the stage has its own text alternative, given by the product; the caption does not replace it. While the stage scrolls, it is a group with the figure's name, so that a person who reaches it by keyboard hears what scrolls.
- 最小目标
- 即使外观尺寸更小,点击区域也满足最小目标尺寸。 minimum 32px · pointer 44px · spacing 8px · touch 48px
键盘操作
| 按键 | 动作 |
|---|---|
| Tab | Moves through the product's controls in the header, then to the stage where it scrolls, then through what the stage, the attachment and the caption hold. The figure adds no stop of its own unless its stage scrolls. |
| ArrowLeft / ArrowRight / Home / End | While the scrolling stage has focus: scroll it sideways, as the platform scrolls a region. |
备注
- Not interactive: the figure itself takes no press, so it has no target to size and minimumTarget holds trivially. The controls in its actions slot and anything operable in its stage are other components, each with its own target.
- A caption is not a text alternative. The caption says what the figure is for a reader who sees it ("Revenue grew in every region"); the picture's own alternative says what the picture shows to a reader who does not. Where the caption already says everything the picture does, the product marks the picture as decorative rather than repeat the caption.
- A live example in the stage stays fully operable and is read as what it is: the figure hides nothing from assistive technology and does not turn its content into an image. A purely decorative specimen (a swatch, a shape) is the product's to hide and to describe in the caption.
- A figure with neither a title nor a caption needs label; the component reports a figure without any name in debug builds (FIG-16) and cannot tell whether a name is a good one.
- A status such as do and don't is never given by a color on the frame: the figure has no status. A product that marks a figure as an example to follow or to avoid puts a tag with its glyph and its word at the start of the caption, where it is read as part of the figure's name or description.
- The scrolling stage is a focus stop (FIG-6) so that a keyboard user can bring every part of wide content into view (WCAG 2.1.1); it is named, and it shows the system's focus indicator, which is held at 3:1 against every surface role, the two fills of this component among them.
- Contrast in the default system: the title is on-surface on surface or surface-container and the caption is on-surface-variant on the surface the figure sits on, both role pairs held at 4.5:1 by the token invariants. The outlined look's edge and the dividers are decorative: the stage is told apart by its position and its caption, not by the line.
- The ground pattern (FIG-26) is decoration (WCAG 1.1.1): it is not exposed and carries nothing the content and the caption do not. It is drawn in surface-container-highest, a surface role against which on-surface text and the focus indicator are held by the token invariants, so text standing on a line or a dot keeps its contrast; and a raised contrast level does not make it louder. Forced colors remove it (FIG-20).
- Forced colors (FIG-20): the filled look loses its fill and gains an edge in the text color. The plain look stays unframed. No look draws a ground pattern.
生成自 specs/figure.spec.json, tokens/sys/measure.tokens.json
- 原生的 figure 始终是 figure。它以标题命名;没有标题时以说明文字命名。两者都有时,标题是名称,说明文字是描述,而且说明文字仍然会在它所在的位置被读到。
label为既不画标题也不画说明文字的图示命名。它从不绘制;已经给出标题或说明文字时,它会被忽略。- 展示区横向滚动时,它是焦点顺序中的一个停靠点,排在其中的任何东西之前,同时也是一个以图示名称命名的组。方向键可以滚动它,Home 和 End 让它滚到两端。不滚动的展示区不增加停靠点。
- 焦点环画在展示区的边缘以内,所以不会被裁掉。
- 页眉、展示区、附加块和说明文字里的一切都仍然可以操作,并保持各自的焦点顺序。
- 文本放大到 200% 时,标题和说明文字会变大并换行,操作会移到标题下方。
- 在从右到左的布局中,页眉会镜像,说明文字从右侧开始。展示区里展示的东西绝不镜像。
- 在强制颜色模式下,outlined 和 filled 外观都有一道文本颜色的边线。plain 外观没有。任何外观都不画底纹。
- 没有名称的图示、展示区为空的图示,以及未知的变体、分隔方式或底纹,会在调试构建中报告。
- 给每个图示一个标题、一段说明文字或一个
label。 - 给展示区里的图片提供它自己的
alt。如果说明文字已经说出了图片表达的全部内容,就把图片标记为装饰性的(alt="")。 - 让实时示例保持可以操作。图示不会隐藏它的内容,也不会把它变成一张图片。