メインコンテンツへスキップ
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
はじめにWebReactSwiftUIJetpack ComposeFlutterReact Nativeプリセット自分のデザインシステムを作るAI エージェントと Tanrei を使うブランドデザイントークンデザインシステムとカスタマイズTheme Studioカラータイポグラフィアイコン形状エレベーションモーションインタラクション状態振る舞いレイアウトアクセシビリティ言葉カラートークンタイプスケールトークン形状トークンエレベーショントークンモーショントークン状態トークンスペースと寸法のトークンコンポーネントボタンメインアクションボタンセグメントボタンボタングループメニュー付きボタンツールバーコピーボタンチェックボックスラジオボタンスイッチチップメニュースライダースライダーフィールドカレンダーDateTimePickerフィールドグループラジオグループチェックボックスグループセレクトセレクトフィールドメニューバーファイルアップロードファイルピッカー 上級者向けドロップゾーンテキスト入力欄 上級者向けテキストフィールドチップフィールドフィールドコンボボックス 上級者向けコンボボックスフィールド数値入力欄 上級者向け数値フィールドカラー入力欄 上級者向けカラーフィールドワンタイムコード入力欄 上級者向けワンタイムコードフィールド埋め込みテキスト入力欄 上級者向けチャットコンポーザーカード区切り線モーダルレイヤー 上級者向けダイアログリストリスト行ボトムシートサイドシートカルーセルコードブロックテーブルポップオーバーステップアコーディオン説明リスト図アプリシェルページヘッダーツリービュータイムライン画像プレビューハンドルサイズ変更できる枠スクロールエリアバッジプログレスインジケーターメーターナンバーティッカーローディングインジケータースナックバーツールチップキーボードショートカットタグインラインコードコールアウトアバター空の状態タググループスケルトンファイル項目色見本マーキーテキストタブタブビューアプリバーナビゲーションバーナビゲーションドロワー検索リンクページネーション前後のリンクステッパーパンくずリスト目次リンクカードFAB メニューステータスTanrei の作り方コントリビューションライセンスと帰属
ホームコンポーネントリスト

リスト

行、タイル、カード、ファイルなど、プロダクト自身の項目を 1 列、1 行、または折り返してグリッドになる行に並べて保持します。読む、1 つずつ開く、選ぶ、ドラッグして並べ替える、といった操作に使います。

content_copyMarkdown で表示
カテゴリ
コンテインメント
トークン
comp.list
レベル
基礎

概要

Web
tanrei-list
clock_loader_40
SwiftUI
TanreiList
schedule
Jetpack Compose
TanreiList
schedule
Flutter
TanreiList
schedule
React Native
List
schedule

生成元 docs/status/status.json, specs/list.spec.json

タイルを別の場所へドラッグするか、ハンドルを押して移動のメニューを開きます

Photo 1Photo 2Photo 3Photo 4Photo 5

リストは箱です。各項目に表示するのはプロダクト自身のコンテンツ(テキスト、画像、カード、ファイル項目、またはリスト行)です。リスト行は、見出しと1〜2行の補足テキスト、その前後に置く要素からなる行で、多くのリストはこの行でできています。リストが担うのは項目のまわりのすべてです。項目の並べ方、項目間の余白と線、支援技術にとっての意味、項目間のキーボードフォーカスの移動、どれが選ばれているか、そして並べ替えです。

列、行、折り返すグリッド

ApplesBananasCherriesOneTwoThreePhoto 1Photo 2Photo 3Photo 4Photo 5

何かを開く項目、リンクの項目、1 つを選ぶリスト

LightDarkMatch the system

使い方

リストの項目は 1 種類、list-item で、各項目はプロダクトのコンテンツを子要素として持ちます。orientation は項目を列(vertical、既定)または行(horizontal)に並べ、wrap は項目を次の行へ折り返してグリッドにします。gap は項目間の余白(none、small、medium、large)を、dividers は折り返さないリストで項目間にヘアラインを引きます。

項目は、何も指定しなければ静的です。静的な項目は自分では何も描かず余白も加えません。コンテンツがそのまま項目であり、プロダクト自身のコントロールを含められます。interactive を付けると項目全体が 1 つのボタンに、href を付けると 1 つのリンクになります。リンクはブラウザーのほかのリンクと同じく扱われ、新しいタブで開いたりアドレスをコピーしたりできます(target="new" は新しいタブで開き、項目に open_in_new の印を付けます。そのことは targetLabel で伝えます)。selection が single または multiple のリストはリストボックスになり、その項目は value で選ばれるオプションになります。インタラクティブな項目、リンク、オプションはコンテンツに余白を付け、すべての状態を描き、label、なければコンテンツのテキストを名前にします。

<!-- A column of your own boxes, 8 px apart. -->
<tanrei-list gap="small">
  <tanrei-list-item><my-card>…</my-card></tanrei-list-item>
  <tanrei-list-item><my-card>…</my-card></tanrei-list-item>
</tanrei-list>

<!-- A grid of tiles: a line that wraps. -->
<tanrei-list orientation="horizontal" wrap gap="medium">
  <tanrei-list-item><img src="1.jpg" alt="Harbour at dawn" /></tanrei-list-item>
  <tanrei-list-item><img src="2.jpg" alt="Market street" /></tanrei-list-item>
</tanrei-list>

<!-- Items that are one button or one link each, with lines between them. A list row draws a headline and its lines. -->
<tanrei-list dividers>
  <tanrei-list-item interactive>
    <tanrei-list-row leading-icon="wifi" headline="Wi-Fi" supporting-text="Connected"></tanrei-list-row>
  </tanrei-list-item>
  <tanrei-list-item href="/privacy/">Privacy policy</tanrei-list-item>
  <tanrei-list-item href="https://example.com/tanrei" target="new" target-label="opens in a new tab">Source code</tanrei-list-item>
</tanrei-list>

<!-- A listbox: every item is an option, chosen by its value. -->
<tanrei-list selection="single" label="Theme" value="light">
  <tanrei-list-item value="light">Light</tanrei-list-item>
  <tanrei-list-item value="dark">Dark</tanrei-list-item>
</tanrei-list>

<script type="module">
  import '@tanrei/web/components/list';
  // The list sets its own value, or values, before it fires change, which carries them.
  document.querySelector('[selection="single"]').addEventListener('change', (e) => setTheme(e.detail.value));
</script>
import { List, ListItem } from '@tanrei/react';

<List orientation="horizontal" wrap gap="medium">
  {photos.map((photo) => (
    <ListItem key={photo.id}><img src={photo.src} alt={photo.alt} /></ListItem>
  ))}
</List>

<List selection="single" label="Theme" value={theme} onChange={(e) => setTheme(e.currentTarget.value)}>
  <ListItem value="light">Light</ListItem>
  <ListItem value="dark">Dark</ListItem>
</List>

SwiftUI、Compose、Flutter、React Native は追随中です。見出し、補足テキスト、先頭と末尾の要素を持つ以前のリストを提供しており、この改訂の内容はまだありません。

並べ替え

並べ替えられる列。各項目にページ側の削除ボタンがあります

Inter closeNoto Sans JP closeHelvetica Neue close

reorderable を付けると、列でも行でもグリッドでも項目を並べ替えられます。各項目は先頭にハンドルを描き、動かせることを示します。ドラッグできるのはハンドルだけでなく項目全体です。マウスでは数ピクセル動かした時点で、指やペンでは長押しで持ち上がるため、スワイプはこれまでどおりページをスクロールします(ハンドルへのタッチはすぐにドラッグになります)。ほかの項目は道を空けるように滑り、持ち上げた項目はそれらの上でポインターについていき、離すと自分の位置に収まります。

ドラッグだけが手段になることはありません。ハンドルはボタンです。押すか Enter を押すと、4 つの移動(先頭へ、1 つ前へ、1 つ後ろへ、末尾へ)のメニューが開きます。キーボードでは、ハンドルで Space を押すと項目が持ち上がり、矢印キーで 1 つずつ運び(Home と End で先頭と末尾へ)、Space か Enter で置き、Escape で元に戻します。1 歩ごとに読み上げられます。

順番はプロダクトのデータなので、リストが自分で変えることはありません。どの方法で動かしても move が発火し、from に項目のインデックス、to に移動後のインデックスが入ります(どちらも 0 から数えます)。それに応えて項目を並べ替えてください。するとリストは項目が入れ替わる様子を描き、動かした項目のハンドルにフォーカスを保ち、新しい位置を支援技術に伝えます。comp.list.motion.reorder-duration の時間内に何も変えなければ、その移動は拒否されたものとして扱われ、項目は元に戻り、何も読み上げられません。

言葉はプロダクトのものです。ハンドルの名前(dragHandleLabel。場所 {label} にリストが項目の名前を入れます)、その説明(dragHandleHint)、メニューの 4 つの移動、そして読み上げられる 3 つの文(liftedText、movedText、cancelledText。場所は {label}、{position}、{count})です。リストに指定するか、setWords() でプロダクト全体に一度だけ指定します。行のリストでは、列で「上へ移動」「下へ移動」と書くところを「左へ移動」「右へ移動」と書きます。

<tanrei-list id="fonts" reorderable label="Typefaces"
             drag-handle-label="Reorder {label}"
             drag-handle-hint="Space lifts, the arrow keys move, Space drops, Escape cancels; Enter opens the moves"
             move-to-start-label="Move to top" move-before-label="Move up"
             move-after-label="Move down" move-to-end-label="Move to bottom"
             lifted-text="{label} lifted: {position} of {count}"
             moved-text="{label}: {position} of {count}"
             cancelled-text="{label} returned to {position} of {count}">
  <tanrei-list-item label="Inter">Inter</tanrei-list-item>
  <tanrei-list-item label="Noto Sans JP">Noto Sans JP</tanrei-list-item>
</tanrei-list>

<script type="module">
  import '@tanrei/web/components/list';
  const list = document.querySelector('#fonts');
  // The list has moved nothing. Put the item where it was asked to stand: from and to count from 0.
  list.addEventListener('move', ({ detail: { from, to } }) => {
    const items = [...list.children];
    list.insertBefore(items[from], items[to > from ? to + 1 : to] ?? null);
  });
</script>
import { List, ListItem } from '@tanrei/react';

const [fonts, setFonts] = useState(['Inter', 'Noto Sans JP', 'Helvetica Neue']);

// The order is your state. The list finds the moved item again in the order you render.
<List
  reorderable
  label="Typefaces"
  dragHandleLabel="Reorder {label}"
  moveToStartLabel="Move to top"
  moveBeforeLabel="Move up"
  moveAfterLabel="Move down"
  moveToEndLabel="Move to bottom"
  liftedText="{label} lifted: {position} of {count}"
  movedText="{label}: {position} of {count}"
  cancelledText="{label} returned to {position} of {count}"
  onMove={(e) => {
    const { from, to } = e.detail;
    setFonts((now) => {
      const next = [...now];
      next.splice(to, 0, next.splice(from, 1)[0]);
      return next;
    });
  }}
>
  {fonts.map((font) => (
    <ListItem key={font} label={font}>{font}</ListItem>
  ))}
</List>

仕様

構成要素

パーツ 説明
1 list The box that holds the items. It lays them out in a column, a line or lines that wrap, draws nothing behind them and adds no space around them; it carries the semantics of a list or a listbox and moves keyboard focus among the items.
2 item One item: a box around the product's content. A static item draws nothing and adds no space, so its content is the item; an interactive item, a link item or an option pads its content and carries hover, focus and press, and the fill of a selected option.
3 content What the product puts in the item: text, a picture, a card, a file item — anything but, in an item that is itself an action, a link or an option, another interactive element.
4 handle · 任意 The mark at the start of every item of a reorderable list: an icon-only Button showing the drag glyph. It says the item can be moved, a pointer or a finger may drag the item by it, and pressing it opens the move menu; with the keyboard it lifts the item. The whole item can be dragged, not only the handle.
5 move-menu · 任意 The menu the handle opens: a Tanrei Menu with four moves — to the start, one place before, one place after, to the end. The way to reorder that needs neither dragging nor a held key.
6 gap · 任意 While an item is dragged, the empty place where it would land if it were dropped now: the other items slide aside to open it. Not drawn.
7 mark · 任意 The check at the end of a selected option: the glyph check of the system's icon set. Its box is reserved in every option of a selectable list.
8 divider · 任意 A hairline between two neighbouring items of a list that does not wrap, across the list, in the middle of the gap between them.
9 focus-ring Gap-then-ring indicator shown for keyboard focus, drawn inside an interactive item, a link item or an option.
10 announcement · 任意 The list's one live region: empty at rest, it holds the product's sentence that says an item was lifted, where it now stands, or that it went back. Not drawn.

プロパティ

プロパティ 型 既定値 説明
orientation vertical | horizontal "vertical" The direction the items follow one another: vertical, a column from the top; horizontal, a line from the start edge (the left in a left-to-right layout).
wrap boolean false Lets the items run onto a further line where the list ends, so that they form a grid: a horizontal list wraps onto a line below where its width ends, a vertical list onto a column toward the end edge where the height the product gives it ends. Off, the items stay on one line or in one column.
gap none | small | medium | large "none" The space between two neighbouring items, and between two lines of a wrapping list: none, where the items touch, or comp.list.gap.small, medium or large.
dividers boolean false Draws a hairline between every two neighbouring items. Read only while wrap is false: the lines of a grid are told apart by their gap.
iconSpace auto | always | never "auto" Whether a List row that is an item's direct child keeps the room of a leading glyph where it draws no leading part, so that the headlines of the list start on one line. auto: a row keeps the room while the row of another item draws a glyph (leadingIcon), so that a list whose rows have no glyph starts their texts at the row's start. always: every such row keeps it. never: only a row that draws a glyph has it. An avatar, a picture or a control in a row's leading slot does not count and keeps no room beside it. The menu's, the tree view's and the navigation drawer's iconSpace, with the same values and default (LST-50).
density regular | compact "regular" How much room an item takes: the least height of an interactive item, a link item and an option and the padding above and below its content, and the density of every List row that is an item's direct child (LST-51). regular (a 48 item in the default system) is for a product used by touch as well as by pointer; compact (a 32 item, the tree view's compact row) is for a tool used with a pointer, where many items are looked through. For touch an item is never lower than the touch target in either (LST-11). The paddings at the start and the end, the gap and the text style are not changed. A design system may add values.
selection none | single | multiple "none" Whether people choose items: none for a list that shows or opens things, single for choosing one item, multiple for choosing any number. single and multiple make the list a listbox.
label string "" The accessible name of the list: what the items are. Required when selection is single or multiple, and when the list is reorderable.
value string null The value of the selected option while selection is single; null selects none. The list sets it when an option is chosen and emits change; the product may also set it.
values strings The values of the selected options while selection is multiple: a list of strings (the platforms take a set). An empty list selects none.
reorderable boolean false Lets people put the items in another order: every item draws a handle, the whole item can be dragged to another place, the handle opens a menu of moves, and the keyboard lifts and carries an item from its handle. The list reports the move that was asked for with the move event and never changes the order itself: the items are the product's data. Read only while selection is none; every item of a reorderable list is static.
dragHandleLabel string "" The accessible name of an item's handle: the whole name in the product's language with one place, {label}, which the list fills with the item's name ("Reorder {label}", "{label}を並べ替え"), so that the handles of two items are told apart. The product's: Tanrei has no word for it. Empty reads the product's words. Required while reorderable.
dragHandleHint string "" The description of every handle: how to move an item from it with the keyboard, in the product's words ("Press Space to lift, the arrow keys to move, Space to drop, Escape to cancel; Enter opens the moves"). Empty reads the product's words; with neither, the handle has no description.
moveToStartLabel string "" The move menu's item that moves the item to the first place ("Move to top", "Move to start"). Empty reads the product's words. Required while reorderable.
moveBeforeLabel string "" The move menu's item that moves the item one place toward the start ("Move up" in a column, "Move left" in a line). Empty reads the product's words. Required while reorderable.
moveAfterLabel string "" The move menu's item that moves the item one place toward the end ("Move down", "Move right"). Empty reads the product's words. Required while reorderable.
moveToEndLabel string "" The move menu's item that moves the item to the last place ("Move to bottom", "Move to end"). Empty reads the product's words. Required while reorderable.
liftedText string "" The sentence assistive technology is told when the keyboard lifts an item, with three places the list fills: {label} with the item's name, {position} with its place, counted from 1, and {count} with the number of items ("{label} lifted: {position} of {count}"). Empty reads the product's words. Required while reorderable.
movedText string "" The sentence assistive technology is told when a lifted item reaches another place, and once a move has taken effect, whether it came from the menu, the keyboard or a pointer: {label}, {position} (the place it has, or would have if dropped now, counted from 1) and {count} ("{label}: {position} of {count}"). Empty reads the product's words. Required while reorderable.
cancelledText string "" The sentence assistive technology is told when a move with the keyboard is cancelled and the item goes back: {label}, {position} (the place it has again) and {count} ("{label} returned to {position} of {count}"). Empty reads the product's words. Required while reorderable.

イベント

イベント 説明
change The user changed the selection; carries value (single) or values (multiple) after the change.
move The user asked for an item to stand in another place: by the move menu, by dropping it after carrying it with the keyboard, or by dropping it after dragging it. Carries from, the item's index among the list's items when the move began, and to, the index it is to have once it has moved, both counted from 0 (moving the second item one place before is from 1, to 0; dropping the first item after the third is from 0, to 2). Emitted once per move, never for a move that ends where it began, and never while an item is carried. The product reorders its items; the list has changed nothing.

アイテム

このコンポーネントが繰り返すアイテムの種類です。フィクスチャはアイテムを順に並べ、各プラットフォームはそれぞれの流儀で種類ごとに名前を付けます。

list-item · グループ — アイテムを含む

One item of the list: a box around the product's content. It is static, interactive, a link or, in a selectable list, an option.

プロパティ 型 既定値 説明
label string "" The item's name. An interactive item, a link item or an option is named by it in place of its content's text; every item is called by it in the handle's name and in what the list announces about a move. Empty: the headline of a List row that is its content's direct child (LST-49), else the text of the content.
interactive boolean false Makes the item one pressable action that emits its click (an item that changes a setting or opens something in place). Ignored in a selectable list, where every item is an option, and in a reorderable list, where every item is static. Its content must then hold no interactive element. An item that goes to a page takes href instead and is a link, not a button.
href string "" The destination: an address as the platform's links take one (a URL; on the web a path or a fragment as well). Not empty, it makes the item one link — a link item — whether interactive is set or not: the link role, activated by pointer, touch or Enter and not by Space, opened by the platform as its own links are, and drawn exactly as an interactive item is. Ignored in a selectable or a reorderable list. Its content must then hold no interactive element.
target same | new "same" Where the destination opens. same: where the person is. new: a new context — a new tab or window on the web, outside the current screen elsewhere — which the item marks with the glyph open_in_new at its end and says through targetLabel. Ignored without href.
targetLabel string "" What assistive technology reads after the link's name while target is new ("opens in a new tab"), in the product's language. Required while target is new; ignored otherwise.
value string "" Identifies the option: the list's value (single) or values (multiple) select the option whose value they hold, and change carries it. Unique within the list; needed for an option, unused by any other item.
disabled boolean false Prevents activation. The arrow keys still reach it. Ignored for a static item: an item that is not an action, a link or an option has nothing to disable.
スロット 説明
default The item's content: the product's own — text, an image, a card, a file item, a List row. In an interactive item, a link item or an option it is presentational and holds no interactive element; in a static item it may hold the product's controls, which keep their own semantics and focus.
イベント 説明
click The interactive item or the link item was activated by pointer, touch, keyboard or assistive technology. A link item emits it before its destination opens; a product that takes the navigation itself (a client-side router) cancels it (LST-26).
仕様 Web SwiftUI Jetpack Compose Flutter React Native
アイテム tanrei-list-item TanreiListItem TanreiListItem TanreiListItem ListItem
label · プロパティ label label label semanticLabel label
interactive · プロパティ interactive action onClick onTap onPress
href · プロパティ href destination href href href
target · プロパティ target target target target target
targetLabel · プロパティ targetLabel targetLabel targetLabel targetSemanticLabel targetLabel
value · プロパティ value tag value value value
disabled · プロパティ disabled disabled enabled enabled disabled
click · イベント click action onClick onTap onPress
備考 A child element of tanrei-list; its children are its content, in its default slot. Its host has the role listitem or option; an interactive item draws a shadow element with role button and tabindex, as the interactive card does, and fires click; with href the shadow root holds an <a> in its place, inside the host's list item. target is the target attribute with the values same and new (the HTML spellings _self and _blank are read as those two); targetLabel is the target-label attribute. Web-only, forwarded to the anchor and to nothing else: rel (to which new adds noopener) and download. Cancelling click (preventDefault()) cancels the navigation. In a reorderable list the item draws its handle, a tanrei-button, in its shadow root before the slot. TanreiListItem(label:, action:) { content } with a view builder for the content, tagged with .tag(value); destination: URL in place of action: makes it a SwiftUI Link. TanreiListItem(label = …, onClick = …) { content } in the list's content lambda; enabled is the inverse flag. TanreiListItem<T>(value:, onTap:, child:) widgets in the list's children:. The element type of the list's items array: { key, label?, value?, disabled?, onPress?, href?, content }, where content is an element.

list-row

A List row as an item's content: the List row component, as it is drawn anywhere else, which the item tells what it is (LST-48) and the list whether it keeps the room of a leading glyph (LST-50).

プロパティ 型 既定値 説明
headline string "" The row's name; the item is named by it where it has no label (LST-49).
overline string "" A short line above the headline.
supportingText string "" The text under the headline.
leadingIcon string "" A glyph of the system's icon set at the row's start; a row that draws one makes the other rows keep its room while iconSpace is auto (LST-50).
trailingText string "" A short value at the row's end.
trailingIcon string "" A glyph of the system's icon set at the row's very end.
仕様 Web SwiftUI Jetpack Compose Flutter React Native
アイテム tanrei-list-row TanreiListRow TanreiListRow TanreiListRow ListRow
headline · プロパティ headline headline headline headline headline
overline · プロパティ overline overline overline overline overline
supportingText · プロパティ supportingText supportingText supportingText supportingText supportingText
leadingIcon · プロパティ leadingIcon leadingIcon leadingIcon leadingIcon leadingIcon
trailingText · プロパティ trailingText trailingText trailingText trailingText trailingText
trailingIcon · プロパティ trailingIcon trailingIcon trailingIcon trailingIcon trailingIcon

状態

振る舞い

EARS 記法による要件です。各プラットフォームの実装は、この ID に対応するテストで検証されます。要件の原文は仕様ファイルのものをそのまま掲載しています。

ID 要件
LST-1 THE list SHALL lay out its items in the order the product gives them, as far apart as gap names — comp.list.gap.small, comp.list.gap.medium or comp.list.gap.large, and touching while it is none —: WHILE orientation is vertical and wrap is false as one column from the top, each item as wide as the list and as tall as its content; WHILE orientation is horizontal and wrap is false as one line from the start edge, each item as wide as its content and as tall as the tallest item of the line. THE list SHALL never make an item narrower than its content needs or cut it: a line wider than the list goes past the list's end, and the product that wants it scrolled places the list in a scroll view of its own. THE list SHALL draw no fill, no edge and no padding of its own around its items.
LST-2 WHILE wrap is true THE list SHALL arrange its items as a grid: WHILE orientation is horizontal, in lines from the start edge that wrap onto a further line below where the list's width ends; WHILE orientation is vertical, in columns from the top that wrap onto a further column toward the end edge where the block size the product gives the list ends, and in one column where it gives none. Each item SHALL keep its content's size, never wider than the list, the items of one line aligned at their start (their tops in a horizontal list); the gap SHALL stand between two items of a line and between two lines alike; enlarged text SHALL make the items wrap sooner, never run past the list's width. Wrapping SHALL change no order: the items are read, focused and counted in the order given, line by line in the reading direction.
LST-3 WHILE dividers is true and wrap is false THE list SHALL draw a line of comp.list.divider.thickness in comp.list.divider.color between every two neighbouring items, across the list (horizontal in a column, vertical in a line) and in the middle of the gap between them, inside the space of the gap where there is one and over the meeting edge where gap is none; THE list SHALL draw none before the first item or after the last, SHALL keep its color and full opacity in every state and condition of its neighbours (a disabled item's opacity does not reach it), and SHALL hide it from assistive technology. WHILE wrap is true THE list SHALL draw no divider and, where dividers is true, report it in debug builds.
LST-4 THE list 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 list is shown THE list SHALL draw itself for the new direction at once, without a motion of its own, keeping its selection, its scroll position and its focus.
LST-5 WHERE the layout direction is right-to-left THE list SHALL mirror its arrangement: a horizontal line, and every line of a wrapping list, begins at the right and runs to the left, a vertical list wraps onto further columns toward the left, and the handle and the mark stand at the item's right and left ends; the arrow keys that point to the start and the end follow (LST-17, LST-33). THE list SHALL leave the direction of the content's text and the mirroring of the content's glyphs to the product: the content is the product's.
LST-6 WHEN orientation, gap, selection or an item's target names a value the list does not define THE list SHALL render with the default value, and in debug builds report the unknown value.
LST-7 WHILE an item is static — the list's selection is none, the item's interactive is false and its href is empty, or the list is reorderable — THE list SHALL draw nothing of its own around the item's content and add no space to it, so that the item is as large as its content (with its handle in a reorderable list, LST-28), SHALL NOT make the item focusable or emit its click, SHALL draw no hover, focus or press answer on it, SHALL ignore its disabled, and SHALL leave a control in its content its own tokens, semantics and focus stop.
LST-8 WHILE an item is interactive, a link item or an option THE list SHALL draw it as one box: its content padded by comp.list.container.padding-block.regular above and below, comp.list.container.padding-inline-start from the start edge and comp.list.container.padding-inline-end from the end edge, the mark of an option comp.list.container.gap after the content (LST-21), at least comp.list.container.height.regular tall and growing with its content and with enlarged text, its corners comp.list.container.shape, and its whole box the item's hit area. THE list SHALL hand the content the content color of the item's condition and state (comp.list.unselected.content.color at rest, and so on) as its foreground and comp.list.content.typescale as its text style, which text the product did not style takes.
LST-9 WHILE an interactive item, a link item or an option is hovered, keyboard-focused or pressed THE list SHALL render its container, content color, mark 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.
LST-10 WHEN an interactive item, a link item or an option receives keyboard focus THE list SHALL show the focus ring inside the item's box, so that the list's scrolling ancestor cannot clip it, without animation; focus gained by pointer or touch SHALL NOT show it.
LST-11 WHERE an interactive item, a link item or an option is smaller than the minimum target THE list SHALL make its box at least sys.target.touch tall and wide for touch input, in both densities, and for fine pointers at least sys.target.pointer wide and, WHILE density is regular, as tall, WHILE density is compact as tall as its density gives (LST-51), because items that touch cannot extend a hit area over each other; a platform that cannot tell the input type SHALL use sys.target.touch.
LST-12 WHEN the list item is pressed by pointer, touch, Enter or Space THE list item 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.
LST-13 WHILE pressed THE list item SHALL answer as sys.behavior.pressed-feedback names: overlay applies the pressed tokens to the whole container at once; ripple grows the pressed state layer from the point of contact (from the center for keyboard activation); dim applies the pressed opacity to the whole control and draws no state layer; none draws no answer to the press. Under ripple and dim only the container color stays with the state under the press; the content color, mark, 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.list.motion.feedback-duration with comp.list.motion.state-easing, fades over comp.list.motion.state-duration with comp.list.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced.
LST-14 THE list item SHALL ease its container corners by sys.shape.corner-smoothing (0 is a quarter circle, 0.6 the iOS continuous corner; a platform with only the OS curve draws it for any amount above 0) and show its keyboard focus as sys.behavior.focus-style names (ring or glow); a platform that cannot draw a choice SHALL fall back to the first value and state that in its README.
LST-15 WHILE an interactive item, a link item or an option is disabled THE list SHALL NOT emit its click or change for it, SHALL expose the disabled state to assistive technology, SHALL render its container, content color and mark from the disabled component tokens of its condition and SHALL apply the disabled opacity to the whole item, its content included; the arrow keys SHALL still reach it, so that people learn it exists, but Space, Enter, pointer and touch SHALL NOT activate it.
LST-16 WHEN the colors of an interactive item, a link item or an option change between states THE list SHALL animate them over comp.list.motion.state-duration with comp.list.motion.state-easing, and SHALL change them at once where motion is reduced.
LST-17 WHILE the list holds an interactive item, a link item or an option THE list SHALL be one Tab stop — the item that had focus last, or else the first selected option, or else the first enabled item — and SHALL move focus by the arrow keys of its arrangement, without wrapping around: WHILE wrap is false, Down Arrow and Up Arrow to the next and previous item of a vertical list, and the arrow pointing to the end and to the start (Right and Left in a left-to-right layout, the reverse in a right-to-left one) of a horizontal list; WHILE wrap is true, the arrows along the lines to the next and previous item in reading order, and the arrows across them to the item of the next or previous line whose centre is nearest along the line; Home and End to the first and the last item; and to the next item whose name begins with the typed characters when printable characters are typed within one second of each other. Moving focus SHALL NOT change the selection; Space or Enter SHALL activate the focused item, Enter alone a link item (LST-27). Static items SHALL NOT take focus.
LST-18 WHILE selection is none THE list SHALL expose the list role, each item as a list item with its position and the list's size, and an interactive item as one element with the button role, or a link item (LST-26) as one element with the link role, inside its list item; WHILE selection is single or multiple THE list SHALL expose the listbox role named by label, multi-selectable while selection is multiple and with its orientation (horizontal while orientation is horizontal and wrap is false), and each item as an option with its selected state, its position and the list's size, and SHALL ignore interactive and href. A reorderable list SHALL be named by label.
LST-19 THE list SHALL name an interactive item, a link item or an option by its label and, while label is empty, by the name the product gives the item on the element where it gives one (LST-52) — an author's name is over the content, as the platform's text alternative computation puts it — and otherwise by the text of its content, and SHALL present its content as part of it, not as separate elements; the mark, the dividers and the glyph that marks a new context SHALL be hidden from assistive technology. IF an interactive item, a link item, an option or an item of a reorderable list has no name — an empty label, no name the product gives it and no text in its content — THE list SHALL still render it and in debug builds report that it has no name.
LST-20 WHILE an item is interactive, a link item or an option THE item's content SHALL contain no interactive element; a platform that can inspect its content (the web, on every change of it) SHALL report one in debug builds, and a platform that cannot SHALL state the rule in its README and docs page.
LST-21 WHILE selection is single or multiple THE list SHALL reserve a box of side comp.list.mark.size at the end of every option, comp.list.container.gap after its content, and, while the option is selected, draw the glyph check of the system's icon set centered in it, in the mark color of the option's condition, with sys.icon.family.selected, sys.icon.fill.selected, sys.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max, and SHALL NOT mirror it when the layout direction is right-to-left; THE list SHALL draw no mark of its own (no path, shape or character of its own for the check). WHEN an option becomes selected or unselected THE list SHALL fade the check in or out without moving or scaling it, and change the option's colors, over comp.list.motion.state-duration with comp.list.motion.state-easing, and SHALL make the change at once where motion is reduced.
LST-22 IF the icon set cannot draw the check yet (its font is still loading or failed to load) THE list SHALL draw nothing in the check's place, never the glyph's name as text, SHALL keep the box of side comp.list.mark.size, SHALL still expose the option's selected state, and SHALL show the check once the icon set can draw it, without the fade of LST-21.
LST-23 WHEN the user activates an enabled interactive item by pointer, touch, Enter or Space — a link item (LST-26) by pointer, touch or Enter — THE list SHALL emit that item's click exactly once.
LST-24 WHEN the user activates an enabled option of a list whose selection is single and whose value is not that option's value THE list SHALL set value to the option's value, so that the option that was selected becomes unselected, and emit change once; WHEN the option is already selected THE list SHALL change nothing and SHALL NOT emit change, because a single choice is never cleared by its own option. WHEN the user activates an enabled option of a list whose selection is multiple THE list SHALL add the option's value to values, or remove it when values holds it, and emit change once.
LST-25 THE list SHALL render an option as selected, from the selected condition, WHILE selection is single and value equals the option's value, or selection is multiple and values holds it, and every other option from the unselected condition; THE list SHALL draw the selected option's fill (comp.list.selected.container.color in its state) over whatever the list stands on and under the item's content, and hand the content the selected content color; WHEN value or values names no option THE list SHALL select nothing for that name, and WHEN an option's value is empty or repeats another option's THE list SHALL still render it; in debug builds it SHALL report each of these.
LST-26 WHILE selection is none, the list is not reorderable and an item's href is not empty THE list SHALL make the item a link item, whether its interactive is true or false: one element with the link role and not the button role inside its list item, named as LST-19 says, its content held to LST-20; the platform's own link to href (the web's anchor element; SwiftUI's Link; on Compose, Flutter and React Native an element with the platform's link semantics whose address is opened by the platform's opener), so that whatever the platform gives a link — on the web its context menu, opening in a new tab or window, copying and dragging its address, and the address shown before it is followed — is the platform's; and everything this spec says of an interactive item other than its role and its keys — its box, states, focus ring, target, press answer, corners, motion, disabled look and its place in the list's one Tab stop (LST-8 to LST-17) — SHALL hold for a link item from the same tokens, with no look of its own for a link and none for a destination already visited.
LST-27 WHEN the user activates a link item by pointer, touch or Enter THE list SHALL emit that item's click exactly once and then open href where target names, unless the product cancelled that click, in which case it SHALL open nothing: the product's own router has taken the navigation. It SHALL show the pressed state as LST-12 and LST-13 say and SHALL NOT hold the navigation back for sys.motion.duration.press-hold. THE list SHALL NOT activate a link item on Space, which on the web scrolls the page as it does on any link, and SHALL NOT show the pressed state for it; WHERE the platform gives its links other keys or gestures (on the web a modified or a middle click that opens a new tab, on Apple platforms a long press that previews) THE list SHALL leave them to the platform.
LST-28 WHILE an item is a link item and its target is new THE list SHALL open href in a new context — on the web a new tab or window that is given no handle to the page that opened it; on the other platforms outside the screen the person is on, as the platform's opener decides — and SHALL draw the glyph open_in_new of the system's icon set at the item's end, after the content and comp.list.container.gap from it, at sys.icon.small in the content color of the item's condition and state, through the icon helper, which mirrors it in a right-to-left layout because the icon set marks its name, and hidden from assistive technology. THE list SHALL expose targetLabel as the item's description, and WHILE targetLabel is empty SHALL still render and in debug builds report that a link that opens a new context does not say so. WHILE target is same THE list SHALL draw no mark and SHALL ignore targetLabel.
LST-29 WHILE selection is none and an item's href is not empty and its disabled is true THE list SHALL NOT make the item a link that can be followed: it SHALL render the item as LST-15 says, the mark of LST-28 with it, SHALL expose the link role with the disabled state and no destination, SHALL keep it reachable by the arrow keys as LST-15 keeps any disabled item, SHALL NOT emit its click, and SHALL open nothing by any means the platform gives a link (on the web the anchor carries no href, so there is no context menu entry, no drag and no new tab for it).
LST-30 WHILE selection is single or multiple THE list SHALL ignore every item's href, target and targetLabel, as it ignores interactive (LST-18), and in debug builds SHALL report an option that has an href: an option holds a state and is not a destination. WHEN an item's target names a value the list does not define THE list SHALL treat it as same, and in debug builds report the unknown value. IF an item's href is only white space, or names a script to run rather than a place to go (the web's javascript: scheme), or cannot be read as an address by the platform, THE list SHALL make the item what its interactive makes it, without a destination, and in the last two cases report it in debug builds.
LST-31 WHILE selection is none and reorderable is true THE list SHALL be reorderable: it SHALL render every item as a static item (LST-7) whatever its interactive and href say, SHALL draw a handle in every item (LST-32), SHALL let every item be dragged by the whole of it (LST-36), SHALL open the move menu from a handle (LST-33) and SHALL let the keyboard carry an item from its handle (LST-35). WHILE selection is single or multiple THE list SHALL NOT be reorderable, and where reorderable is true SHALL report it in debug builds: an option is chosen by a press that a drag would take.
LST-32 WHILE the list is reorderable THE list SHALL draw in every item, at its start edge and before its content, comp.list.container.gap from it and centred across the item, a handle: an icon-only Tanrei Button of the text variant at Button's small size showing the glyph drag_indicator of the system's icon set, drawn and answering hover, focus and press from Button's tokens, the list's handle in every item the same. THE list SHALL name it by dragHandleLabel with its place {label} filled by the item's name (LST-19), describe it by dragHandleHint, expose it as a button that opens a menu, with its expanded state, and SHALL disable it WHILE the list holds one item, which has nowhere to go — as Button disables a control that stays reachable (focusableWhenDisabled), so that focus that comes to it after the other items were taken away is not lost. The handle SHALL be a Tab stop of its own in every item, before the controls of the item's content.
LST-33 WHEN the user activates an enabled handle by pointer, touch, Enter or Down Arrow THE list SHALL open the move menu: one Tanrei Menu, anchored to that handle as a Menu is to its anchor, holding four items in this order — moveToStartLabel with the glyph vertical_align_top, moveBeforeLabel with arrow_upward, moveAfterLabel with arrow_downward and moveToEndLabel with vertical_align_bottom in a vertical list; first_page, arrow_back, arrow_forward and last_page, which the icon set mirrors in a right-to-left layout, in a horizontal one — with focus on its first enabled item. THE list SHALL disable the two items that would leave the first item where it is, and the two that would leave the last item where it is. WHEN the user chooses one THE list SHALL close the menu and emit move once with from the item's index i and to 0, i − 1, i + 1 or the index of the last item; WHEN the menu asks to be closed otherwise (Escape, a press outside, Tab) THE list SHALL close it and move nothing. Focus SHALL return to the handle when the menu closes (LST-43).
LST-34 WHEN the user presses Space on an enabled handle THE list SHALL lift its item for the keyboard: it SHALL draw the item dragged (LST-37) where it stands, keep focus on its handle and announce liftedText (LST-44). WHILE an item is lifted by the keyboard THE list SHALL take Space, Enter, Escape, Home, End and the arrow keys of its arrangement (LST-17) on the handle and let none of them reach anything else, an overlay that holds the list included: an arrow key SHALL move the item's place one step — in a list that does not wrap one place toward the start or the end; in a wrapping list one place in reading order along the lines, or into the next or previous line at the place whose centre is nearest along the line — and Home and End to the first and the last place, never past either; the item SHALL move into its new place and its neighbours aside as LST-38 says, and each step that changes the place SHALL announce movedText with the place the item would have if dropped now.
LST-35 WHEN the user presses Space or Enter WHILE an item is lifted by the keyboard THE list SHALL drop it: settle it into its place as LST-39 says and, where the place is not the one it was lifted from, emit move exactly once with from the index it had and to the index of its place. WHEN the user presses Escape, or focus leaves the handle, or the window or the app loses focus, or the product changes the list's items, its reorderable or its selection, WHILE an item is lifted by the keyboard THE list SHALL return the item and its neighbours to their places as LST-40 says, emit nothing, and announce cancelledText with the place the item has again — except where the product removed the item.
LST-36 WHILE the list is reorderable THE list SHALL let a pointer drag an item by any part of it that is not an interactive element of its content (a button, a link, a field, a control — which keep their presses), the handle included: WHEN the primary button of a mouse is pressed there and the pointer moves past the platform's touch slop (8 points where the platform names none) THE list SHALL lift the item at once; WHEN a touch or a pen presses the handle and moves past the slop THE list SHALL lift the item at once, and the touch SHALL NOT scroll; WHEN a touch or a pen presses anywhere else on the item and stays within the slop for the platform's long-press duration (500 ms where the platform names none) THE list SHALL lift the item then, and the touch SHALL NOT scroll from then on, while a touch that moves past the slop sooner SHALL scroll, select text or do whatever it did before, and lift nothing. A press of another mouse button, a second pointer while an item is carried, and a press on a disabled handle SHALL lift nothing. THE list SHALL keep the platform's own answers to a long press on a reorderable item (a context menu, a text selection, a preview) from appearing, and a press that lifts nothing SHALL do what it would have done.
LST-37 WHILE an item is dragged — lifted by a pointer or by the keyboard — THE list SHALL draw it above the other items of the list with its content unchanged, filled with comp.list.dragged.container.color under the content, with the shadow comp.list.dragged.container.elevation and the corners comp.list.container.shape, the fill and the shadow arriving over comp.list.motion.state-duration with comp.list.motion.state-easing, and SHALL leave the gap where it would land. WHILE a pointer drags it THE list SHALL move it with the pointer by the distance the pointer has travelled since the press, in the frame the pointer moves and without a motion of its own — along the list's axis only while wrap is false, in both directions while wrap is true — never past the list's own box, wherever the pointer goes; SHALL draw no item and no handle hovered or pressed; SHALL let nothing of the list be selected as text or be taken by the platform's own drag and drop; SHALL show a fine pointer the platform's cursor for something held (grabbing), and the cursor for something that can be held (grab) over a draggable part of an item at rest; and SHALL emit nothing.
LST-38 WHILE an item is dragged THE list SHALL keep the gap where the item would land if it were dropped now and SHALL move every other item whose place that changes, over comp.list.motion.reorder-duration with comp.list.motion.reorder-easing, without fading or scaling it: WHILE wrap is false, WHEN the centre of the dragged item passes the centre of a neighbour, that neighbour SHALL move to the other side of the gap by the dragged item's length and the gap; WHILE wrap is true the dragged item's place SHALL be the place, among those the items had when it was lifted, whose centre is nearest to the dragged item's centre, and every item between its old place and that one SHALL move into the place of its neighbour, so that the grid closes behind the item and opens in front of it. WHILE a pointer is nearer than sys.target.touch to an edge of the list's nearest scrolling ancestor and the list reaches beyond that edge THE list SHALL scroll that ancestor toward it, the faster the nearer, and keep the gap under the dragged item.
LST-39 WHEN the user releases an item dragged by a pointer, or drops one lifted by the keyboard (LST-35), THE list SHALL move it into the gap over comp.list.motion.reorder-duration with comp.list.motion.reorder-easing and take the dragged fill and shadow from it over comp.list.motion.state-duration. IF the gap is not where the item stood when it was lifted THE list SHALL emit move exactly once, with from the index the item had and to the index of the gap, both counted from 0, and SHALL keep drawing the items as they were dropped until the product gives that order or comp.list.motion.reorder-duration has passed since the event, whichever comes first, so that a product that reorders in answer to the event shows no frame of the old order; it SHALL then draw the product's order and go on as LST-43 says, and where the product gave no such order the items SHALL go back to their places over the same motion. IF the gap is where the item stood THE list SHALL emit nothing and announce nothing.
LST-40 WHILE a pointer drags an item, WHEN the user presses Escape, or the platform cancels the pointer or takes it for a gesture of its own, or the window or the app loses focus, or the product changes the list's items, its reorderable or its selection, THE list SHALL end the drag without a move: it SHALL return the item and its neighbours to the places they had over comp.list.motion.reorder-duration with comp.list.motion.reorder-easing, SHALL emit nothing, SHALL announce nothing and SHALL leave the scroll position where the drag brought it. Escape SHALL be taken by the list while an item is dragged and SHALL NOT reach an overlay that holds the list, so that putting an item back does not also close the dialog it is in.
LST-41 WHEN the order of the items of a reorderable list changes — after a move, or because the product changed it — THE list SHALL move every item whose place changed from where it was drawn to its new place over comp.list.motion.reorder-duration with comp.list.motion.reorder-easing, in both directions where the list wraps, without fading or scaling it, the focus ring travelling with the item that holds focus; an item that is new or gone SHALL appear or leave at once, and an item that was just dropped SHALL go on from where it is drawn into its place.
LST-42 WHERE motion is reduced THE list SHALL still move an item dragged by a pointer with the pointer, which is the person's own movement and not a motion of the list's, SHALL give a dragged item the dragged fill and shadow at once, SHALL put a neighbour into its new place at once (LST-38), SHALL put an item lifted by the keyboard into its next place at once (LST-34), SHALL put a released or dropped item into the gap or back to its place at once (LST-39, LST-40, LST-35), SHALL draw a new order at once (LST-41) and SHALL scroll its ancestor near an edge as LST-38 says.
LST-43 WHEN the product, after a move the list emitted, gives its items in an order in which the moved item stands at the index to, THE list SHALL draw that order (LST-41), SHALL set every item's position anew for assistive technology (LST-18), SHALL announce movedText with the place the item now has (LST-44) and SHALL keep keyboard focus with the moved item: WHILE focus was on its handle, in the move menu, or on the handle of the item carried by the keyboard, on the handle of the item now at to, whether the product moved the item it had or gave a new one for the same content; WHILE focus was elsewhere THE list SHALL NOT move it. IF the product has not given such an order by the time comp.list.motion.reorder-duration has passed since the move was emitted THE list SHALL take the move as refused: it SHALL announce nothing, leave focus on the handle of the item that stands where it stood, and draw the items as the product has them.
LST-44 WHILE the list is reorderable THE list SHALL hold one live region of its own, polite, empty at rest and not drawn, and SHALL have nothing else of the list announce a move. THE list SHALL put into it liftedText when the keyboard lifts an item (LST-34), movedText when an item lifted by the keyboard reaches another place (LST-34) and when a move has taken effect (LST-43), and cancelledText when a move with the keyboard is cancelled (LST-35), each with its places filled — {label} by the item's name (LST-19), {position} by its place counted from 1, and {count} by the number of items, the two numbers written as the platform writes a whole number in the language of the list — so that it is announced once, after what is being read; a later sentence SHALL replace what the region holds and SHALL NOT queue behind it. THE list SHALL fill the places as a word with places is filled: each place wherever and however often the product wrote it; any other text between braces, and a brace that opens or closes nothing, left as it is written and in debug builds reported once per page or screen, naming the prop; a brace written twice drawn as one brace; and the name inserted as plain text of its own direction, isolated from the sentence. THE list SHALL announce nothing when a pointer lifts an item or carries it over others: the person using a pointer is watching the item, and assistive technology is told the one thing that happened, where the item now stands.
LST-45 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 list SHALL draw a dragged item on the platform's background color with an edge sys.border.hairline wide in the platform's highlight color all around it, in place of a fill and a shadow that are not drawn there, SHALL draw the dividers in the platform's text color, and SHALL leave the handle and the move menu to be drawn as a Button and a Menu are there.
LST-46 WHEN the product takes away an item of a reorderable list that holds keyboard focus THE list SHALL move focus to the handle of the item that now stands where that item stood, else of the item before it; WHEN the last item is taken away THE list SHALL leave focus to the product, which knows where a person adds an item. THE list SHALL announce nothing for a removal or an addition: what was removed is the product's to say. A control the product places in an item's content — a button that removes the item — keeps its own tokens, semantics and focus stop, after the handle in reading and focus order.
LST-47 THE list SHALL have no words of its own: it SHALL take dragHandleLabel, dragHandleHint, moveToStartLabel, moveBeforeLabel, moveAfterLabel, moveToEndLabel, liftedText, movedText and cancelledText from the instance's prop and, WHILE that is empty, from the product's words of the same key, and from nowhere else; WHILE the list is reorderable and one of them other than dragHandleHint is empty in both, it SHALL still render and work, and in debug builds report the missing word once. IF dragHandleLabel has no place {label} THE list SHALL name every handle with it as it is written and report in debug builds that the handles of two items cannot be told apart.
LST-48 WHERE an element that fits itself to its item (a List row, list-row) is a direct child of an item THE list SHALL tell it what the item is — whether it is an action, a link or an option, which pads its content (LST-8); whether it draws the handle of a reorderable list before its content (LST-32); whether it is a selected option; whether it is a disabled action, link or option; whether it keeps the room of a leading glyph (LST-50) — before that element is first drawn in the item and again WHEN any of these changes (selection, interactive, href, disabled, the list becoming reorderable or not, or what LST-50 decides), so that the element draws itself to fit the item in every arrangement and mode of the list. An element that is not a direct child of the item SHALL be told nothing and SHALL draw itself as it stands alone.
LST-49 WHERE an item's label is empty and its content holds a List row as a direct child THE list SHALL take the item's name from that row's headline in place of the text of its content — for the accessible name of an action, a link or an option, the handle's name, typeahead and every announcement — and SHALL describe an action, a link or an option by the row's overline, supporting text and trailing text, in that order, before the description of a link that opens a new context (LST-28); WHEN the row's texts change THE list SHALL take the new name and description at once. An item with a label keeps it as its name and is still described by the row.
LST-50 THE list SHALL decide for all its items together whether a List row that is an item's direct child (LST-48) keeps the room of a leading glyph where it draws no leading part (LRW-16). WHILE iconSpace is auto THE list SHALL tell every such row to keep the room WHERE an item of the list holds a List row whose leading part is a glyph — its leadingIcon, its leading slot empty —, so that the headlines of the rows with a glyph and of the rows without one start on one line, and SHALL tell none to keep it WHERE no item does, so that a list without glyphs starts its texts at the row's start; WHILE iconSpace is always THE list SHALL tell every such row to keep it, whether or not any row draws a glyph; WHILE iconSpace is never THE list SHALL tell none to keep it, so that only a row that draws a glyph has its room. The content of a row's leading slot (an avatar, a picture, a control) SHALL NOT count, because its size is the product's and differs from row to row, so that a room kept for it would line up nothing. The list is one run of items: its rows are decided together whatever its orientation, wrap, gap, dividers, selection and reorderable are. WHEN an item is added, removed or moved, or a row's leadingIcon or the content of its leading slot changes, THE list SHALL decide again; WHEN iconSpace names a value the list does not define THE list SHALL treat it as auto and in debug builds report the unknown value.
LST-51 THE list SHALL draw its items at its density. WHILE density is regular an interactive item, a link item and an option SHALL be at least comp.list.container.height.regular tall and padded by comp.list.container.padding-block.regular above and below (LST-8); WHILE density is compact at least comp.list.container.height.compact tall and padded by comp.list.container.padding-block.compact. A static item draws no box of its own and is not changed. THE list SHALL tell a List row that is an item's direct child (LST-48) the list's density, before the row is first drawn in the item and again WHEN density changes, and the row SHALL draw at that density in place of its own (LRW-17), so that the rows of one list are of one density. WHEN density names a value the active design system does not have THE list SHALL draw the default density's items and in debug builds report the unknown value; a density a design system added SHALL be drawn from that density's tokens, as the core values are. WHEN density changes while the list is shown THE list SHALL draw the new items at once, without a motion, keeping focus and the selection.
LST-52 WHERE the platform has ARIA attributes (the web), the hosts of the list, of an option and of an item that is neither an action nor a link carry their roles themselves (LST-18), so what the product writes on them is not moved, but for a name: WHILE the list's label, or an option's label or the text of its content, is not empty THE list SHALL hold the product's aria-label and aria-labelledby on that host as their data-aria- twins, so that its own is the whole name although the platform gives aria-labelledby the precedence, and WHEN it is emptied SHALL give them back as they were written; WHILE it is empty a name the product gives so is the name and SHALL NOT be reported as having none in debug builds (LST-18, LST-19); an item that is neither an action nor a link has no name of its own and keeps the product's. WHILE an item is an interactive item or a link item, and WHILE the list is reorderable, the role is carried by the element inside — the action, or the list inside the host (LST-44) — and WHEN the product sets an aria- attribute on that host, by the attribute or by the ARIA property that reflects it, THE list SHALL move it to the data-aria- attribute of the same name, so that the host is no second node with its name, description or state, and SHALL expose it on that element — an id reference by the elements it names in the host's tree or a tree around it, a description after its own — except aria-disabled on an item, which the item owns and which THE list SHALL move, not expose and report in debug builds; its label is the name over a name given so (LST-19). WHEN an item or the list leaves that mode THE list SHALL give back to its host what it moved, as it was written, and WHEN it enters it SHALL move what the host carries. WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaDescribedByElements…) to null, THE list SHALL take it away.

プラットフォーム別の名前対応

パリティは API が同一であることを意味しません。同じ契約を、各プラットフォームの流儀で表現します。

仕様 Web SwiftUI Jetpack Compose Flutter React Native
コンポーネント tanrei-list TanreiList TanreiList TanreiList List
orientation · プロパティ orientation axis orientation direction orientation
wrap · プロパティ wrap wraps wrap wrap wrap
gap · プロパティ gap spacing gap spacing gap
dividers · プロパティ dividers dividers dividers dividers dividers
iconSpace · プロパティ iconSpace iconSpace iconSpace iconSpace iconSpace
density · プロパティ density density density density density
selection · プロパティ selection selection selectionMode selectionMode selectionMode
label · プロパティ label label contentDescription semanticLabel accessibilityLabel
value · プロパティ value selection selectedValue selected value
values · プロパティ values selection selectedValues selected values
reorderable · プロパティ reorderable onMove onMove onMove reorderable
dragHandleLabel · プロパティ dragHandleLabel dragHandleLabel dragHandleLabel handleSemanticLabel dragHandleLabel
dragHandleHint · プロパティ dragHandleHint dragHandleHint dragHandleHint handleSemanticHint dragHandleHint
moveToStartLabel · プロパティ moveToStartLabel moveToStartLabel moveToStartLabel moveToStartLabel moveToStartLabel
moveBeforeLabel · プロパティ moveBeforeLabel moveBeforeLabel moveBeforeLabel moveBeforeLabel moveBeforeLabel
moveAfterLabel · プロパティ moveAfterLabel moveAfterLabel moveAfterLabel moveAfterLabel moveAfterLabel
moveToEndLabel · プロパティ moveToEndLabel moveToEndLabel moveToEndLabel moveToEndLabel moveToEndLabel
liftedText · プロパティ liftedText liftedText liftedText liftedText liftedText
movedText · プロパティ movedText movedText movedText movedText movedText
cancelledText · プロパティ cancelledText cancelledText cancelledText cancelledText cancelledText
change · イベント change selection onSelectionChange onSelectionChanged onSelectionChange
move · イベント move onMove onMove onMove onMove
備考 tanrei-list holds tanrei-list-item children. It sets its own value or values (an array property; the values attribute is not reflected) before firing change, as a native control does. Focus moves among actionable items by a roving tabindex. Each item is a separate element, so the list sets aria-posinset and aria-setsize on them. Words: the attributes drag-handle-label, drag-handle-hint, move-to-start-label, move-before-label, move-after-label, move-to-end-label, lifted-text, moved-text and cancelled-text, and the same keys of setWords(). move is a CustomEvent whose detail is { from, to }; it bubbles, is not cancelable, and the list moves no element: the product reorders the tanrei-list-item children (or its framework does), and the list sees it as a change of its children. The move menu is one tanrei-menu in the list's shadow root, placed against the handle that opened it. A dragged item and its neighbours are moved by transforms, so the product's elements never change place under it; the item carries touch-action: pan-x pan-y and the handle touch-action: none, and a long press is told from a swipe by a non-passive touchmove listener that is cancelled only once the item is lifted. The live region is one visually hidden role="status" element in the list's shadow root. Before the element is defined (no script) the items are plain children in the order written and nothing can be moved. Ships the previous revision of the list today — rows with a headline, supporting text, leading and trailing parts and the check, selection, interactive items — and none of this revision is built on this platform yet: TanreiList(axis: .vertical, wraps:, spacing:) { … } laid out by a custom Layout (a flow layout while wrapping); onMove: (from, to) makes it reorderable — the handle with a Menu of the four moves, the whole row draggable through onDrag/onDrop or a long-press gesture, the moves also exposed as accessibility custom actions, and the sentences posted as accessibility announcements. Ships the previous revision of the list today — rows with a headline, supporting text, leading and trailing parts and the check, selection, interactive items — and none of this revision is built on this platform yet: TanreiList(orientation, wrap, gap) { … } — a Column, a Row or a FlowRow/FlowColumn while wrapping — with onMove: (from: Int, to: Int) -> Unit making it reorderable: the handle opens a DropdownMenu of the four moves, the whole item is dragged after a long press (detectDragGesturesAfterLongPress) and at once from the handle, the moves are also customActions of the item's semantics, and the announcement is a polite live region node. Items need stable keys for the motion of LST-41. Ships the previous revision of the list today — rows with a headline, supporting text, leading and trailing parts and the check, selection, interactive items — and none of this revision is built on this platform yet: TanreiList(direction: Axis.vertical, wrap:, spacing:, children:) — a Flex or a Wrap — with onMove: (int from, int to) making it reorderable: the handle opens a MenuAnchor of the four moves, the whole item is a LongPressDraggable (a Draggable from the handle), the moves are also semantics custom actions, and the sentences go through SemanticsService.announce. to is the index the item has after the move, not the insertion index of the framework's reorderable list. Ships the previous revision of the list today — rows with a headline, supporting text, leading and trailing parts and the check, selection, interactive items — and none of this revision is built on this platform yet: <List items orientation wrap gap onMove> — a flex container with flexWrap — the handle opening a menu of the four moves, the whole item dragged after a long press through a gesture responder, the moves also accessibilityActions of the item, and the sentences announced through AccessibilityInfo.announceForAccessibility.

トークン

トークン 参照先 解決値(ライト)
--tanrei-comp-list-container-gap sys.space.space200 16px
--tanrei-comp-list-container-height-compact comp.tree-view.container.height.compact 32px
--tanrei-comp-list-container-height-regular — 48px
--tanrei-comp-list-container-padding-block-compact — 4px
--tanrei-comp-list-container-padding-block-regular — 8px
--tanrei-comp-list-container-padding-inline-end sys.space.space200 16px
--tanrei-comp-list-container-padding-inline-start sys.space.space200 16px
--tanrei-comp-list-container-shape sys.shape.corner.none 0px
--tanrei-comp-list-disabled-container-shape — 0px
--tanrei-comp-list-disabled-opacity — 0.38
--tanrei-comp-list-divider-color sys.color.outline-variant #000000 · 8%
--tanrei-comp-list-divider-thickness sys.border.hairline 1px
--tanrei-comp-list-dragged-container-color sys.color.surface-container-high #f3f3f3
--tanrei-comp-list-dragged-container-elevation sys.elevation.level3 0px 0px 0px 1px rgb(0 0 0 / 0.08), 0px 1px 1px 0px rgb(0 0 0 / 0.04), 0px 4px 8px -4px rgb(0 0 0 / 0.04), 0px 16px 24px -8px rgb(0 0 0 / 0.06)
--tanrei-comp-list-focused-container-shape — 0px
--tanrei-comp-list-focused-opacity — 1
--tanrei-comp-list-gap-large sys.space.space300 24px
--tanrei-comp-list-gap-medium sys.space.space200 16px
--tanrei-comp-list-gap-small sys.space.space150 12px
--tanrei-comp-list-hovered-container-shape — 0px
--tanrei-comp-list-hovered-opacity — 1
--tanrei-comp-list-mark-size sys.icon.medium 24px
--tanrei-comp-list-mark-width sys.border.thick 2px
--tanrei-comp-list-motion-feedback-duration sys.motion.role.feedback 450ms
--tanrei-comp-list-motion-reorder-duration sys.motion.role.selection.travel 250ms
--tanrei-comp-list-motion-reorder-easing sys.motion.easing.spatial cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-list-motion-state-duration sys.motion.role.state.large 250ms
--tanrei-comp-list-motion-state-easing sys.motion.easing.state cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-list-pressed-container-shape — 0px
--tanrei-comp-list-pressed-opacity — 1
--tanrei-comp-list-selected-container-color sys.color.secondary-container #262626 · 16%
--tanrei-comp-list-selected-content-color sys.color.on-secondary-container #262626
--tanrei-comp-list-selected-disabled-container-color — #262626 · 16%
--tanrei-comp-list-selected-disabled-content-color — #262626
--tanrei-comp-list-selected-disabled-mark-color — #1b1b1b
--tanrei-comp-list-selected-disabled-state-layer-color — #262626
--tanrei-comp-list-selected-focused-container-color — #262626 · 24.4%
--tanrei-comp-list-selected-focused-content-color — #262626
--tanrei-comp-list-selected-focused-mark-color — #1b1b1b
--tanrei-comp-list-selected-focused-state-layer-color — #262626
--tanrei-comp-list-selected-hovered-container-color — #262626 · 22.7%
--tanrei-comp-list-selected-hovered-content-color — #262626
--tanrei-comp-list-selected-hovered-mark-color — #1b1b1b
--tanrei-comp-list-selected-hovered-state-layer-color — #262626
--tanrei-comp-list-selected-mark-color sys.color.primary #1b1b1b
--tanrei-comp-list-selected-pressed-container-color — #262626 · 24.4%
--tanrei-comp-list-selected-pressed-content-color — #262626
--tanrei-comp-list-selected-pressed-mark-color — #1b1b1b
--tanrei-comp-list-selected-pressed-state-layer-color — #262626
--tanrei-comp-list-selected-state-layer-color comp.list.selected.content.color #262626
--tanrei-comp-list-unselected-container-color — #000000 · 0%
--tanrei-comp-list-unselected-content-color sys.color.on-surface #1b1b1b
--tanrei-comp-list-unselected-disabled-container-color — #000000 · 0%
--tanrei-comp-list-unselected-disabled-content-color — #1b1b1b
--tanrei-comp-list-unselected-disabled-mark-color — #000000 · 0%
--tanrei-comp-list-unselected-disabled-state-layer-color — #1b1b1b
--tanrei-comp-list-unselected-focused-container-color — #1b1b1b · 10%
--tanrei-comp-list-unselected-focused-content-color — #1b1b1b
--tanrei-comp-list-unselected-focused-mark-color — #000000 · 0%
--tanrei-comp-list-unselected-focused-state-layer-color — #1b1b1b
--tanrei-comp-list-unselected-hovered-container-color — #1b1b1b · 8%
--tanrei-comp-list-unselected-hovered-content-color — #1b1b1b
--tanrei-comp-list-unselected-hovered-mark-color — #000000 · 0%
--tanrei-comp-list-unselected-hovered-state-layer-color — #1b1b1b
--tanrei-comp-list-unselected-mark-color — #000000 · 0%
--tanrei-comp-list-unselected-pressed-container-color — #1b1b1b · 10%
--tanrei-comp-list-unselected-pressed-content-color — #1b1b1b
--tanrei-comp-list-unselected-pressed-mark-color — #000000 · 0%
--tanrei-comp-list-unselected-pressed-state-layer-color — #1b1b1b
--tanrei-comp-list-unselected-state-layer-color comp.list.unselected.content.color #1b1b1b
--tanrei-comp-list-content-typescale sys.typescale.body 400 14px/1.5714

フィクスチャ

基準となる描画パターンです。全プラットフォームが同じ ID でスナップショットを撮り、結果を比較できるようにしています。

生成元 specs/list.spec.json, tokens/comp/list.tokens.json, design/tokens/

ガイドライン

使う場面

1 種類のものの集まりで、目を通す、開く、選ぶ、並べる対象に使います。メッセージ、人、ファイル、写真、設定、ピッカーの選択肢などです。列をまたいで値を比べるなら表を、ボタンから開く短い操作の集まりならメニューを使います。

リストは自分では何も描きません。背景も、項目のまわりの余白も、スクロールもありません。サーフェス、カード、画面のスクロールビューの中に置き、各項目の見た目はコンテンツで整えてください。

4 種類の項目

種類 指定方法 実体 用途
静的 selection が none、interactive が false、href なし コンテンツそのもの。フォーカスもホバーも押下もありません。 読むだけの項目、自前のコントロールを持つ項目。
インタラクティブ interactive リスト項目の中の 1 つのボタン。 それぞれが何かを変える、またはその場で開く項目。
リンク href リスト項目の中の 1 つのリンク。インタラクティブな項目とまったく同じ見た目です。Enter で開き、Space では開きません。 それぞれ固有のアドレスを持つページへ移る項目。
オプション selection が single か multiple リストボックスのオプション。選択状態とチェックを持ちます。 項目から選ぶ。

静的、インタラクティブ、リンクの項目は 1 つのリストに混在できます。選択できるリストはオプションだけを持ちます。並べ替えられるリストは静的な項目だけを持ち、リストボックスにはなりません。操作、リンク、オプションは、ドラッグが奪ってしまう押下で使われるからです。

並べ替えられるリスト

  • 順番に意味があり、その順番を決めるのが利用者である場面で reorderable を使います。フォントスタックのファミリー、ホーム画面のセクション、添付ファイル、キューなどです。長いリストには、代わりに並べ替え(ソート)の手段を用意してください。
  • move のハンドラーの中で、またはフレームワークが描画し直す直後に項目を並べ替えます。今ある要素を動かしても、新しい要素を描画しても構いません。リストは位置と名前で動かした項目を見つけます。
  • コンテンツのテキストが項目をうまく名指さない場合は label を付けます。名前はハンドルの名前の一部になるので 2 つの項目のハンドルを区別でき、読み上げられる内容にもなります。
  • それぞれの文は場所を含めて文全体を書きます。リストは自分で句を組み立てないため、語順はその言語のものになります。
  • 項目の中に置いたプロダクトのコントロール(項目を削除するボタンなど)は、ハンドルの後に独自のフォーカス位置を保ちます。項目名を含めた名前を付けてください(「Inter を削除」)。フォーカスを持つ項目を削除すると、リストはその位置に来た項目のハンドルへフォーカスを移します。削除したことはプロダクトが伝えてください。

選択の種類

選択 リストの役割 オプションを選ぶと
なし(既定) リスト 何も選ばれません。インタラクティブな項目は自分の click を発火します。
単一 リストボックス そのオプションを選び、選ばれていたものを外します。もう一度選んでも外れません。
複数 複数選択のリストボックス オプションのオンとオフを切り替えます。

矢印キーはフォーカスを動かすだけです。選択は、Space か Enter を押すか項目をタップしたときに変わります。選ばれたオプションは選択時の塗りと末尾のチェックで描かれ、チェックの場所はどのオプションにも確保されるので、コンテンツの位置がそろいます。

グリフのある行とない行

項目がリスト行を持ち、一部の行にだけ先頭のグリフ(leadingIcon)があるとき、ほかの行がテキストをどこから始めるかを iconSpace が決めます。

iconSpace グリフのない行
auto(既定) リストのほかの行がグリフを描いている間は、グリフの幅を空けておきます。そのため、すべての見出しが一直線に始まります。どの行もグリフを描かないリストでは、テキストは行の先頭から始まります。
always どの行もグリフを描かない場合でも、すべての行で幅を空けておきます。
never 幅を空けません。テキストは行の先頭から始まります。

リストは、どの並べ方とモードでも、すべての行をまとめて決めます。行の leading スロットのアバター、画像、コントロールは数えず、その横に幅も空けません。その大きさはプロダクトが決めるもので、行ごとに違うからです。メニュー、ツリービュー、ナビゲーションドロワーにも、同じ値と既定値の iconSpace があります。

density は項目が取る広さを決めます。regular(既定)と、マウスで使い多くの項目を見渡すツール向けの compact です。compact のリストでは、アクション、リンク、テキストだけのオプションの高さが 32 になり、項目のリスト行は自身の density にかかわらず compact で描かれます。1 つのリストの行は 1 つの密度にそろいます。タッチでは項目がタッチターゲットより低くなることはありません。

推奨

  • 選択できるリストにはオプションが何かを示す label を、並べ替えられるリストには項目が何かを示す label を付けます。
  • ページへ移る項目には href を付け、その場で動作する項目には interactive を使います。
  • 2 つのリストの間に見出しを置いてセクションを作ります。リストには独自のセクション見出しはありません。

非推奨

  • インタラクティブな項目、リンク項目、オプションの中にボタン、リンク、スイッチなどのコントロールを入れないでください。項目は 1 つの要素なので、支援技術は中のコントロールに届かず、コントロールを押すと項目も作動してしまいます。
  • すぐに実行されるものにオプションを使わないでください。リストボックスは値を選ぶものです。
  • 自前のドラッグハンドルや移動ボタンを描かないでください。reorderable がハンドルを描き、そのメニューがドラッグを使わない移動手段になります。

アクセシビリティ

ロール
list (listbox while selection is single or multiple)
ラベル付け
A selectable list is a listbox named by label; a reorderable list is named by label too. An interactive item, a link item or an option is named by its label or else by its content's text, and its content is presentational. While target is new, a link item is described by its targetLabel. In a reorderable list each handle is a button that opens a menu, named by dragHandleLabel with the item's name and described by dragHandleHint; the move menu's items are named by the four move words. The list's one live region says liftedText, movedText and cancelledText, with the item's name, its place and the number of items.
最小ターゲット
見た目のサイズが小さくても、ヒット領域は最小ターゲットサイズを満たします。 minimum 32px · pointer 44px · spacing 8px · touch 48px

キーボード操作

キー 動作
Tab / Shift+Tab Moves focus into the list (to the item focused last, the first selected option or the first enabled item) and out of it. A list of static items is not a tab stop; focus moves through the controls in its items. In a reorderable list every handle is a stop, before the controls of its item.
Arrow keys Move focus to the next or previous item along the list: Up and Down in a column, Left and Right in a line (mirrored in a right-to-left layout). In a wrapping list the arrows along the lines move in reading order and the arrows across them move to the nearest item of the next or previous line. They do not change the selection.
Home / End Moves focus to the first or last item.
Printable characters Moves focus to the next item whose name begins with the characters typed.
Space / Enter Activates the focused item: an interactive item emits its click; an option is selected (single) or switched (multiple). A link item is activated by Enter alone.
Enter / Down Arrow (on a handle) Opens the move menu: Move to start, Move before, Move after, Move to end, in the product's words. Choosing one moves the item; focus returns to its handle.
Space (on a handle) Lifts the item. Then the arrow keys of the arrangement move it one place, Home and End to the first and last place, Space or Enter drop it there, and Escape puts it back. Each step is announced.
Escape (while an item is dragged) Puts the item back where it was. Nothing is moved.

備考

  • The list is a box: what an item shows is the product's own content, in a slot. The list owns the arrangement (a column, a line, or lines that wrap into a grid, with a gap and dividers), the semantics (list or listbox, positions and size), keyboard focus among actionable items, selection, and reordering. A row with a headline, supporting text, a leading glyph, picture or control and a trailing value, glyph or control is a List row placed in the item as its direct child: the item tells the row what it is (LST-48) and takes its name from the row's headline (LST-49).
  • Four kinds of item, chosen by props: static (selection none, interactive false, no href) draws nothing of its own — its content is the item — and may hold the product's controls; interactive is one button inside its list item; a link item (href) is one link inside its list item; an option (selection single or multiple) is chosen. The last three are drawn as a padded box with every state and the minimum target; a list may mix static, interactive and link items, and a selectable list holds only options.
  • The list does not scroll or virtualize: the product places it in its own scroll view, or builds it lazily with the platform's lazy list and states the set size where the platform needs it.
  • Reordering meets WCAG 2.2 success criterion 2.5.7 (dragging movements) and 2.1.1 (keyboard) without move buttons on every item: the handle is a button whose menu moves the item to the start, one place before, one place after or to the end — single presses for a pointer, touch, a switch, voice control and a screen reader — and with the keyboard it lifts the item, which the arrow keys carry and Space drops, as in the drag and drop patterns of mature systems (Atlassian's and GitHub's).
  • The whole item can be dragged, not only the handle: a mouse lifts it after a few points of movement, a touch or a pen after a long press (so that a swipe still scrolls) or at once from the handle. The handle is the visible sign that the item can be moved, and the one part that both a pointer and the keyboard can use.
  • The order is the product's data. The list emits move with from and to and draws the items in the order the product then gives; a product that refuses a move changes nothing and the list announces nothing.
  • A reorderable list holds static items only, and is never a listbox: an action, a link or an option is taken by a press that a drag would take. What a reorderable item may hold besides its content: the product's own controls, such as a button that removes the item; the list keeps focus in the list when the item with focus is removed (LST-46).
  • The four move words and the three sentences are the product's, with places to fill. The product writes the sentence, so the order of the words is its language's; the list fills in a name and two numbers and builds no phrase of its own. In a line, the product says "Move left" and "Move right" (or the reverse in a right-to-left language) where a column says "Move up" and "Move down".
  • A wrapping list is still one list in one order: it is read, tabbed through and counted line by line in the reading direction, and a move to another line is a move to another place in that order.
  • WCAG 2.5.8 (target size): for touch every interactive item, link item and option is at least the touch target high in both densities (LST-11). The compact density is lower than the pointer target for a fine pointer, by design: it is the density of a tool used with a mouse, it stays above the 24 by 24 the criterion asks, and its items reach across the list's whole width. A product that cannot accept that uses regular.

生成元 specs/list.spec.json, tokens/sys/measure.tokens.json

コンポーネントが担うこと

  • 選択のないリストはリストとして公開され、各項目は位置とリストの件数を持つリスト項目になります。インタラクティブな項目はリスト項目の中の 1 つのボタン、リンク項目はそこにある 1 つのリンクです。選択できるリストは label で名付けられた、向きを持つリストボックスで、各項目は選択状態を持つオプションです。
  • インタラクティブな項目、リンク、オプションを持つリストは 1 つの Tab 位置です。並べ方に応じた矢印キー(列では上下、行では左右。右から左のレイアウトでは反転し、グリッドでは行をまたぐ方向にも動きます)で、端で折り返さずに項目間を移動します。Home、End、タイプアヘッドも使えます。静的な項目はフォーカスを受けず、その中のコントロールは独自の Tab 位置を保ちます。
  • 並べ替えられるリストでは、各ハンドルはメニューボタンで、dragHandleLabel に項目名を入れた名前と dragHandleHint の説明を持ち、独自の Tab 位置になります。そのメニューは 1 回ずつの押下で項目を動かせるため、ドラッグでできることはドラッグなしでもできるという WCAG の要件(2.5.7)を満たします。Space はキーボードのために項目を持ち上げます(2.1.1)。
  • 1 つの控えめなライブリージョンが、キーボードで項目を持ち上げたこと、1 歩ごとに置かれる位置、移動が反映された後の位置、Escape で元に戻したことを伝えます。
  • ドラッグ中の項目はドラッグ時の塗りと影をまとってポインターについていき、ほかの項目は並べ替えのモーションで道を空けます。モーションを減らす設定では、ポインターの下の項目以外はすべて即座に動きます。強制カラーでは、ドラッグ中の項目はハイライト色で縁取られます。
  • Escape はドラッグ中の項目を元に戻し、リストを含むダイアログまで閉じることはありません。項目を長押ししてもブラウザーのメニューは開きません。
  • インタラクティブな項目、リンク、オプションは最小ターゲット以上の大きさで、フォーカスリングは内側に描かれ、文字が大きくなると項目も大きくなります。
  • デバッグビルドは、名前のない項目、ラベルのない選択できるリストや並べ替えられるリスト、空または重複した値のオプション、どのオプションも指さない選択、インタラクティブな項目やオプションの中のコントロール、誰も指定していない言葉、選択できるリストへの reorderable、リストが定義していない iconSpace を報告します。

プラットフォームの既知の制約:

  • SwiftUI、Compose、Flutter、React Native は以前のリストを提供しており、この改訂の内容はありません。向き、折り返し、間隔、コンテンツのスロット、並べ替えはまだ使えません。

利用者側で行うこと

  • 選択できるリストと並べ替えられるリストには label を付けます。
  • 並べ替えられるリストには、プロダクトの言語で言葉を指定します。指定しないとハンドルは名前のないまま動作し、何も読み上げられません。
  • move が発火したら項目を並べ替えます。リストは何も変えていません。
  • target が new のリンク項目には、「新しいタブで開きます」のような targetLabel を付けます。
  • インタラクティブな項目、リンク、オプションにはコントロールを入れません。自前のコントロールが必要な項目は静的にします。
  • 大量のデータでは自前の遅延リストを作り、プラットフォームが必要とする場合は件数を伝えます。リストはスクロールも仮想化もしません。