ステッパー
プロダクトが決まった順序のステップで進めるフローの中で、いまどこにいるかを示します。どのステップが現在で、どれが完了し、どれにエラーがあり、どれがこれからなのかを示し、ステップを押してそこへ戻れるようにします。
- カテゴリ
- ナビゲーション
- トークン
comp.stepper- レベル
- 基礎
- Web
tanrei-stepperclock_loader_40 - SwiftUI
TanreiStepperradio_button_unchecked - Jetpack Compose
TanreiStepperradio_button_unchecked - Flutter
TanreiStepperradio_button_unchecked - React Native
Stepperradio_button_unchecked
生成元 docs/status/status.json, specs/stepper.spec.json
横向き、エラーのあるステップを含む
ステッパーは、購入手続き、初期設定、いくつかの部分に分かれた申し込みのように、いまの位置があるフローのコンテンツの上か横に置きます。1 つのステップが現在のステップで、その前のステップは完了しています。1 つがその人の対応を必要としていることがあり、残りはこれからのステップです。
ステップは子要素の <tanrei-stepper-step> で、順番に並べます。value は現在のステップを指します。ステッパーが自分で value を動かすことはありません。その人がステップを押すと、そのステップの値を持つ select を発火します。そこへ移るかどうかはプロダクト側のフローが決め、移るなら value を設定します。
SwiftUI、Compose、Flutter、React Native は計画中です。このページの冒頭で各プラットフォームに添えた名前は仕様が定めたもので、まだ提供していません。
<tanrei-stepper id="checkout" label="購入手続きの進み具合" value="shipping" pressable="visited"
completed-text="完了" error-text="エラーあり" position-text="ステップ {position}/{count}">
<tanrei-stepper-step value="account" label="アカウント"></tanrei-stepper-step>
<tanrei-stepper-step value="shipping" label="配送" description="住所と配送方法"></tanrei-stepper-step>
<tanrei-stepper-step value="gift" label="ギフト包装" description="任意"></tanrei-stepper-step>
<tanrei-stepper-step value="payment" label="支払い"></tanrei-stepper-step>
</tanrei-stepper>
<script type="module">
import '@tanrei/web/components/stepper';
const stepper = document.querySelector('#checkout');
// ステップを押すと、そこへ移りたいという要求になります。フローが判断してから value を動かします。
stepper.addEventListener('select', (e) => {
if (goTo(e.detail.value)) stepper.value = e.detail.value;
});
</script>import { Stepper, StepperStep } from '@tanrei/react';
<Stepper
label="購入手続きの進み具合"
value={step}
pressable="visited"
completedText="完了"
errorText="エラーあり"
positionText="ステップ {position}/{count}"
onSelect={(e) => setStep(e.detail.value)}
>
<StepperStep value="account" label="アカウント" />
<StepperStep value="shipping" label="配送" status={shippingError ? 'error' : 'auto'} />
<StepperStep value="payment" label="支払い" />
<StepperStep value="review" label="確認" />
</Stepper>文言は利用者側で用意します。completed-text と error-text は、支援技術がステップのラベルの後に読み上げる言葉です。position-text はコンパクトな形に表示する 1 行で、{position} と {count} の箇所を含みます。setWords({ stepCompletedText, stepErrorText, stepPositionText }) を使えば、すべてのステッパーに一度だけ渡せます。
縦向きと、コンパクトな形
構成要素
| パーツ | 説明 |
|---|---|
1 root | The ordered list of the flow's steps, named by label: one row of equal columns (horizontal), one column (vertical), or, in the compact form, a bar and two lines of text. It has no fill, no edge and no padding of its own. |
2 step | One item of the list: its marker, its label and, where it has one, its description. A step is in exactly one condition — incomplete, current, complete or error — and, while it can be pressed, in the interaction states. |
3 container | The area of a step that carries hover, focus and press while the step can be pressed: its marker and its text, with the container's padding around them. It has no fill at rest. A step that cannot be pressed draws its container but answers nothing. |
4 marker | What begins a step: a filled or ringed circle holding the step's number, the glyph check (complete) or the glyph priority_high (error). Its fill, ring and content say the step's condition; it is decorative, because the step's condition is also said in words. |
5 label | The step's name, in a few words ("Shipping"). It wraps and is never cut. |
6 description · 任意 | A short second line under the label ("Optional", "2 items"), in a smaller and quieter style. It wraps and is never cut. |
7 connector | The line from a step's marker to the next step's marker: across the column in the horizontal form, down beside the text in the vertical form. Drawn in the complete color after a complete step, so that the way already gone is one line. Decorative. The last step has none. |
8 bar · 任意 | The compact form's row of segments, one per step, filled up to and including the current step. Decorative: the position text says the same in words. |
9 position · 任意 | The compact form's position in the product's words ("Step 2 of 5"), above the current step's label. |
10 focus-ring | The indicator shown for keyboard focus, around a pressable step's container. |
プロパティ
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
label | string | "" | The accessible name of the stepper ("Checkout progress"), in the product's language. Not drawn. It tells the list of steps from the content it tracks, so it is required. |
value | string | "" | The value of the current step: where the person is. Empty, or a value no step has, makes no step current — before the flow begins, or once it is finished. The stepper never changes it itself: the product moves its flow and sets value. |
layout | horizontal | vertical | compact | "horizontal" | horizontal: the steps side by side in equal columns, above the content they track; where the width it is given cannot hold every step at its least width, the stepper draws the compact form instead (SPR-6). vertical: the steps one under another, beside the content or in a narrow column. compact: the bar and the position in words ("Step 2 of 5") with the current step's label, at any width. |
pressable | none | visited | all | "none" | Which steps the person can press to go to them. none: no step; the stepper only shows where the person is. visited: each step that is complete or has an error and is not current — the steps the person has been to, so that they can go back. all: every step that is not current, for a flow whose steps can be done in any order. A disabled step is never pressable, and the current step never is. The compact form presses nothing. |
completedText | string | "" | The word assistive technology hears after the label of a complete step ("Completed"), in the product's language. Not drawn: the check says it to the eye. The product's: Tanrei has no word for it. Empty reads the product's words. Required while a step is complete. |
errorText | string | "" | The word assistive technology hears after the label of a step with an error ("Has an error"), in the product's language. Not drawn: the glyph says it to the eye. The product's: Tanrei has no word for it. Empty reads the product's words. Required while a step has an error. |
positionText | string | "" | The compact form's position: the whole sentence in the product's language with two places the stepper fills, {position} with the current step's place counted from 1 and {count} with the number of steps ("Step {position} of {count}", "ステップ {position}/{count}"). The product's: Tanrei has no sentence for it. Empty reads the product's words. Required while the compact form is drawn. |
イベント
| イベント | 説明 |
|---|---|
select | The person pressed a step to go to it, by pointer, touch, Enter, Space or assistive technology; carries the step's value. The stepper does not change value: the product goes to the step (or does not) and sets value. |
アイテム
このコンポーネントが繰り返すアイテムの種類です。フィクスチャはアイテムを順に並べ、各プラットフォームはそれぞれの流儀で種類ごとに名前を付けます。
step
One step of the flow: its value, its label, an optional description, its status and whether it can be visited.
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
value | string | "" | Identifies the step: the stepper's value names the current step by it, and select carries it. Unique within the stepper; required. |
label | string | "" | The step's name, in a few words ("Shipping"). Drawn, and the start of what assistive technology hears for the step. Required. |
description | string | "" | A short second line under the label ("Optional", "2 items"). Empty draws none. |
status | auto | incomplete | complete | error | "auto" | What the product knows of the step. auto: complete when it comes before the current step and incomplete when it comes after it (or when no step is current) — a flow done in order. incomplete and complete: so, wherever the step stands (a step skipped and left for later; a step done ahead in a flow of any order). error: the step needs the person's attention. The current step is drawn current whatever its status, except error, which it keeps. |
disabled | boolean | false | The step cannot be gone to now (it depends on an earlier choice). Only meaningful while pressable is not none: the step is drawn disabled and is not pressable. Ignored on the current step. |
| 仕様 | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| アイテム | tanrei-stepper-step | TanreiStepperStep | TanreiStepperStep | TanreiStepperStep | StepperStep |
value · プロパティ | value | id | value | value | value |
label · プロパティ | label | label | label | label | label |
description · プロパティ | description | description | description | description | description |
status · プロパティ | status | status | status | status | status |
disabled · プロパティ | disabled | disabled | enabled | enabled | disabled |
| 備考 | A child element: <tanrei-stepper-step value="shipping" label="Shipping" description="…" status="error" disabled>, as <option> in a <select>. | TanreiStepperStep(id:, label:, description:, status: .auto, disabled:), an Identifiable value. | A data class; enabled is the inverse flag. | A value class; enabled is the inverse flag. | The element type of the steps array: { value, label, description?, status?, disabled? }. |
状態
振る舞い
EARS 記法による要件です。各プラットフォームの実装は、この ID に対応するテストで検証されます。要件の原文は仕様ファイルのものをそのまま掲載しています。
| ID | 要件 |
|---|---|
SPR-1 | THE stepper SHALL draw each step in exactly one condition: current WHILE value equals the step's value (the first step with that value, SPR-21) and its status is not error; error WHILE its status is error, current or not; complete WHILE its status is complete, or its status is auto and it comes before the current step; incomplete WHILE its status is incomplete, or its status is auto and it comes after the current step or no step is current. WHEN value or a step's status changes THE stepper SHALL draw every step's new condition at once, without a motion of its own beyond the state motion of SPR-17. |
SPR-2 | THE stepper SHALL draw each step's marker as a circle at least comp.stepper.marker.size high and wide, with corners comp.stepper.marker.shape eased by sys.shape.corner-smoothing, filled with the marker color of the step's condition and state (comp.stepper.incomplete.marker.color, comp.stepper.current.marker.color, comp.stepper.complete.marker.color, comp.stepper.error.marker.color at rest) and edged inside its size by a ring comp.stepper.marker.outline.width wide in the marker outline color of the same (comp.stepper.incomplete.marker.outline.color, and so on). An incomplete or current marker SHALL hold the step's number — its place in the flow, counted from 1 — in comp.stepper.marker.label.typescale and the marker content color of its condition, centred, as a left-to-right run whose digits are never reversed; a complete marker SHALL hold the glyph check and an error marker the glyph priority_high instead, in the marker content color of their condition, each in a box comp.stepper.marker.icon.size large through the platform's icon helper with sys.icon.family.selected, sys.icon.fill.selected, the weight comp.stepper.marker.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max, unmirrored in every layout direction; THE stepper SHALL draw no mark of its own. |
SPR-3 | THE stepper SHALL draw each step's label in comp.stepper.label.typescale and the label color of its condition and state, and, WHERE the step has a description, the description comp.stepper.description.gap under the label in comp.stepper.description.typescale and the description color of the same; 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. A change of condition SHALL NOT change the label's text style, so that no step moves when the current step does. |
SPR-4 | WHILE layout is horizontal and the full form is drawn (SPR-6) THE stepper SHALL lay its steps out in one row of columns of equal width, in order, each column a step's container: its marker at the container's start, comp.stepper.container.padding from its edges, and its label and description under the marker, comp.stepper.marker.gap below it, aligned to the start and as wide as the column less its padding; the row SHALL be exactly as wide as the place it stands in and as high as its tallest step, every step's marker on one line. |
SPR-5 | WHILE layout is vertical THE stepper SHALL lay its steps out in one column, in order, each step's container as wide as the stepper: its marker at the container's start, comp.stepper.container.padding from its edges, and its label and description beside the marker, comp.stepper.marker.gap from it, filling the rest of the width; the marker SHALL be centred on the label's first line, and WHERE the marker is taller than that line the stepper SHALL lower the text by half the difference, so that the marker's top is the content's top. |
SPR-6 | WHILE layout is compact, or layout is horizontal and the width the layout gives the stepper is less than the number of steps times comp.stepper.step.min-width, THE stepper SHALL draw the compact form instead of its steps: the bar — one segment per step in a row as wide as the stepper, comp.stepper.bar.gap apart, each comp.stepper.bar.thickness thick with corners comp.stepper.bar.shape, the segments of the current step and every step before it in comp.stepper.bar.filled.color and the others in comp.stepper.bar.color — then, comp.stepper.position.gap under it, the position in comp.stepper.position.typescale and comp.stepper.position.color, and under that the current step's label as SPR-3 draws a current step's, or an error step's where the current step has an error, preceded there by its marker's glyph priority_high at comp.stepper.marker.icon.size in the error label color. It SHALL decide by the width it is given, not by the window's, and SHALL change form at once WHEN that width crosses the threshold, keeping value. WHILE no step is current THE stepper SHALL draw the bar with no segment filled, and neither the position nor a label. |
SPR-7 | THE stepper SHALL fill the position's places as the product's sentence marks them: {position} with the current step's place counted from 1 and {count} with the number of steps, each written as the platform writes a whole number in the language of the element; it SHALL do nothing else to the sentence, and SHALL draw a sentence without {position} as it is written and in debug builds report it. |
SPR-8 | WHILE a step is followed by another step and the full form is drawn THE stepper SHALL draw a connector from that step's marker to the next step's: a straight line comp.stepper.connector.thickness thick, starting comp.stepper.connector.gap after the step's marker and ending comp.stepper.connector.gap before the next step's marker — across the row on the markers' centre line in the horizontal form, down the markers' centre line in the vertical form — in comp.stepper.connector.complete.color WHILE the step is complete and comp.stepper.connector.color otherwise. No container's fill or state layer SHALL cover a connector, and the connector SHALL be hidden from assistive technology. |
SPR-9 | WHILE pressable is visited THE stepper SHALL make pressable each step that is drawn complete or error, is not current and is not disabled; WHILE pressable is all, each step that is not current and is not disabled; WHILE pressable is none, no step; and in the compact form no step, whatever pressable says. A pressable step SHALL be the platform's own button for the whole of its container, in the focus order in the order of the steps; a step that is not pressable SHALL NOT take focus, SHALL NOT answer a pointer, a press or a key, and SHALL draw no interaction state. |
SPR-10 | WHEN the person activates a pressable step by pointer, touch, Enter, Space or assistive technology THE stepper SHALL emit select exactly once with that step's value, and SHALL NOT change value or any step's condition itself: the product goes to the step and sets value, or keeps the person where they are. |
SPR-11 | WHILE pressable is not none and a step's disabled is true and the step is not current THE stepper SHALL draw the step from the disabled tokens of its condition — its label, description, marker content and ring faded as disabled content, its fill kept, SHALL NOT make it pressable, and SHALL expose it as a disabled button, so that a person who reaches it hears that it cannot be gone to now; WHILE pressable is none THE stepper SHALL draw and expose a step whose disabled is true as it draws any other, because nothing is pressed and so nothing is unavailable. WHILE the current step's disabled is true THE stepper SHALL draw it current and in debug builds report it. |
SPR-12 | WHILE a pressable step is hovered, keyboard-focused or pressed THE stepper SHALL render its container, marker, marker outline, marker content, label, description and opacity from the component tokens of its condition in the highest-precedence active state, with precedence pressed over focused over hovered; focus gained by pointer or touch SHALL NOT select the focused state. |
SPR-13 | WHEN a pressable step receives keyboard focus THE stepper SHALL show the focus ring around that step'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. |
SPR-14 | WHEN a pressable step is pressed by pointer, touch, Enter or Space THE stepper 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. |
SPR-15 | WHILE pressed THE stepper 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 step 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; marker, label, description, 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.stepper.motion.feedback-duration with comp.stepper.motion.state-easing, fades over comp.stepper.motion.state-duration with comp.stepper.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced. |
SPR-16 | THE stepper SHALL ease its containers' corners, comp.stepper.container.shape, 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. |
SPR-17 | WHEN a step changes between interaction states or between conditions THE stepper SHALL change its colors over comp.stepper.motion.state-duration with comp.stepper.motion.state-easing, and at once where motion is reduced; a glyph or a number that replaces another in a marker SHALL be replaced at once. |
SPR-18 | THE stepper SHALL make every step's container at least sys.target.pointer high and wide for fine pointers and sys.target.touch for touch input — a platform that cannot tell the input type SHALL use sys.target.touch — leaving the room it adds below and after the container's content, so that a pressable step's hit area meets the minimum target without reaching over a neighbouring step's, and so that a pressable and a plain step stand alike. |
SPR-19 | THE stepper SHALL be exposed to assistive technology as an ordered list named by label, of as many items as it has steps, each step one item holding, in this order, its label, the product's word for its condition where it has one — completedText for a complete step, errorText for a step with an error, nothing for an incomplete one — and its description; the current step SHALL be exposed as the current step of the flow (the web's aria-current="step"; the platform's selected trait with its position where it has no current state). Markers, numbers, glyphs, connectors and the bar SHALL be hidden: the list gives each step its place, and the words its condition. WHILE the compact form is drawn THE stepper SHALL instead be exposed as one group named by label holding the position and the current step's label, followed by errorText where the current step has an error, so that what is heard is what is drawn. |
SPR-20 | THE stepper SHALL have no words of its own: it SHALL take completedText, errorText and positionText from the instance's prop and, WHILE that is empty, from the product's words of the same keys; WHILE a word that a drawn step needs was given by nobody THE stepper SHALL expose nothing in its place, still draw the step, and record and report the missing word as the product's words do. |
SPR-21 | WHEN value names no step THE stepper SHALL make no step current; WHEN a step's value is empty or repeats another step's THE stepper SHALL still draw it and treat the first step with a value as the one that value names; WHILE label is empty, a step's label is empty, or the stepper holds fewer than two steps, THE stepper SHALL still render; in debug builds it SHALL report each of these, except an empty value, which names the time before or after the flow. |
SPR-22 | WHILE the text size is enlarged THE stepper SHALL grow each label, description, number and position with it and grow each marker with its number, keeping comp.stepper.marker.size as a minimum and every gap and padding as it is, SHALL wrap and never cut text, and SHALL still choose its form by the width it is given (SPR-6). |
SPR-23 | 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 stepper SHALL draw every ring, connector, segment, number, glyph and text in the platform's text color — a pressable step's label in the platform's button text color — the current step's marker filled in the platform's highlight color with its number in the highlight text color, and the filled segments of the bar in the highlight color, and SHALL draw the focus ring in the platform's highlight color; nothing it draws relies on a fill alone. |
SPR-24 | THE stepper 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 stepper is shown THE stepper SHALL draw itself for the new direction at once, without a motion of its own, keeping its focus. |
SPR-25 | WHERE the layout direction is right-to-left THE stepper SHALL mirror its layout by logical start and end — the first step at the right of a horizontal row, the markers at the right of a vertical column, the bar filled from the right — and SHALL keep its reading and focus order first step to last; it SHALL NOT mirror a glyph or reverse a number. |
SPR-26 | THE stepper SHALL lay out each label, description and the position 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 or a number keeps its own order in a right-to-left layout; THE stepper SHALL still place the text and align its lines by the layout direction, not by the text's own. |
SPR-27 | IF the icon set cannot draw a marker's glyph yet (its font is still loading or failed to load) THE stepper SHALL draw nothing in the glyph's place, never the glyph's name as text, keeping the marker's size, fill and ring, and SHALL still expose the step's condition in words; it SHALL show the glyph once the icon set can draw it. |
SPR-28 | WHERE the platform has ARIA attributes (the web), the host carries its list or group role (SPR-19) itself, so what the product writes on it is not moved, but for a name: WHILE label is not empty THE stepper SHALL hold the product's aria-label and aria-labelledby on that host as their data-aria- twins, so that label is its whole name although the platform gives aria-labelledby the precedence, and WHEN label is emptied SHALL give them back as they were written; WHILE label is empty a name the product gives so — aria-label, or aria-labelledby naming an element — SHALL be its name and SHALL NOT be reported as having none in debug builds (SPR-21). WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaLabelledByElements) to null, THE stepper SHALL take it away. |
プラットフォーム別の名前対応
パリティは API が同一であることを意味しません。同じ契約を、各プラットフォームの流儀で表現します。
| 仕様 | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| コンポーネント | tanrei-stepper | TanreiStepper | TanreiStepper | TanreiStepper | Stepper |
label · プロパティ | label | label | contentDescription | semanticLabel | accessibilityLabel |
value · プロパティ | value | current | current | current | value |
layout · プロパティ | layout | layout | layout | layout | layout |
pressable · プロパティ | pressable | pressable | pressable | pressable | pressable |
completedText · プロパティ | completedText | completedText | completedText | completedText | completedText |
errorText · プロパティ | errorText | errorText | errorText | errorText | errorText |
positionText · プロパティ | positionText | positionText | positionText | positionText | positionText |
select · イベント | select | onSelect | onSelect | onSelect | onSelect |
| 備考 | <tanrei-stepper label="Checkout" value="payment" layout="horizontal" pressable="visited"> holds <tanrei-stepper-step> children, in order. The stepper is a role="list" named by aria-label, each step host a role="listitem" with aria-current="step" on the current one; a pressable step draws a native <button> in its shadow root around its marker and text, a step that is not pressable the same parts in a <div>. The words for a condition are a visually hidden span after the label. The compact form is drawn in the stepper's own shadow root, where the steps are not displayed, and the host's role becomes group. The switch from horizontal to compact reads the host's width with a ResizeObserver against comp.stepper.step.min-width measured from a probe. select is a CustomEvent with detail.value; value is never set by the element. React: Stepper and StepperStep, generated wrappers. Fixtures fill their stage: 600 wide for a horizontal stepper, 360 for a vertical one, 320 for a compact one. | TanreiStepper(_ label:, steps:, current: ID?, layout:, pressable:, onSelect:). Not SwiftUI's Stepper, which increments a value (the number input's steppers are that). The list is an accessibility container; the current step carries the .isSelected trait and its position as its accessibility value, because iOS has no current-step state. The compact switch reads the proposed width (ViewThatFits). | TanreiStepper(steps, current, onSelect, layout, pressable, contentDescription, modifier). A collectionInfo list with collectionItemInfo per step; the current step is selected = true with its position in stateDescription, because Compose has no current-step semantics. The compact switch reads the incoming constraints (BoxWithConstraints). | TanreiStepper(steps:, current:, onSelect:, layout:, pressable:, semanticLabel:), built with the widgets library, without Material's Stepper. Semantics(container: true, label:) around a list; the current step Semantics(selected: true) with its position in its value. The compact switch reads the incoming constraints (LayoutBuilder). | <Stepper steps={StepperStep[]} value layout pressable onSelect accessibilityLabel />. The list has role="list" where the platform maps it, each step role="listitem"; the current step aria-current on the web target and accessibilityState.selected with its position elsewhere. A pressable step is a Pressable with role="button". The compact switch reads onLayout. |
トークン
| トークン | 参照先 | 解決値(ライト) |
|---|---|---|
--tanrei-comp-stepper-bar-color | sys.color.outline-variant | |
--tanrei-comp-stepper-bar-filled-color | sys.color.primary | |
--tanrei-comp-stepper-bar-gap | sys.space.space50 | 4px |
--tanrei-comp-stepper-bar-shape | sys.shape.corner.full | 9999px |
--tanrei-comp-stepper-bar-thickness | sys.space.space50 | 4px |
--tanrei-comp-stepper-complete-container-color | — | |
--tanrei-comp-stepper-complete-description-color | sys.color.on-surface-variant | |
--tanrei-comp-stepper-complete-disabled-container-color | — | |
--tanrei-comp-stepper-complete-disabled-description-color | — | |
--tanrei-comp-stepper-complete-disabled-label-color | — | |
--tanrei-comp-stepper-complete-disabled-marker-color | — | |
--tanrei-comp-stepper-complete-disabled-marker-content-color | — | |
--tanrei-comp-stepper-complete-disabled-marker-outline-color | — | |
--tanrei-comp-stepper-complete-disabled-state-layer-color | — | |
--tanrei-comp-stepper-complete-focused-container-color | — | |
--tanrei-comp-stepper-complete-focused-description-color | — | |
--tanrei-comp-stepper-complete-focused-label-color | — | |
--tanrei-comp-stepper-complete-focused-marker-color | — | |
--tanrei-comp-stepper-complete-focused-marker-content-color | — | |
--tanrei-comp-stepper-complete-focused-marker-outline-color | — | |
--tanrei-comp-stepper-complete-focused-state-layer-color | — | |
--tanrei-comp-stepper-complete-hovered-container-color | — | |
--tanrei-comp-stepper-complete-hovered-description-color | — | |
--tanrei-comp-stepper-complete-hovered-label-color | — | |
--tanrei-comp-stepper-complete-hovered-marker-color | — | |
--tanrei-comp-stepper-complete-hovered-marker-content-color | — | |
--tanrei-comp-stepper-complete-hovered-marker-outline-color | — | |
--tanrei-comp-stepper-complete-hovered-state-layer-color | — | |
--tanrei-comp-stepper-complete-label-color | sys.color.on-surface | |
--tanrei-comp-stepper-complete-marker-color | sys.color.secondary-container | |
--tanrei-comp-stepper-complete-marker-content-color | sys.color.on-secondary-container | |
--tanrei-comp-stepper-complete-marker-outline-color | sys.color.secondary-container | |
--tanrei-comp-stepper-complete-pressed-container-color | — | |
--tanrei-comp-stepper-complete-pressed-description-color | — | |
--tanrei-comp-stepper-complete-pressed-label-color | — | |
--tanrei-comp-stepper-complete-pressed-marker-color | — | |
--tanrei-comp-stepper-complete-pressed-marker-content-color | — | |
--tanrei-comp-stepper-complete-pressed-marker-outline-color | — | |
--tanrei-comp-stepper-complete-pressed-state-layer-color | — | |
--tanrei-comp-stepper-complete-state-layer-color | comp.stepper.complete.label.color | |
--tanrei-comp-stepper-connector-color | sys.color.outline-variant | |
--tanrei-comp-stepper-connector-complete-color | sys.color.primary | |
--tanrei-comp-stepper-connector-gap | sys.space.space50 | 4px |
--tanrei-comp-stepper-connector-thickness | sys.border.thick | 2px |
--tanrei-comp-stepper-container-padding | sys.space.space100 | 8px |
--tanrei-comp-stepper-container-shape | sys.shape.corner.small | 6px |
--tanrei-comp-stepper-current-container-color | — | |
--tanrei-comp-stepper-current-description-color | sys.color.on-surface-variant | |
--tanrei-comp-stepper-current-disabled-container-color | — | |
--tanrei-comp-stepper-current-disabled-description-color | — | |
--tanrei-comp-stepper-current-disabled-label-color | — | |
--tanrei-comp-stepper-current-disabled-marker-color | — | |
--tanrei-comp-stepper-current-disabled-marker-content-color | — | |
--tanrei-comp-stepper-current-disabled-marker-outline-color | — | |
--tanrei-comp-stepper-current-disabled-state-layer-color | — | |
--tanrei-comp-stepper-current-focused-container-color | — | |
--tanrei-comp-stepper-current-focused-description-color | — | |
--tanrei-comp-stepper-current-focused-label-color | — | |
--tanrei-comp-stepper-current-focused-marker-color | — | |
--tanrei-comp-stepper-current-focused-marker-content-color | — | |
--tanrei-comp-stepper-current-focused-marker-outline-color | — | |
--tanrei-comp-stepper-current-focused-state-layer-color | — | |
--tanrei-comp-stepper-current-hovered-container-color | — | |
--tanrei-comp-stepper-current-hovered-description-color | — | |
--tanrei-comp-stepper-current-hovered-label-color | — | |
--tanrei-comp-stepper-current-hovered-marker-color | — | |
--tanrei-comp-stepper-current-hovered-marker-content-color | — | |
--tanrei-comp-stepper-current-hovered-marker-outline-color | — | |
--tanrei-comp-stepper-current-hovered-state-layer-color | — | |
--tanrei-comp-stepper-current-label-color | sys.color.on-surface | |
--tanrei-comp-stepper-current-marker-color | sys.color.primary | |
--tanrei-comp-stepper-current-marker-content-color | sys.color.on-primary | |
--tanrei-comp-stepper-current-marker-outline-color | sys.color.primary | |
--tanrei-comp-stepper-current-pressed-container-color | — | |
--tanrei-comp-stepper-current-pressed-description-color | — | |
--tanrei-comp-stepper-current-pressed-label-color | — | |
--tanrei-comp-stepper-current-pressed-marker-color | — | |
--tanrei-comp-stepper-current-pressed-marker-content-color | — | |
--tanrei-comp-stepper-current-pressed-marker-outline-color | — | |
--tanrei-comp-stepper-current-pressed-state-layer-color | — | |
--tanrei-comp-stepper-current-state-layer-color | comp.stepper.current.label.color | |
--tanrei-comp-stepper-description-gap | sys.space.space25 | 2px |
--tanrei-comp-stepper-disabled-container-shape | — | 6px |
--tanrei-comp-stepper-disabled-opacity | — | 1 |
--tanrei-comp-stepper-error-container-color | — | |
--tanrei-comp-stepper-error-description-color | sys.color.error | |
--tanrei-comp-stepper-error-disabled-container-color | — | |
--tanrei-comp-stepper-error-disabled-description-color | — | |
--tanrei-comp-stepper-error-disabled-label-color | — | |
--tanrei-comp-stepper-error-disabled-marker-color | — | |
--tanrei-comp-stepper-error-disabled-marker-content-color | — | |
--tanrei-comp-stepper-error-disabled-marker-outline-color | — | |
--tanrei-comp-stepper-error-disabled-state-layer-color | — | |
--tanrei-comp-stepper-error-focused-container-color | — | |
--tanrei-comp-stepper-error-focused-description-color | — | |
--tanrei-comp-stepper-error-focused-label-color | — | |
--tanrei-comp-stepper-error-focused-marker-color | — | |
--tanrei-comp-stepper-error-focused-marker-content-color | — | |
--tanrei-comp-stepper-error-focused-marker-outline-color | — | |
--tanrei-comp-stepper-error-focused-state-layer-color | — | |
--tanrei-comp-stepper-error-hovered-container-color | — | |
--tanrei-comp-stepper-error-hovered-description-color | — | |
--tanrei-comp-stepper-error-hovered-label-color | — | |
--tanrei-comp-stepper-error-hovered-marker-color | — | |
--tanrei-comp-stepper-error-hovered-marker-content-color | — | |
--tanrei-comp-stepper-error-hovered-marker-outline-color | — | |
--tanrei-comp-stepper-error-hovered-state-layer-color | — | |
--tanrei-comp-stepper-error-label-color | sys.color.error | |
--tanrei-comp-stepper-error-marker-color | — | |
--tanrei-comp-stepper-error-marker-content-color | sys.color.error | |
--tanrei-comp-stepper-error-marker-outline-color | sys.color.error | |
--tanrei-comp-stepper-error-pressed-container-color | — | |
--tanrei-comp-stepper-error-pressed-description-color | — | |
--tanrei-comp-stepper-error-pressed-label-color | — | |
--tanrei-comp-stepper-error-pressed-marker-color | — | |
--tanrei-comp-stepper-error-pressed-marker-content-color | — | |
--tanrei-comp-stepper-error-pressed-marker-outline-color | — | |
--tanrei-comp-stepper-error-pressed-state-layer-color | — | |
--tanrei-comp-stepper-error-state-layer-color | comp.stepper.error.label.color | |
--tanrei-comp-stepper-focused-container-shape | — | 6px |
--tanrei-comp-stepper-focused-opacity | — | 1 |
--tanrei-comp-stepper-hovered-container-shape | — | 6px |
--tanrei-comp-stepper-hovered-opacity | — | 1 |
--tanrei-comp-stepper-incomplete-container-color | — | |
--tanrei-comp-stepper-incomplete-description-color | sys.color.on-surface-variant | |
--tanrei-comp-stepper-incomplete-disabled-container-color | — | |
--tanrei-comp-stepper-incomplete-disabled-description-color | — | |
--tanrei-comp-stepper-incomplete-disabled-label-color | — | |
--tanrei-comp-stepper-incomplete-disabled-marker-color | — | |
--tanrei-comp-stepper-incomplete-disabled-marker-content-color | — | |
--tanrei-comp-stepper-incomplete-disabled-marker-outline-color | — | |
--tanrei-comp-stepper-incomplete-disabled-state-layer-color | — | |
--tanrei-comp-stepper-incomplete-focused-container-color | — | |
--tanrei-comp-stepper-incomplete-focused-description-color | — | |
--tanrei-comp-stepper-incomplete-focused-label-color | — | |
--tanrei-comp-stepper-incomplete-focused-marker-color | — | |
--tanrei-comp-stepper-incomplete-focused-marker-content-color | — | |
--tanrei-comp-stepper-incomplete-focused-marker-outline-color | — | |
--tanrei-comp-stepper-incomplete-focused-state-layer-color | — | |
--tanrei-comp-stepper-incomplete-hovered-container-color | — | |
--tanrei-comp-stepper-incomplete-hovered-description-color | — | |
--tanrei-comp-stepper-incomplete-hovered-label-color | — | |
--tanrei-comp-stepper-incomplete-hovered-marker-color | — | |
--tanrei-comp-stepper-incomplete-hovered-marker-content-color | — | |
--tanrei-comp-stepper-incomplete-hovered-marker-outline-color | — | |
--tanrei-comp-stepper-incomplete-hovered-state-layer-color | — | |
--tanrei-comp-stepper-incomplete-label-color | sys.color.on-surface-variant | |
--tanrei-comp-stepper-incomplete-marker-color | — | |
--tanrei-comp-stepper-incomplete-marker-content-color | sys.color.on-surface-variant | |
--tanrei-comp-stepper-incomplete-marker-outline-color | sys.color.outline | |
--tanrei-comp-stepper-incomplete-pressed-container-color | — | |
--tanrei-comp-stepper-incomplete-pressed-description-color | — | |
--tanrei-comp-stepper-incomplete-pressed-label-color | — | |
--tanrei-comp-stepper-incomplete-pressed-marker-color | — | |
--tanrei-comp-stepper-incomplete-pressed-marker-content-color | — | |
--tanrei-comp-stepper-incomplete-pressed-marker-outline-color | — | |
--tanrei-comp-stepper-incomplete-pressed-state-layer-color | — | |
--tanrei-comp-stepper-incomplete-state-layer-color | comp.stepper.incomplete.label.color | |
--tanrei-comp-stepper-marker-gap | sys.space.space100 | 8px |
--tanrei-comp-stepper-marker-icon-size | sys.icon.extra-small | 16px |
--tanrei-comp-stepper-marker-icon-weight | sys.icon.mark.weight | 500 |
--tanrei-comp-stepper-marker-outline-width | sys.border.thick | 2px |
--tanrei-comp-stepper-marker-shape | sys.shape.corner.full | 9999px |
--tanrei-comp-stepper-marker-size | — | 24px |
--tanrei-comp-stepper-motion-feedback-duration | sys.motion.role.feedback | 450ms |
--tanrei-comp-stepper-motion-state-duration | sys.motion.role.state.large | 250ms |
--tanrei-comp-stepper-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-stepper-position-color | sys.color.on-surface-variant | |
--tanrei-comp-stepper-position-gap | sys.space.space100 | 8px |
--tanrei-comp-stepper-pressed-container-shape | — | 6px |
--tanrei-comp-stepper-pressed-opacity | — | 1 |
--tanrei-comp-stepper-step-min-width | — | 120px |
--tanrei-comp-stepper-description-typescale | sys.typescale.body-small | 400 13px/1.5385 |
--tanrei-comp-stepper-label-typescale | sys.typescale.label | 500 14px/1.4286 |
--tanrei-comp-stepper-marker-label-typescale | sys.typescale.label-small | 500 12px/1.3333 |
--tanrei-comp-stepper-position-typescale | sys.typescale.label-small | 500 12px/1.3333 |
フィクスチャ
基準となる描画パターンです。全プラットフォームが同じ ID でスナップショットを撮り、結果を比較できるようにしています。
horizontal
label: Checkout value: payment completedText: Completed errorText: Has an error items: 4 horizontal-descriptions
label: Checkout value: shipping completedText: Completed errorText: Has an error items: 4 horizontal-error
label: Checkout value: payment completedText: Completed errorText: Has an error items: 4 current-error
label: Checkout value: payment completedText: Completed errorText: Has an error items: 4 pressable-visited
label: Checkout value: payment pressable: visited completedText: Completed errorText: Has an error items: 4 pressable-disabled
label: Set-up value: profile pressable: all completedText: Completed errorText: Has an error items: 4 finished
label: Checkout completedText: Completed errorText: Has an error items: 3 long-labels
label: Application value: documents completedText: Completed errorText: Has an error items: 3 vertical
label: Set-up value: profile layout: vertical completedText: Completed errorText: Has an error items: 4 vertical-error
label: Set-up value: team layout: vertical pressable: visited completedText: Completed errorText: Has an error items: 4 compact
label: Checkout value: shipping layout: compact completedText: Completed errorText: Has an error positionText: Step {position} of {count} items: 5 compact-error
label: Checkout value: payment layout: compact completedText: Completed errorText: Has an error positionText: Step {position} of {count} items: 4 horizontal-rtl
label: الدفع value: payment completedText: مكتمل errorText: به خطأ direction: rtl items: 4 compact-rtl
label: الدفع value: shipping layout: compact completedText: مكتمل errorText: به خطأ positionText: الخطوة {position} من {count} direction: rtl items: 4 生成元 specs/stepper.spec.json, tokens/comp/stepper.tokens.json, design/tokens/
プロダクトが決めた順序で 3〜7 個のステップを進むフローで、いまどこにいて、あとどれだけ残っているかが分かると最後まで進みやすくなるときに使います。購入手続き、いくつかの部分に分かれた登録、申し込みなどです。ステップのコンテンツの上に置くか(横向き)、その横に縦の列として置きます(縦向き)。
次の場合は、ステッパーを使いません。
- 読み手が自分で順に進める手順。これはステップです。位置を持たない番号付きの手順で、マーカーはただの輪であり、進み具合を示すことはありません。
- 2 つのステップしかないフロー、または位置を示しても何も伝わらないほど短いフロー。このページが何のためのものかを言う見出しで足ります。
- どんな順序でも進められる、互いに独立したタスクの長いリスト。これはタスクリストです。タスクごとに状態を添えた行を 1 つ置き、それぞれをリンクにします。
- フロー自身のナビゲーションの代わり。「戻る」ボタンと「続ける」ボタンは残してください。ステッパーはその人がどこにいるかを示すもので、ほとんどの人が移動に使う手段ではありません。
| 状態 | 意味 | 描き方 |
|---|---|---|
| 現在 | その人がいる場所。 | ステップの番号が入った、塗りつぶしのマーカー。 |
| 完了 | 済んだステップ。既定では、現在のステップより前のすべてのステップ。 | チェックの入ったマーカー。 |
| エラー | どこにあっても、その人の対応が必要なステップ。 | 輪と優先度を示すグリフ。ラベルはエラーの色。 |
| 未完了 | これからのステップ。既定では、現在のステップより後のすべてのステップ。 | ステップの番号が入った輪。 |
ステップの status は既定で auto です。現在のステップより前は完了、後は未完了になります。フローがそれ以上のことを知っているときに設定します。直す必要のあるステップには error、順序どおりでなく済んだステップには complete、飛ばしたけれどまだ済ませる必要のあるステップには incomplete を指定します。どの状態も、色だけでなくマーカーの形で見分けられます。
フローが終わったら、value を空にして、すべてのステップに complete を指定します。
pressable="visited"にすると、その人が訪れたステップ(完了したステップやエラーのあるステップ)を押して戻れます。ほとんどのフローにはこれが合います。pressable="all"にすると、現在のステップ以外のどのステップでも押せます。どんな順序でも進められるステップから成るフロー向けです。pressable="none"(既定)は、位置を示すだけです。
多くのシステムと同じく、押せるステップは、ホバーやフォーカスを受けるまで押せないステップと同じ見た目です。利用者にもっと手がかりが必要なら、ステッパーの近くにそう書いてください(「ステップを選んで変更」など)。現在のステップが押せることはありません。まだ進めないステップ(前の選択に左右されるもの)は disabled にします。薄く描かれ、利用できないことが読み上げられます。
横向きのステッパーは、すべてのステップをそれぞれの最小幅で並べられない幅になると、自動でコンパクトな形に変わります。現在のステップまで塗られた区切りのあるバー、プロダクトの言葉による位置(「ステップ 2/5」)、現在のステップのラベルを描きます。layout="compact" を指定すると、どの幅でもこの形になります。コンパクトな形は押せません。その役目はフローの「戻る」ボタンが担います。すべてのステップを見せたままにしたいときは、layout="vertical" で縦の列にします。
- ステップには、その人がすることや渡すものを 1〜2 語で名前を付けます。アカウント、配送、支払い、確認などです。
- ステップの数は最初から最後まで変えません。ときどきしか当てはまらないステップは、途中で加えるのではなく、表示しておいて飛ばします。
- エラーは、その人が直せるステップに付け、何が問題なのかを短い説明で添えます。
- ステッパーを、先へ進む唯一の手段にしない。
- ラベルに番号を書かない。番号はマーカーが示し、リストが読み上げます。
- ページのセクションやタブにステッパーを使わない。それらはタブか目次です。
- ロール
list- ラベル付け
- An ordered list named by label ("Checkout progress"). Each step is an item read as its label, then its condition in the product's words (completedText, errorText), then its description; the current step is exposed as the current step (aria-current="step"). The list gives each step its place ("3 of 4"), so the number in the marker is not read again. In the compact form the stepper is a group named by label that reads the position and the current step's label, as drawn.
- 最小ターゲット
- 見た目のサイズが小さくても、ヒット領域は最小ターゲットサイズを満たします。 minimum 32px · pointer 44px · spacing 8px · touch 48px
キーボード操作
| キー | 動作 |
|---|---|
| Tab / Shift+Tab | Moves focus to the next or previous pressable step, in the order of the steps; a step that cannot be pressed is not a stop. |
| Enter / Space | Presses the focused step: the stepper emits select with its value, and the product goes there. |
備考
- The stepper is an ordered list with the current item marked, as in the W3C's tutorial on forms in several steps: a step's place comes from the list, its condition from words the product gives, and the current step from aria-current="step". It is not a landmark: it belongs to the flow's content, and a page has one.
- Condition is never said by color alone (WCAG 1.4.1): the current marker is filled and holds the number, a complete marker holds a check, an error marker a different glyph, an incomplete marker is a ring; each is also said in words to assistive technology.
- Contrast in the default system: the ring of an incomplete step is outline, held to 3:1 on the surface; the current marker's primary fill is held to 3:1, and its number on-primary to 4.5:1 on it; the complete marker's secondary-container fill is not held to 3:1 by itself, and does not need to be, because its check (on-secondary-container, 4.5:1) identifies it. Labels are on-surface or on-surface-variant (4.5:1), the error label error (4.5:1). The connector and the bar are decorative.
- Pressing a step only asks to go there (select): the product decides, and moves value. A step that cannot be pressed is plain text and not a stop; a disabled step of a pressable stepper is a disabled button, so that a person hears it cannot be gone to now.
- The compact form draws no pressable step: a person goes back with the flow's own Back control. What is drawn is what is heard: the position and the current step.
- How a state looks is a value decision of the active design system; the stepper reads the state's tokens and never computes the effect itself.
- Not the steps of a procedure: a set of instructions to read, with no position, is Steps, whose markers are hairline rings with no fill, no glyph and no state.
生成元 specs/stepper.spec.json, tokens/sys/measure.tokens.json
- ステッパーは、
labelを名前とする順序付きリストです。各ステップは項目で、ラベル、状態を表す言葉(completed-text、error-text)、説明の順に読まれます。リストが各ステップの位置(「4 項目中 3 番目」など)を伝えるので、マーカーの番号を重ねて読むことはありません。 - 現在のステップは、現在のステップとして伝えます(
aria-current="step")。 - 押せるステップはネイティブのボタンで、ステップの順に Tab で止まる位置になります。Enter と Space で押せます。押せないステップはただのテキストで、Tab で止まりません。押せるステッパーの中の無効なステップは、無効なボタンです。
- マーカー、グリフ、コネクター、バーは、支援技術からは隠されます。
- 状態は色だけでなく形でも見分けられます。塗りつぶしのマーカー、チェック、優先度を示すグリフ、輪です。
- コンパクトな形では、ステッパーはラベルを名前とする 1 つのグループになり、描かれているものを読みます。位置と現在のステップのラベル、現在のステップにエラーがあればエラーの言葉です。
- ラベルと説明は折り返し、途中で切れることはありません。文字サイズを大きくするとすべてが大きくなり、ステッパーは与えられた幅に応じてコンパクトな形に変わります。
- 強制カラーモードでは、現在のマーカーはハイライトの色に、それ以外はすべてテキストの色になります。
- ラベルがない場合、どのステップも指さない値、空の値や重複したステップの値、ラベルのないステップ、ステップが 2 つ未満のステッパー、無効と指定された現在のステップ、
{position}を含まない位置の文、言葉が足りない場合は、デバッグビルドで報告します。
- どのフローを追うものかを言う
labelをステッパーに付けます(「購入手続きの進み具合」)。 completed-text、error-text、position-textをプロダクトの言語で指定するか、setWords()で一度だけ渡します。- フロー自身の「戻る」ボタンと「続ける」ボタンを残し、ステップが変わったら新しいステップの見出しにフォーカスを移します。スクリーンリーダーの利用者が、いまどこにいるかを聞けるようにするためです。
- ステップにエラーがあるときは、エラーそのものもステップのコンテンツの中に示します。ステッパーが伝えるのは、そのステップに対応が必要だということだけです。