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

マーキーテキスト

置かれた場所に収まらない 1 行のテキストです。ふだんは省略記号で切れたまま止まっていて、トリガーが続くあいだは一定の速さで横にスクロールして全体を見せます。テキストがはみ出しているときだけ動き、動きを減らす設定では決して動かず、支援技術には 1 回、全体が読まれます。

content_copyMarkdown で表示
カテゴリ
コミュニケーション
トークン
comp.marquee-text
レベル
基礎

概要

Web
tanrei-marquee-text
clock_loader_40
SwiftUI
TanreiMarqueeText
radio_button_unchecked
Jetpack Compose
TanreiMarqueeText
radio_button_unchecked
Flutter
TanreiMarqueeText
radio_button_unchecked
React Native
MarqueeText
radio_button_unchecked

生成元 docs/status/status.json, specs/marquee-text.spec.json

収まらない曲名と、収まる曲名

トラック 7 — 置かれた行にはとても収まらない、とても長い曲名短い曲名

マーキーテキストは、プロダクトのテキスト 1 行を、それには狭すぎる場所に置くためのものです。止まっているあいだは、ほかの切れた行と同じように読めます。行の始まりから始まり、切れたところで省略記号で終わります。トリガーが続くあいだ(既定では、ポインターが重なっているあいだ、または置かれたコントロールにキーボードフォーカスがあるあいだ)は、ピクセル毎秒で決まる一定の速さで横にスクロールし、テキストのどの部分も一度は見える位置を通ります。そのあと始まりに戻って止まります。上の 1 行目にポインターを重ねてみてください。2 行目は収まっているので、決して動きません。テキストが収まっているマーキーテキストは、ただの 1 行のテキストです。

向いているのは、行の幅が決まっていて、テキストはたいてい短いけれどもときどき長くなる場所です。リスト行のタイトル、ナビゲーションバーやドロワーのラベル、チップ、再生中の曲名、テーブルのセルなどです。ほとんどの場合は切れた行のままで足りるなら、切れたままにして全文をツールチップで見せる方法もあります。ツールチップは全体を一度に見せ、何も動かしません。

使い方

Web と React の例は現在の仕様に沿っています。SwiftUI、Compose、Flutter、React Native は予定段階で、マーキーテキストはまだ提供されていません。

<!-- 既定:ポインターが行か、行が置かれたコントロールに重なっているあいだ、またはそのコントロールにキーボードフォーカスがあるあいだ動きます。 -->
<tanrei-marquee-text>トラック 7 — 置かれた行にはとても収まらない、とても長い曲名</tanrei-marquee-text>

<!-- ホバーやフォーカスのたびに 1 回だけ、終わりまで動いて戻ります。 -->
<tanrei-marquee-text loop="bounce" iterations="1">…</tanrei-marquee-text>

<!-- 再生中の曲名:ひとりでに動き、自分の一時停止ボタンを持ちます。 -->
<tanrei-marquee-text trigger="always" playback-control play-label="流れるテキストを再生" pause-label="流れるテキストを一時停止">
  再生中:とても長い名前のアーティストによる、とても長い曲名
</tanrei-marquee-text>

<script type="module">
  import '@tanrei/web/components/marquee-text';
</script>
import { MarqueeText } from '@tanrei/react';

<MarqueeText>{track.title}</MarqueeText>

<MarqueeText loop="bounce" iterations={1}>{track.title}</MarqueeText>

{/* ひとりでに動きます。ページのあらゆる動きを止めるページ側のコントロールが paused を設定します。 */}
<MarqueeText trigger="always" paused={motionPaused}>
  {`再生中:${track.title}`}
</MarqueeText>

仕様

構成要素

パーツ 説明
1 viewport The line's box: as wide as its place, one line high, clipping the text. While the text moves, its clipped edges fade out.
2 text The product's text, on one line, in the text style of where it stands. At rest it starts at the line's start and ends with an ellipsis where it is cut.
3 copy · 任意 While the text repeats, a second drawing of it a gap after the first, so that the line never empties. Hidden from assistive technology.
4 playback-control · 任意 While the text scrolls by itself all the time, an icon-only Button of the text variant and the small size at the line's end, pausing and playing the motion.

プロパティ

プロパティ 型 既定値 説明
trigger hover-or-focus | hover | focus | always "hover-or-focus" When the text scrolls. hover: while a fine pointer is over the line or the control it stands in. focus: while that control, or something in the line, has keyboard focus. hover-or-focus: either. always: from when the line is shown, by itself, with a way to pause it.
loop repeat | bounce "repeat" How a pass goes. repeat: the text moves toward its start until its end has passed, a copy following it a gap behind, so that the line comes back to where it began. bounce: the text moves until its end is in view, pauses, and moves back.
speed number null How fast the text moves, in pixels per second, so that a long text and a short one move at the same pace. Null takes comp.marquee-text.speed.
startPause number null How long the text rests at its start before each pass, in milliseconds; 0 rests none. Null takes comp.marquee-text.motion.start-pause.
endPause number null While loop is bounce: how long the text rests with its end in view before it moves back, in milliseconds. Null takes comp.marquee-text.motion.end-pause.
iterations number null How many passes a trigger plays before the text rests at its start. Null plays passes without end while the trigger holds: until the pointer leaves or focus moves away for hover, focus and hover-or-focus, and for as long as the line is shown for always.
paused boolean false Holds the motion where it is: set by the playback control, or by the product's own control that pauses every moving part of the page.
playbackControl boolean false While trigger is always: whether the line draws its playback control. Off by default: a product that moves text all the time gives a way to pause it — this control, or its own control that pauses every moving part of the page and sets paused; without either, a person cannot stop the motion, which WCAG 2.2.2 requires of motion that lasts more than five seconds.
playLabel string "" The playback control's accessible name while the motion is paused ("Play scrolling text"). Required while the control is drawn.
pauseLabel string "" The playback control's accessible name while the text moves ("Pause scrolling text"). Required while the control is drawn.

スロット

スロット 説明
default The text: plain text, or inline content of the product's (a bold run, an inline mark). A fixture's string is drawn as plain text.

イベント

イベント 説明
pausedChange The person paused or played the motion with the playback control; carries paused. The product that sets paused emits nothing.

状態

振る舞い

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

ID 要件
MRQ-1 THE marquee text SHALL lay its content out on one line, in the text style, color and direction of where it stands, in a viewport as wide as its place and one line high, and SHALL clip it there; WHILE the content fits, THE marquee text SHALL draw it as plain text, start nothing, draw no copy and no playback control, and be in every way a line of text.
MRQ-2 WHILE the content does not fit and does not move THE marquee text SHALL rest it with its start at the viewport's start, cut at the viewport's end with an ellipsis of the platform's text, so that the line reads as any cut line does.
MRQ-3 WHILE its trigger holds — trigger hover: a fine pointer is over the line or over the nearest element around it that takes presses or focus; focus: that element, or something inside the line, has keyboard focus; hover-or-focus: either; always: the line is shown and in view — and the content does not fit, THE marquee text SHALL wait comp.marquee-text.motion.start-delay (for always, startPause) and then play its passes (MRQ-4, MRQ-5): iterations passes where iterations is not null, and without end while the trigger holds where it is null; after the last pass it SHALL rest as MRQ-2 says. WHEN the trigger ends before the passes do THE marquee text SHALL return the content to its start over comp.marquee-text.motion.return-duration with comp.marquee-text.motion.return-easing and rest; a new trigger SHALL play its passes again from the start.
MRQ-4 WHILE loop is repeat THE marquee text SHALL play a pass by moving the content toward its start edge at speed (comp.marquee-text.speed while speed is null) in pixels per second, steadily, with comp.marquee-text.motion.easing, a copy of the content following it comp.marquee-text.gap behind, until the copy stands where the content began — then the line looks as it did — and SHALL rest there startPause (comp.marquee-text.motion.start-pause while it is null) before the next pass.
MRQ-5 WHILE loop is bounce THE marquee text SHALL play a pass by moving the content toward its start edge at speed until its end stands at the viewport's end, resting there endPause (comp.marquee-text.motion.end-pause while it is null), moving it back at the same speed until its start stands at the viewport's start, and resting there startPause before the next pass; it SHALL draw no copy.
MRQ-6 WHILE the marquee text plays its passes — moving, or resting between two passes — THE marquee text SHALL draw no ellipsis and SHALL fade each edge of the viewport behind which content lies hidden over comp.marquee-text.fade.extent, from clear to the content's full color; WHEN it rests after its passes, or because its trigger ended, it SHALL draw the ellipsis of MRQ-2 again and no fade.
MRQ-7 THE marquee text SHALL move the content in the direction its text is written: toward the left for text whose direction is left to right and toward the right for text whose direction is right to left, the direction being the content's own — the base direction of its first strong character, or the layout direction where it has none — so that the line always moves to bring the text's hidden end into view; it SHALL rest it at the start edge of that direction, cut at the other.
MRQ-8 WHERE motion is reduced THE marquee text SHALL NOT move its content; WHILE a trigger other than always holds it SHALL instead show the hidden part at once, without a motion, by placing the content so that the next viewport's width of it lies in view, the last view ending at the content's end, with the fade of MRQ-6 at each edge behind which content lies hidden, resting startPause on each such view and returning to the start at once after the last, so that every part of the text can be seen; it SHALL go through the views iterations times, or without end while the trigger holds where iterations is null. WHILE trigger is always it SHALL rest as MRQ-2 says and draw no playback control.
MRQ-9 WHILE trigger is always and the content moves THE marquee text SHALL hold its motion where it is while a pointer is over the line or focus is within it, and go on from there when neither is; WHILE paused is true it SHALL hold its motion where it is until paused is false; WHILE the line is out of view or its page is hidden it SHALL hold its motion and start the pass again from the start when it is back. Holding on hover and focus SHALL NOT be taken as the way to stop the motion: that is MRQ-10.
MRQ-10 WHILE trigger is always, playbackControl is true, the content does not fit and motion is not reduced, THE marquee text SHALL draw at the end of its line, comp.marquee-text.playback.gap after the viewport, an icon-only Button of the text variant and the small size, showing the icon set's pause glyph while the text moves and play_arrow while it is paused, named by pauseLabel while it moves and playLabel while it is paused; WHEN the person activates it THE marquee text SHALL toggle paused and emit pausedChange once, keeping focus on the button. WHILE trigger is always, the content does not fit, motion is not reduced and playbackControl is false, THE marquee text SHALL in debug builds report once that the product must give the page a control that sets paused, or set playbackControl (WCAG 2.2.2).
MRQ-11 THE marquee text SHALL expose its content to assistive technology once, whole, as the text it is, read where the line stands, and SHALL hide the copy, the ellipsis and the fade from it; the motion SHALL change nothing it exposes, SHALL make no announcement, and SHALL take no focus: the line itself is not a focus stop.
MRQ-12 WHILE playbackControl would be drawn and playLabel or pauseLabel is empty THE marquee text SHALL read the missing name from the product's words, still draw the control where neither gives it, and in debug builds report that it has no accessible name; THE marquee text SHALL have no words of its own.
MRQ-13 WHILE the text size is enlarged THE marquee text SHALL grow its line with the text and move it at speed times the ratio of its text's size to the size of that text style at the default text size, so that as many characters pass in a second at every text size; the fade and the gap SHALL keep their sizes.
MRQ-14 WHEN the content, the viewport's width or the text size changes THE marquee text SHALL measure again whether the content fits, and WHILE a pass is playing SHALL end it at once and start again from the start where it still does not fit, or rest as MRQ-1 says where it now does; WHEN speed, startPause, endPause, loop or trigger changes it SHALL take the new value from the next pass.
MRQ-15 IF speed is not a positive number, or startPause, endPause or iterations is negative, THE marquee text SHALL treat it as null and in debug builds report it; WHEN trigger or loop names a value the component does not define THE marquee text SHALL use the default value (hover-or-focus, repeat) and in debug builds report the unknown value.
MRQ-16 WHERE the layout direction is right-to-left THE marquee text SHALL place its playback control at the left end of the line, and the content SHALL move and rest by its own direction as MRQ-7 says, whatever the layout direction.
MRQ-17 THE marquee text 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 line is shown THE marquee text SHALL rest at once and draw itself for the new direction.
MRQ-18 WHERE the platform draws with a person's own forced colors THE marquee text SHALL draw its text in the color the platform gives the element around it, and its fade SHALL be no fade: the content is clipped at the viewport's edge.

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

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

仕様 Web SwiftUI Jetpack Compose Flutter React Native
コンポーネント tanrei-marquee-text TanreiMarqueeText TanreiMarqueeText TanreiMarqueeText MarqueeText
trigger · プロパティ trigger trigger trigger trigger trigger
loop · プロパティ loop loop loop loop loop
speed · プロパティ speed speed speed speed speed
startPause · プロパティ startPause startPause startPause startPause startPause
endPause · プロパティ endPause endPause endPause endPause endPause
iterations · プロパティ iterations iterations iterations iterations iterations
paused · プロパティ paused isPaused paused paused paused
playbackControl · プロパティ playbackControl showsPlaybackControl playbackControl playbackControl playbackControl
playLabel · プロパティ playLabel playLabel playLabel playLabel playLabel
pauseLabel · プロパティ pauseLabel pauseLabel pauseLabel pauseLabel pauseLabel
pausedChange · イベント pausedchange isPaused binding onPausedChange onPausedChanged onPausedChange
備考 <tanrei-marquee-text trigger loop speed start-pause end-pause iterations paused playback-control play-label pause-label>text</tanrei-marquee-text>. The slotted text is drawn once; the copy of MRQ-4 is a clone in the shadow root with aria-hidden="true" and inert. Whether the text fits is read with a ResizeObserver on the viewport and when the slotted text changes; the motion of a whole run of passes is one Web Animations API translate animation whose keyframes hold the pauses, each pass's travel lasting the distance divided by speed. The fade is a mask-image gradient. The trigger's area is the nearest ancestor, across shadow roots, that takes presses or focus, and the host where there is none; hover is read from pointerenter and pointerleave of a mouse or a pen, focus from focusin and focusout of an element that matches :focus-visible. The playback control is a <tanrei-button variant="text" size="small"> in the shadow root. The text size of MRQ-13 is the ratio of the browser's default font size (font-size: medium) to 16 px. The element <marquee> is not used: it is deprecated, ignores reduced motion and cannot be paused by the person. A TimelineView(.animation) offset inside a clipped ViewThatFits-measured line; the copy is accessibilityHidden(true); accessibilityReduceMotion from the environment. Not Modifier.basicMarquee alone: it cannot pause, has no bounce, and ignores the motion settings by design (it runs under a fixed motion scale). Built on the same measurement (no motion when the content fits) with an Animatable offset, and reads the animator duration scale for reduced motion. A Ticker-driven offset in a ClipRect; the copy inside ExcludeSemantics; MediaQuery.disableAnimationsOf for reduced motion. An Animated offset on the native driver; the copy with importantForAccessibility="no-hide-descendants" and accessibilityElementsHidden; AccessibilityInfo.isReduceMotionEnabled for reduced motion. hover applies where the platform has a pointer (iPadOS, the web build).

トークン

トークン 参照先 解決値(ライト)
--tanrei-comp-marquee-text-fade-extent sys.space.space200 16px
--tanrei-comp-marquee-text-gap sys.space.space600 48px
--tanrei-comp-marquee-text-motion-easing sys.motion.easing.linear cubic-bezier(0, 0, 1, 1)
--tanrei-comp-marquee-text-motion-end-pause — 1200ms
--tanrei-comp-marquee-text-motion-return-duration sys.motion.role.state.default 250ms
--tanrei-comp-marquee-text-motion-return-easing sys.motion.easing.state cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-marquee-text-motion-start-delay sys.motion.role.show-delay 300ms
--tanrei-comp-marquee-text-motion-start-pause — 1200ms
--tanrei-comp-marquee-text-playback-gap sys.space.space100 8px
--tanrei-comp-marquee-text-speed — 30

フィクスチャ

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

生成元 specs/marquee-text.spec.json, tokens/comp/marquee-text.tokens.json, design/tokens/

ガイドライン

使う場面

行を 1 行のまま、レイアウトが決めた幅に保たなければならず、切れた部分がときどき必要になる場所で使います。プレイリストの行にある長い曲名、言語によって長くなる行き先のラベル、名前を入れたチップなどです。行は高さも位置も変えず、求められたときだけ残りを見せます。

行動するために全文を読む必要があるテキストには使いません。警告、エラー、選択の条件、金額、指示などです。動くテキストは読むのに時間がかかり、見落とされやすいからです。そうしたテキストには必要なだけ行を与え、折り返させます。

トリガーの選び方

トリガー 用途
hover-or-focus 既定で、ほとんどどこでも適した選択です。ポインターを重ねたときにも、置かれたコントロールにキーボードで到達したときにも動くので、どちらの人にも同じものが見えます。
hover キーボードで素早く移動する長いリスト。フォーカスが通るたびに各行のタイトルが動き出すと、役に立つより気が散ります。
focus 主にキーボードやリモコンで操作するサーフェスの行。そこではホバーに意味がありません。
always 再生中の曲名や、ポインターを向けるより目をやるだけの行。表示されたときからひとりでに動くので、止める手段が必要です(アクセシビリティを参照)。

トリガーの範囲は、行だけでなく、行が置かれたコントロール(リスト行、チップ、行き先)です。リスト行のどこにポインターを重ねても、そのタイトルが動きます。ホバーとして数えるのはマウスやペンのような精密なポインターだけで、タッチでは動き始めません。

repeat と bounce

  • repeat(既定)は、テキストの終わりが通り過ぎるまで先頭側へ動かし、そのうしろに隙間を空けてコピーを続けます。行が空になることはなく、始めの状態に戻ります。電光掲示板のように読め、しばらく動く行に向いています。
  • bounce は、テキストの終わりが見えるところまで動かして止め、元に戻します。コピーを描かないので、終わりと始まりが並んで見えることはありません。終わりを一度ちらりと見せるだけの行に向いています。

どちらも、テキストが書かれている方向に動かします。左から右のテキストなら左へ、右から左のテキストなら右へ動き、周りのページの方向には左右されません。

速さと止まる時間

  • speed は 1 回の流れにかかる時間ではなく、ピクセル毎秒で表します。長い曲名も短い曲名も同じ速さで動きます。トークン comp.marquee-text.speed に任せ、プロダクトのどの動く行も同じ速さを保つようにします。文字サイズが大きくなると速さも文字とともに上がり、どの大きさでも 1 秒に通り過ぎる文字の数は同じです。
  • startPause は、毎回の流れの前にテキストが始まりで止まる時間です。始まりを読めるようにするためのものです。trigger="always" では、最初の流れの前の待ち時間でもあります。
  • endPause は、bounce のとき、テキストが終わりを見せたまま止まってから戻るまでの時間です。
  • iterations は、1 回のトリガーで流れを何回繰り返してから始まりで止まるかです。null のままなら、ポインターが離れるかフォーカスが移るまで、always なら行が表示されているあいだずっと繰り返します。動きを短く収める回数を設定することが、ホバーやフォーカスのトリガーをアクセシブルにします(後述)。

止まる時間は読むための時間です。アニメーションを速めたり遅くしたりするプロダクトのモーション設定は、これを短くしません。

文言

テキストは、動くところを見る必要がめったにない長さにとどめます。マーキーはほかより長いときどきの曲名のためのもので、文をチップに収める手段ではありません。項目どうしを見分ける語は、動かなくても読める始まりに置きます。テキストには太字の部分のようなインラインの内容も入れられますが、常に 1 行です。

推奨

  • 行は、人がポインターを重ねたりフォーカスしたりするコントロールの中に置き、トリガーの範囲がリスト行全体になるようにします。
  • iterations を設定し、ホバーやフォーカスのたびに短く流れて止まるようにします。
  • trigger="always" の行には止める手段を用意します。行自身の再生コントロールか、ページのあらゆる動きを止めるプロダクト側のコントロールです。

非推奨

  • 行動するために全文を読む必要があるテキストに使わない。そのテキストには専用の行を与えます。
  • 常に動く行を 1 つの画面にいくつも置かない。動く行は 1 本でも目を引きます。何本もあると、互いに、また画面のほかのすべてと競い合います。
  • 動きを始めるために、行そのものをボタンやリンクにしない。行はテキストで、人が押すのは周りのコントロールです。
  • 長いテキストを短い流れに収めるために止まる時間を縮めない。テキストを短くするか、別の方法で全体を見せます。

アクセシビリティ

ロール
none (text)
ラベル付け
The text is read once, whole, as text; the copy is hidden. The playback control is named by pauseLabel and playLabel, from the instance and then the product's words.
最小ターゲット
見た目のサイズが小さくても、ヒット領域は最小ターゲットサイズを満たします。 minimum 32px · pointer 44px · spacing 8px · touch 48px

キーボード操作

キー 動作
Tab Reaches the playback control while it is drawn; the line itself is not a stop. Focus on the control the line stands in (a row, a chip) starts the motion for trigger focus and hover-or-focus, and moving focus away stops it.
Enter / Space on the playback control Pauses or plays the motion.

備考

  • Pause, Stop, Hide (WCAG 2.2.2): motion that starts without a person's direct action and lasts more than five seconds beside other content needs a way to pause, stop or hide it, and the Understanding document counts motion started by a hover, a focus or scrolling into view, and stopped only while focused, as not meeting that. The defaults can conflict with it: trigger always draws no playback control (playbackControl is false), and a hover or a focus plays passes until it ends (iterations is null). A product meets it by drawing the playback control or binding its page-wide pause control to paused for trigger always, and by setting iterations so that the motion a hover or a focus starts ends within five seconds, or by keeping such lines where nothing else is read beside them.
  • Animation from interactions (WCAG 2.3.3): where motion is reduced, the line never moves; the hidden part is still shown, a viewport at a time, without a motion (MRQ-8).
  • The minimum target is the playback control's, a Button's; the line takes no input of its own.

生成元 specs/marquee-text.spec.json, tokens/sys/measure.tokens.json

既定のままでは WCAG 2.2.2 に反することがある

Pause, Stop, Hide(WCAG 2.2.2、レベル A)は、ひとりでに始まり、5 秒より長く続き、ほかのコンテンツと並んで表示される動きを、その人が一時停止、停止、または非表示にできることを求めています。Tanrei の既定はそれだけではこれを満たしません。次の 2 点で満たさず、どう満たすかはプロダクト側が決めます。

  1. trigger="always" は既定で再生コントロールを描きません(playbackControl は false)。ほかのコンテンツと並んで 5 秒より長く動き続ける行には、止める手段が必要です。playbackControl を設定すると、行の末尾にアイコンだけの一時停止・再生ボタンが描かれ、pauseLabel と playLabel、またはプロダクトの言葉 marqueePauseLabel と marqueePlayLabel で名前が付きます。あるいは、ページのあらゆる動きを止めるプロダクト側のコントロールを paused に結び付けます。どちらもないまま動き続ける行は、デバッグビルドで報告されます。
  2. hover、focus、hover-or-focus では、iterations が null のとき、ポインターが離れるかフォーカスが移るまで流れを繰り返します。 WCAG の Understanding 文書は、ホバーやフォーカスで始まる動きをひとりでに始まる動きとして数え、フォーカスが離れたときにしか止まらない動きは止める手段にならないとしています。2.2.2 を満たすには、動きが 5 秒以内に終わるように iterations を設定します。長いテキストでは 1 回の流れだけで 5 秒を超えることがあります。その場合はテキストを短くするか速さを上げるか、別の方法で全文を見せます。

行は、ポインターが重なっているあいだやフォーカスが内側にあるあいだ、また画面の外にあるあいだやページが隠れているあいだ、動きをその場で保ちます。読みやすくはなりますが、止める手段ではありません。

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

  • テキストが収まらないときだけ動きます。テキストが収まる行はただのテキストを描き、何も始めません。
  • 動きを減らす設定(WCAG 2.3.3)では決して動きません。ホバーやフォーカスでは、隠れた部分をビューポート 1 つ分ずつ、動きなしで見せ、それぞれで止まるので、テキストのどの部分も見られます。trigger="always" の行は切れたまま止まり、再生コントロールを描きません。
  • 支援技術は、行が置かれた位置で、テキストを 1 回、全体を、テキストとして読みます。コピー、省略記号、フェードは支援技術から隠され、動きは読まれる内容を何も変えず、何も読み上げさせません。
  • 行はフォーカスが止まる位置ではありません。Tab で到達するのは行が置かれたコントロールと、描かれているあいだの再生コントロールです。
  • 再生コントロールは text バリアント、small サイズのボタンで、テキストが動いているあいだはアイコンセットの一時停止のグリフ、止まっているあいだは再生のグリフを表示します。Enter または Space で切り替わり、フォーカスはボタンにとどまり、pausedChange を発火します。ターゲットは最小ターゲットを満たします。
  • 右から左のレイアウトでは、再生コントロールは行の左端に置かれます。テキストは自分の方向に従って動きます。
  • 強制カラーモードでは、テキストはプラットフォームが周りの要素に与える色になり、端はフェードせずに切り取られます。
  • コンポーネントは自分の言葉を持ちません。インスタンスからもプロダクトの言葉からも名前が得られない再生コントロールは、それでも描かれ、デバッグビルドで報告されます。未知の trigger や loop、範囲外の速さ、止まる時間、回数も同じく報告されます。

Web のコンポーネントは HTML の <marquee> 要素ではありません。この要素は非推奨で、動きを減らす設定を無視し、その人が一時停止できません。

利用者側で行うこと

  • 上のとおり WCAG 2.2.2 を満たします。trigger="always" のすべての行に止める手段を用意し、ホバーやフォーカスで始まる動きが 5 秒以内に終わる iterations を設定します。
  • 再生コントロールの 2 つの名前を、インスタンスで、またはプロダクトの言葉で一度だけ、ページの言語で与えます。「流れるテキストを一時停止」「流れるテキストを再生」のように、ボタンが何をするかを言います。
  • 全文を読む必要があるテキストはマーキーに入れません。切れた行は、動きを起こさない人にはその部分を隠したままです。
  • 常に動く行は 1 つの画面に 1 本までにし、人が読んでいる長いテキストの横には置きません。