---
title: "النص المتحرك"
description: "سطر واحد من النص لا يتسع له مكانه. في السكون يُقصّ وينتهي بعلامة حذف، وما دام محفِّزه قائمًا يُمرَّر جانبيًّا بوتيرة ثابتة ليُظهر نفسه كله. لا يتحرك إلا حين يفيض النص، ولا يتحرك أبدًا حيث تُقلَّل الحركة، ويُقرأ مرة واحدة، كاملًا."
url: "https://tanrei.chnotchy.com/ar/components/marquee-text/"
last_updated: 2026-10-23T21:17:12.000Z
---

# النص المتحرك

> سطر واحد من النص لا يتسع له مكانه. في السكون يُقصّ وينتهي بعلامة حذف، وما دام محفِّزه قائمًا يُمرَّر جانبيًّا بوتيرة ثابتة ليُظهر نفسه كله. لا يتحرك إلا حين يفيض النص، ولا يتحرك أبدًا حيث تُقلَّل الحركة، ويُقرأ مرة واحدة، كاملًا.

## نظرة عامة

النص المتحرك (marquee) سطر واحد من نص المنتج في مكان أضيق منه. في السكون يُقرأ كأي سطر مقصوص: يبدأ عند بداية السطر وينتهي بعلامة حذف (…) حيث يُقصّ. وما دام محفِّزه قائمًا، وهو افتراضيًّا مرور المؤشر فوقه أو تركيز لوحة المفاتيح على عنصر التحكم الذي يقع فيه، يُمرَّر جانبيًّا بوتيرة ثابتة تُعطى بالبكسل في الثانية، فيمرّ كل جزء من النص في المنظر؛ ثم يعود إلى بدايته ويسكن. مرِّر المؤشر فوق السطر الأول أعلاه. أما الثاني فيتسع، ولذلك لا يتحرك أبدًا: النص المتحرك الذي يتسع نصه سطر نص عادي.

يناسب الأماكن التي يكون فيها عرض السطر ثابتًا ونصه قصيرًا في الغالب، لكنه أحيانًا ليس كذلك: عنوان في صف القائمة، وتسمية في شريط التنقل أو في درج التنقل، والرقاقة، واسم ما يُشغَّل الآن، وخلية في جدول. وحيث يكفي السطر المقصوص في معظم الأحيان، فالخيار الآخر أن يُترك مقصوصًا ويُعطى النص كاملًا في [التلميح](https://tanrei.chnotchy.com/ar/components/tooltip/)، الذي يُظهره كله دفعة واحدة ولا يحرّك شيئًا.

### الاستخدام

عيّنتا Web و React تعرضان المواصفة الحالية. أما SwiftUI و Compose و Flutter و React Native فمخطَّط لها: لا تقدّم نصًّا متحركًا بعد.

**Web**

```html
<!-- الافتراضي: يتحرك ما دام المؤشر فوق السطر أو فوق عنصر التحكم الذي يقع فيه، أو ما دام ذلك العنصر يتلقى تركيز لوحة المفاتيح. -->
<tanrei-marquee-text>المقطع 7: عنوان طويل جدًّا لا يتسع له الصف الذي يقع فيه</tanrei-marquee-text>

<!-- يمضي إلى نهايته ويعود، مرة واحدة لكل تحويم أو تركيز. -->
<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>
```

**React**

```tsx
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>
```

## المواصفات

- Category: Communication
- Level: base
- Listing: default
- Page: https://tanrei.chnotchy.com/components/marquee-text/
- Spec: https://github.com/chnotchy/tanrei/blob/main/specs/marquee-text.spec.json

### Availability

| Design system | Has it | Notes |
| --- | --- | --- |
| Tanrei (`tanrei`) | Yes | — |
| Cupertino (Apple HIG-inspired) (`cupertino`) | Yes | — |
| M3 Expressive-like (Material 3 Expressive-inspired) (`m3-expressive-like`) | Yes | — |
| M3-like (Material 3-inspired) (`m3-like`) | Yes | — |

### Platforms

- Web: the element `<tanrei-marquee-text>`, registered by importing `@tanrei/web` (or only its own module, `@tanrei/web/components/marquee-text`).
- React: `MarqueeText` from `@tanrei/react`.

| Platform | Name | Status |
| --- | --- | --- |
| Web | `tanrei-marquee-text` | alpha |
| SwiftUI | `TanreiMarqueeText` | planned |
| Jetpack Compose | `TanreiMarqueeText` | planned |
| Flutter | `TanreiMarqueeText` | planned |
| React Native | `MarqueeText` | planned |

Names a platform gives in its own idiom:

| Spec | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
| --- | --- | --- | --- | --- | --- |
| `paused` (prop) | `paused` | `isPaused` | `paused` | `paused` | `paused` |
| `playbackControl` (prop) | `playbackControl` | `showsPlaybackControl` | `playbackControl` | `playbackControl` | `playbackControl` |
| `pausedChange` (event) | `pausedchange` | `isPaused binding` | `onPausedChange` | `onPausedChanged` | `onPausedChange` |

Statuses: `planned` — In the inventory. Nothing shippable exists yet. `lagging` — An implementation of an earlier spec exists; it has not caught up with the current one. `alpha` — Implemented with tests. The API may still change. `beta` — Feature complete and at parity. Only fixes are expected. `stable` — Covered by semantic versioning. `deprecated` — Still shipped; scheduled for removal.

### Anatomy

- `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.
- `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.
- `copy` (optional): While the text repeats, a second drawing of it a gap after the first, so that the line never empties. Hidden from assistive technology.
- `playback-control` (optional): 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.

### Props

| Prop | Type | Default | Web attribute | Description |
| --- | --- | --- | --- | --- |
| `trigger` | `enum`: `hover-or-focus`, `hover`, `focus`, `always` | `"hover-or-focus"` | `trigger` | 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` | `enum`: `repeat`, `bounce` | `"repeat"` | `loop` | 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` | — | `speed` | 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` | — | `start-pause` | 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` | — | `end-pause` | 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` | — | `iterations` | 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` | `paused` | 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` | `playback-control` | 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` | `""` | `play-label` | The playback control's accessible name while the motion is paused ("Play scrolling text"). Required while the control is drawn. |
| `pauseLabel` | `string` | `""` | `pause-label` | The playback control's accessible name while the text moves ("Pause scrolling text"). Required while the control is drawn. |

### Events

| Event | Description |
| --- | --- |
| `pausedChange` | The person paused or played the motion with the playback control; carries paused. The product that sets paused emits nothing. |

### Slots

| Slot | Description |
| --- | --- |
| `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. |

### States

`enabled`

### Accessibility

- Role: `none (text)`
- Labeling: 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 target size: yes

| Keys | Action |
| --- | --- |
| 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 or 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.

### Behaviour

Requirements in EARS form, each with its stable 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.

### Tokens

As written in the token documents (DTCG): an alias in braces names the token it takes its value from, which each design system resolves. On the web each token is a CSS custom property: `--tanrei` and the name after `tanrei`, joined by hyphens (`tanrei.comp.marquee-text.…` → `--tanrei-comp-marquee-text-…`).

#### `tanrei.comp.marquee-text`

| Token | Type | Value |
| --- | --- | --- |
| `comp.marquee-text.speed` | `number` | `30` |
| `comp.marquee-text.gap` | `dimension` | `{tanrei.sys.space.space600}` |
| `comp.marquee-text.fade.extent` | `dimension` | `{tanrei.sys.space.space200}` |
| `comp.marquee-text.playback.gap` | `dimension` | `{tanrei.sys.space.space100}` |
| `comp.marquee-text.motion.start-pause` | `duration` | `1200ms` |
| `comp.marquee-text.motion.end-pause` | `duration` | `1200ms` |
| `comp.marquee-text.motion.start-delay` | `duration` | `{tanrei.sys.motion.role.show-delay}` |
| `comp.marquee-text.motion.easing` | `cubicBezier` | `{tanrei.sys.motion.easing.linear}` |
| `comp.marquee-text.motion.return-duration` | `duration` | `{tanrei.sys.motion.role.state.default}` |
| `comp.marquee-text.motion.return-easing` | `cubicBezier` | `{tanrei.sys.motion.easing.state}` |

## الإرشادات

### متى يُستخدم

استخدم النص المتحرك حيث يجب أن يبقى السطر سطرًا واحدًا، بعرض يحدده التخطيط، ويحتاج الشخص أحيانًا إلى الجزء المقصوص: اسم أغنية طويل في صف من قائمة تشغيل، وتسمية وجهة تطيلها لغة ما، ورقاقة تحمل اسمًا. يحتفظ السطر بارتفاعه ومكانه، ولا يُظهر بقيته إلا حين يُطلب منه ذلك.

لا تستخدمه لنص يجب أن يقرأه الشخص كاملًا ليتصرف: تحذير، أو خطأ، أو شروط اختيار، أو مبلغ، أو تعليمات. فالنص المتحرك بطيء القراءة وسهل الإغفال. أعطِ هذا النص الأسطر التي يحتاج إليها، ودعه يلتفّ.

### اختيار المحفِّز

| المحفِّز | يُستخدم لـ |
| --- | --- |
| `hover-or-focus` | الافتراضي، والاختيار الصحيح في كل مكان تقريبًا: يتحرك السطر حين يشير إليه الشخص بالمؤشر أو يصل بلوحة المفاتيح إلى عنصر التحكم الذي يقع فيه، فيرى الاثنان الشيء نفسه. |
| `hover` | قائمة طويلة يتنقل فيها مستخدمو لوحة المفاتيح بسرعة، حيث يشتّت تحرّكُ عنوان كل صف عند مرور التركيز به أكثر مما يفيد. |
| `focus` | سطر في سطح يُستخدم غالبًا بلوحة المفاتيح أو بجهاز التحكم عن بُعد، حيث لا معنى للتحويم. |
| `always` | اسم ما يُشغَّل الآن، وأسطر مثله يلقي الشخص عليها نظرة ولا يشير إليها. يتحرك وحده منذ يُعرض، ويحتاج إلى طريقة لإيقافه مؤقتًا (انظر «إمكانية الوصول»). |

نطاق المحفِّز هو عنصر التحكم الذي يقع فيه السطر (صف، أو رقاقة، أو وجهة)، لا السطر وحده: وضع المؤشر في أي موضع من الصف يحرّك عنوانه. ولا يُحسب تحويمًا إلا المؤشر الدقيق، كالفأرة أو القلم؛ واللمس لا يبدأ الحركة.

### الحركتان repeat و bounce

- **القيمة `repeat`** (الافتراضية) تحرّك النص نحو بدايته حتى تمرّ نهايته، وتتبعه نسخة على مسافة منه، فلا يفرغ السطر أبدًا ويعود كما بدأ. يُقرأ كشريط الأخبار، ويناسب سطرًا يتحرك مدة من الوقت.
- **القيمة `bounce`** تحرّك النص حتى تظهر نهايته، وتسكن هناك، ثم تعيده. لا ترسم نسخة، فلا تُرى النهاية والبداية متجاورتين أبدًا. وتناسب سطرًا يتحرك مرة واحدة، لنظرة قصيرة إلى نهايته.

كلتاهما تحرّك النص في الاتجاه الذي كُتب به: نحو اليسار للنص المكتوب من اليسار إلى اليمين، ونحو اليمين للنص المكتوب من اليمين إلى اليسار، أيًّا كان اتجاه الصفحة حوله.

### السرعة والتوقفات

- **الخاصية `speed`** بالبكسل في الثانية، لا بزمن دورة كاملة، فيتحرك العنوان الطويل والقصير بالوتيرة نفسها. اتركها للرمز `comp.marquee-text.speed`، لكي تحافظ كل الأسطر المتحركة في المنتج على وتيرة واحدة. وحين يُكبَّر حجم النص تكبر السرعة معه، فيمرّ العدد نفسه من الأحرف في الثانية بكل حجم.
- **الخاصية `startPause`** هي مدة سكون النص عند بدايته قبل كل دورة، لكي تُقرأ بدايته. ومع `trigger="always"` هي أيضًا الانتظار قبل الدورة الأولى.
- **الخاصية `endPause`**، مع `bounce`، هي مدة سكون النص ونهايته ظاهرة قبل أن يعود.
- **الخاصية `iterations`** هي عدد الدورات التي يشغّلها المحفِّز الواحد قبل أن يسكن النص عند بدايته. وإن تُركت null استمرت الدورات حتى يبتعد المؤشر أو ينتقل التركيز، ومع `always` ما دام السطر معروضًا. والعدد الذي يُبقي الحركة قصيرة هو ما يجعل محفِّز التحويم أو التركيز متاحًا (أدناه).

التوقفات أوقات قراءة. وإعدادات الحركة في المنتج، التي تسرّع الرسوم المتحركة أو تبطئها، لا تقصّرها.

### المحتوى النصي

اجعل النص قصيرًا بما يكفي لكي لا يحتاج الناس إلى رؤيته يتحرك إلا نادرًا: النص المتحرك للعنوان العارض الأطول من غيره، لا وسيلة لحشر جملة في رقاقة. ضع في البداية ما يميّز العناصر بعضها من بعض، حيث يُقرأ بلا حركة. يمكن أن يحوي النص محتوى مضمَّنًا، كجزء بخط غامق؛ وهو سطر واحد دائمًا.

### افعل

- ضع السطر داخل عنصر التحكم الذي يشير إليه الشخص أو يركّز عليه، لكي يكون نطاق المحفِّز الصف كله.
- اضبط `iterations` لكي يشغّل كل تحويم أو تركيز دورة قصيرة ثم يتوقف.
- أعطِ السطر ذا `trigger="always"` طريقة لإيقافه مؤقتًا: عنصر التحكم في التشغيل الخاص به، أو عنصر التحكم في المنتج الذي يوقف كل ما يتحرك في الصفحة.

### لا تفعل

- لا تستخدمه لنص يجب أن يقرأه الشخص كاملًا ليتصرف. أعطِ هذا النص أسطره الخاصة.
- لا تضع في شاشة واحدة عدة أسطر تتحرك طوال الوقت. فسطر واحد متحرك يجذب العين؛ وعدة أسطر تتنافس فيما بينها ومع كل ما في الشاشة.
- لا تجعل السطر نفسه زرًّا أو رابطًا لبدء الحركة. إنه نص؛ وما يضغطه الشخص هو عنصر التحكم المحيط به.
- لا تقصّر التوقفات لكي يتسع نص طويل لدورة قصيرة. قصّر النص، أو اعرضه كاملًا بطريقة أخرى.

## إمكانية الوصول

### قد تتعارض القيم الافتراضية مع WCAG 2.2.2

يطلب المعيار [Pause, Stop, Hide](https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html) (WCAG 2.2.2، المستوى A) أن تكون الحركة التي تبدأ وحدها وتدوم أكثر من خمس ثوانٍ وتُعرض بجانب محتوى آخر قابلة لأن يوقفها الشخص مؤقتًا أو يوقفها أو يخفيها. وقيم Tanrei الافتراضية لا تفي به وحدها، من وجهين، والمنتج هو الذي يقرر كيف يفي به.

1. **مع `trigger="always"` لا يُرسم عنصر التحكم في التشغيل افتراضيًّا** (`playbackControl` قيمتها false). والسطر الذي يتحرك طوال الوقت أكثر من خمس ثوانٍ بجانب محتوى آخر يحتاج إلى طريقة لإيقافه مؤقتًا. فإما أن تضبط `playbackControl`، فيرسم السطر في نهايته زر إيقاف مؤقت وتشغيل بأيقونة وحدها، اسمه من `pauseLabel` و `playLabel` أو من كلمات المنتج `marqueePauseLabel` و `marqueePlayLabel`؛ وإما أن تربط بالخاصية `paused` عنصر التحكم الخاص بالمنتج الذي يوقف كل ما يتحرك في الصفحة. وتُبلِّغ بنيات التنقيح (debug) عن سطر يتحرك طوال الوقت بلا أيٍّ منهما.
2. **مع `hover` و `focus` و `hover-or-focus`، إذا كانت `iterations` قيمتها null، تستمر الدورات حتى يبتعد المؤشر أو ينتقل التركيز.** ووثيقة Understanding الخاصة بمعايير WCAG تعدّ الحركة التي يبدأها التحويم أو التركيز حركة تبدأ تلقائيًّا، وتقول إن الحركة التي لا تتوقف إلا حين يغادر التركيز ليست وسيلة لإيقافها. وللوفاء بالمعيار 2.2.2 اضبط `iterations` بحيث تنتهي الحركة في خمس ثوانٍ أو أقل. وفي النص الطويل قد تستغرق دورة واحدة أكثر من ذلك: قصّر النص أو ارفع السرعة، أو اعرض النص كاملًا بطريقة أخرى.

يُبقي السطر حركته في موضعها ما دام المؤشر فوقه أو التركيز داخله، وما دام خارج المنظر أو صفحته مخفية. وهذا يسهّل قراءته، لكنه ليس وسيلة لإيقافه.

### ما يتكفل به المكوّن

- لا يتحرك إلا حين لا يتسع النص. والسطر الذي يتسع نصه يرسم نصًّا عاديًّا ولا يبدأ شيئًا.
- حيث يُطلب تقليل الحركة (WCAG 2.3.3) لا يتحرك أبدًا. وعند التحويم أو التركيز يُظهر الجزء المخفي بقدر عرض السطر في كل مرة، بلا حركة، ويسكن عند كل منظر، لكي يبقى كل جزء من النص قابلًا للرؤية؛ والسطر ذو `trigger="always"` يسكن مقصوصًا ولا يرسم عنصر التحكم في التشغيل.
- تقرأ التقنيات المساعدة النص مرة واحدة، كاملًا، نصًّا، حيث يقع السطر. والنسخة وعلامة الحذف والتلاشي مخفية عنها، والحركة لا تغيّر شيئًا مما تقرؤه ولا تُعلِن شيئًا.
- السطر ليس موضع توقف للتركيز. يصل المفتاح Tab إلى عنصر التحكم الذي يقع فيه السطر، وإلى عنصر التحكم في التشغيل ما دام مرسومًا.
- عنصر التحكم في التشغيل زر من الطراز text والحجم small، يعرض رسم الإيقاف المؤقت من مجموعة الأيقونات ما دام النص يتحرك، ورسم التشغيل ما دام موقوفًا مؤقتًا. يبدّله المفتاح Enter أو Space، ويبقى التركيز عليه، ويُطلق `pausedChange`. وهدفه يفي بالحد الأدنى للهدف.
- في التخطيط من اليمين إلى اليسار يقع عنصر التحكم في التشغيل عند الطرف الأيسر من السطر؛ ويتحرك النص بحسب اتجاهه هو.
- في الألوان المفروضة (forced colors) يأخذ النص اللون الذي تعطيه المنصة للعنصر المحيط به، وتُقصّ حوافه بدل أن تتلاشى.
- ليست له كلمات خاصة به. وعنصر التحكم في التشغيل الذي لا يجد اسمًا في النسخة ولا في كلمات المنتج يُرسم مع ذلك ويُبلَّغ عنه في بنيات التنقيح؛ وكذلك يُبلَّغ عن قيمة `trigger` أو `loop` غير معروفة، وعن سرعة أو توقف أو عدد خارج النطاق.

مكوّن الويب ليس العنصر `<marquee>` في HTML. فهذا العنصر [مهمَل](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/marquee)، ويتجاهل تقليل الحركة، ولا يستطيع الشخص إيقافه مؤقتًا.

### ما عليك فعله

- أوفِ بالمعيار WCAG 2.2.2 كما سبق: طريقة لإيقاف كل سطر ذي `trigger="always"` مؤقتًا، وعدد في `iterations` ينهي الحركة التي يبدأها التحويم أو التركيز في خمس ثوانٍ أو أقل.
- أعطِ عنصر التحكم في التشغيل اسميه، في النسخة أو مرة واحدة في كلمات المنتج، بلغة الصفحة: «إيقاف النص المتحرك مؤقتًا» و«تشغيل النص المتحرك» يقولان ما يفعله الزر.
- لا تضع في النص المتحرك نصًّا يجب أن يُقرأ كاملًا: فالسطر المقصوص يخفيه عمّن لا يبدأ الحركة أبدًا.
- اكتفِ بسطر واحد يتحرك طوال الوقت في الشاشة، ولا تضعه بجانب نص طويل يقرؤه الشخص.
