شريط التمرير
يتيح للأشخاص اختيار قيمة، أو مدى من القيم، بسحب مقبض على طول مسار، باستمرار أو على درجات.
- الفئة
- الاختيار
- الرموز
comp.slider- المستوى
- أساسي
- يُستخدم في
- Slider field
- Web
tanrei-sliderschedule - SwiftUI
TanreiSliderschedule - Jetpack Compose
TanreiSliderschedule - Flutter
TanreiSliderschedule - React Native
Sliderschedule
مولَّد من docs/status/status.json, specs/slider.spec.json
مستمر، ومدرَّج مع نقاط توقف، ومدى
ساحة التجربة
يختار شريط التمرير قيمة واحدة بين min و max (0 و 100 افتراضيًّا). ومع الخاصية range يكون له مقبضان ويختار الامتداد من startValue إلى value. القيمة 0 للخاصية step تعني الاستمرار؛ وفوق 0 تنجذب القيم إلى min مضافًا إليه مضاعفات صحيحة من step.
لا يرسم شريط التمرير تسمية. الخاصية label تسمّيه للتقنيات المساعدة، والتسمية المرئية نص من عندك بجانب شريط التمرير، بالكلمات نفسها. والمدى يحتاج إلى الخاصية startLabel لمقبض بدايته أيضًا.
حدثان يبلّغان عن التغيّر. يصدر الحدث input مع كل تغيّر ما دام الشخص يسحب، ويصدر الحدث change مرة واحدة حين ينتهي التغيّر: انتهى الضغط، أو ضُغط مفتاح، أو أُجري تعديل من تقنية مساعدة. والقيمة التي تعيّنها أنت لا تُصدر أيًّا منهما. وكل منصة تسمّيهما بطريقتها: onValueChange و onValueChangeFinished على Compose، و onChanged و onChangeEnd على Flutter، و onValueChange و onSlidingComplete على React Native، وعلى SwiftUI الربط (binding) و onCommit.
المراجعة التي أعطت شريط التمرير مقبضه المستدير، والمراجعة التي جعلت حلقته أثقل، لم تغيّرا إلا مظهره، فكل العيّنات أدناه سارية. يرسم الويب المظهر الحالي. أما SwiftUI و Compose و Flutter و React Native فمتأخرة: ما زالت ترسم المظهر السابق، وهو مقبض مستدير مصمت مع مسارين مقطوعين عند حافته ومقاس واحد لنقاط التوقف في كل الأحجام، إلى أن تلحق.
<!-- لا يرسم شريط التمرير تسمية: ضع تسميتك المرئية بجانبه، بالكلمات نفسها. -->
<tanrei-slider name="volume" label="مستوى الصوت" value="40" value-indicator="active"></tanrei-slider>
<!-- مدرَّج، مع نقطة عند كل درجة. -->
<tanrei-slider label="السطوع" value="30" step="10" stops></tanrei-slider>
<!-- المدى يرسل start-value ثم value تحت الاسم نفسه. -->
<tanrei-slider name="price" range min="0" max="500" step="10" start-value="100" value="300"
label="أعلى سعر" start-label="أدنى سعر"></tanrei-slider>
<script type="module">
import '@tanrei/web/components/slider';
const volume = document.querySelector('[name="volume"]');
// يعيّن العنصر قيمته بنفسه قبل أن يُصدر input و change.
volume.addEventListener('input', () => preview(volume.value));
volume.addEventListener('change', () => save(volume.value));
</script>import { Slider } from '@tanrei/react';
<Slider
label="مستوى الصوت"
value={volume}
valueIndicator="active"
onInput={(e) => setVolume(e.currentTarget.value)}
onChange={(e) => save(e.detail.value)}
/>
<Slider
range
min={0}
max={500}
step={10}
startValue={minPrice}
value={maxPrice}
label="أعلى سعر"
startLabel="أدنى سعر"
onInput={(e) => setPrices(e.currentTarget.startValue, e.currentTarget.value)}
/>import Tanrei
// كل تغيّر يكتب في الربط؛ و onCommit تعمل حين ينتهي التغيّر.
TanreiSlider("مستوى الصوت", value: $volume, in: 0...100, onCommit: save)
TanreiSlider("السطوع", value: $brightness, in: 0...100, step: 10)
// المدى هو المُهيِّئ الذي ربطه من النوع ClosedRange: والقيمة lowerBound هي مقبض البداية.
TanreiSlider("أعلى سعر", startLabel: "أدنى سعر", value: $prices, in: 0...500, step: 10)import io.github.chnotchy.tanrei.components.TanreiSlider
// رفع الحالة: حرِّك value من onValueChange.
TanreiSlider(
value = volume,
onValueChange = { volume = it },
contentDescription = "مستوى الصوت",
onValueChangeFinished = ::save, // تحمل القيمة، بخلاف نظيرتها في foundation
)
// step مقدار، لا عدد الدرجات كما في Material.
TanreiSlider(value = brightness, onValueChange = { brightness = it }, step = 10f, contentDescription = "السطوع")
// المدى هو الصيغة التي قيمتها من النوع ClosedFloatingPointRange.
TanreiSlider(
value = prices,
onValueChange = { prices = it },
valueRange = 0f..500f,
step = 10f,
contentDescription = "أعلى سعر",
startContentDescription = "أدنى سعر",
)import 'package:tanrei/tanrei.dart';
TanreiSlider(
value: volume,
onChanged: (double value) => setState(() => volume = value), // القيمة null تعطّله
onChangeEnd: save,
semanticLabel: 'مستوى الصوت',
);
// step مقدار، لا divisions كما في Material.
TanreiSlider(value: brightness, step: 10, onChanged: (double value) => setState(() => brightness = value), semanticLabel: 'السطوع');
TanreiSlider.range(
start: minPrice,
end: maxPrice,
max: 500,
step: 10,
onChanged: (double start, double end) => setState(() {
minPrice = start;
maxPrice = end;
}),
semanticLabel: 'أعلى سعر',
startSemanticLabel: 'أدنى سعر',
);import { Slider } from '@tanrei/react-native';
<Slider value={volume} onValueChange={setVolume} onSlidingComplete={save} accessibilityLabel="مستوى الصوت" />
<Slider value={brightness} step={10} stops onValueChange={setBrightness} accessibilityLabel="السطوع" />
// مدى: الدالتان كلتاهما تستقبلان (value, startValue).
<Slider
range
minimumValue={0}
maximumValue={500}
step={10}
startValue={minPrice}
value={maxPrice}
onValueChange={(value, startValue) => setPrices(startValue, value)}
accessibilityLabel="أعلى سعر"
startAccessibilityLabel="أدنى سعر"
/>الأحجام، والتوسيط، ومؤشر القيمة، والاتجاه العمودي، والتعطيل
في النظام الافتراضي المقبض حلقة: دائرة بمقاس 20 معبَّأة بلون السطح، داخل حدّ بلون المسار النشط. عرض الحدّ 3 ويُرسم داخل حافة الدائرة، فلا يغيّر مقاس المقبض: يترك قرصًا بمقاس 14 بلون السطح، والحدّ الأعرض يترك قرصًا أصغر. يمرّ المسار والمسار النشط تحت المقبض ويلتقيان عند مركزه، فيُقرأ المسار النشط خطًّا واحدًا ينتهي في الحلقة. ومقاس المقبض 20 في كل الأحجام، على مسارات بثخانة 4 و 6 و 8.
نقاط التوقف، والنقطة التي تعلّم نهاية مسافة الحركة، ثخانتها نصف ثخانة المسار: 2 و 3 و 4 في الأحجام small و medium و large. ويقع مؤشر القيمة فوق أعلى الحلقة بقليل، موسَّطًا عليها. وفي حالة التعطيل تحتفظ الحلقة بتعبئتها، ويبهت حدّها مع المسار النشط.
يستطيع نظام التصميم أن يرسم المقبض بطريقته من الرموز (tokens) نفسها. مع حدّ عرضه 0 يكون المقبض شكلًا مصمتًا، ومع فجوة بين المسارين والمقبض يتوقف المساران دونه ويُدوَّران هناك. وهكذا يرسم النظام m3-like شريط Material القائم.
البنية
البنية
continuous كما ترسمه حزمة الويب.| الجزء | الوصف |
|---|---|
1 track | The line the handle travels along: the whole range from min to max. Drawn in the track color where it is not active. |
2 active-track | The part of the track from the origin to the value, or between the two handles of a range, drawn over the track. |
3 handle | The part the person drags, one per value: in Tanrei a circle (its width along the track equals its height across it) with a fill and an outline of its own, a narrow upright bar where a system says so. |
4 handle-outline · اختياري | The ring drawn over the handle's fill, inside its edge, so the handle keeps its size however wide the ring is: a wider ring leaves a smaller disc of fill. None where its width is 0. |
5 container | The round state layer centered on a handle, moving with it. It carries hover, focus and press and is invisible at rest. |
6 stop-indicator · اختياري | A dot on the track's midline, half the track's thickness across in Tanrei: at an end of the handle's travel that lies on the track, and at every step while stops is true. |
7 value-indicator · اختياري | A small label beside a handle that shows its value while the handle is pressed or focused, or always. |
8 focus-ring | Gap-then-ring indicator around the handle that has keyboard focus. |
القياسات
القياسات
| الطول | الرمز | القيمة (px) |
|---|---|---|
handle height | tanrei.comp.slider.handle.height.small | 20 |
container size | tanrei.comp.slider.container.size | 40 |
continuous كما ترسمه حزمة الويب.الخصائص
| الخاصية | النوع | القيمة الافتراضية | الوصف |
|---|---|---|---|
size | small | medium | large | "small" | The track's weight and the stop dots' size (and, where a system says so, the handle's height). Small is the everyday slider; medium and large give a prominent control (a volume or brightness slider) more weight. The hit area always meets the minimum target. A design system may add values. |
orientation | horizontal | vertical | "horizontal" | Horizontal runs from the inline start (min) to the inline end (max); vertical runs from the bottom (min) to the top (max). |
value | number | 0 | The value of the only handle, or of a range's end handle. |
startValue | number | 0 | The value of a range's start handle. Ignored while range is false. |
range | boolean | false | Draws two handles, choosing the range from startValue to value (a price filter). |
min | number | 0 | The lowest value, at the track's start. |
max | number | 100 | The highest value, at the track's end. |
step | number | 0 | 0 is continuous. Above 0 the slider is discrete: its values are min plus whole multiples of step, up to max. |
origin | number | null | Where the active track starts. Null starts it at min. A value inside the range makes a centered slider (a balance control) whose active track grows toward either side. Ignored while range is true. |
stops | boolean | false | Draws a stop dot at every value a discrete slider can take. Meant for a few steps; ignored while step is 0. |
valueIndicator | none | active | always | "none" | Whether a handle shows its value beside it: never, while it is pressed or has keyboard focus, or all the time. |
disabled | boolean | false | Prevents interaction and removes the handles from the focus order. |
label | string | "" | Names the slider (a range's end handle) for assistive technology. Never drawn: a visible label is the product's text next to the slider, in the same words. Required. |
startLabel | string | "" | Names a range's start handle ("Minimum price"). Required while range is true. |
valueText | string | "" | The value as words ("40 %", "3 stars"), spoken and shown by the value indicator in place of the number. For a range, the end handle's. |
startValueText | string | "" | The start handle's valueText, for a range. |
الأحداث
| الحدث | الوصف |
|---|---|
input | The person changed a value; carries value and, for a range, startValue. Emitted for every change during a drag, not when the product sets a value. |
change | The person finished changing a value (the press ended, or a key or assistive-technology adjustment was made); carries value and, for a range, startValue. Always after the input it follows. |
الحالات
السلوك
متطلبات بصيغة EARS. يُختبر تنفيذ كل منصة مقابل هذه المعرّفات. يُعرض نص المتطلبات كما ورد في ملف المواصفة، بالإنجليزية.
| المعرّف | المتطلب |
|---|---|
SLD-1 | THE slider SHALL keep value (and, while range is true, startValue) between min and max; WHILE step is greater than 0 it SHALL take only min plus whole multiples of step that do not exceed max, snapping to the nearest, and WHILE step is 0 any value between min and max. |
SLD-2 | WHEN the person presses the slider by pointer or touch — the track, a handle, or the space around them — THE slider SHALL move the handle nearer the press (for a range whose handles meet, the one that can move toward the press) to the value under it and, WHILE the press moves, SHALL make the handle follow it along the track, clamped to the handle's range and snapped to step; it SHALL emit input once for each value change and, WHEN the press ends with a value other than the one it started with, change once after the last input. On touch the handle SHALL move once the press has travelled along the track by the platform's touch slop, or when a press that did not move ends; a press that first travels across the track by the slop SHALL be left to an enclosing scroll view and SHALL change nothing. |
SLD-3 | WHILE a handle has keyboard focus THE slider SHALL increase its value by one keyboard step with Right Arrow or Up Arrow and decrease it with Left Arrow or Down Arrow (Right and Left swapped in a right-to-left horizontal slider), by ten keyboard steps with Page Up and Page Down, and set it to the lowest and highest value it can take with Home and End; the keyboard step is step, or one hundredth of max − min while step is 0. Each key press that changes the value SHALL emit input and then change once; a key press that changes nothing SHALL emit nothing. |
SLD-4 | WHEN assistive technology increments or decrements a handle (a vertical swipe on an adjustable element, the platform's increment and decrement actions) THE slider SHALL change its value by one keyboard step, and WHEN it sets a value directly where the platform allows that THE slider SHALL clamp and snap it; either SHALL emit input and then change once. |
SLD-5 | WHILE range is true THE slider SHALL draw a start handle at startValue and an end handle at value, SHALL stop each handle at the other's value so that the two may meet but never cross, and SHALL make each handle its own Tab stop, the start handle first, and its own element for assistive technology. |
SLD-6 | WHILE range is false THE slider SHALL draw the active track between origin (min while origin is null, and origin clamped to the range) and value, on whichever side of origin value lies; WHILE range is true it SHALL draw the active track between startValue and value. |
SLD-7 | THE slider SHALL be as long along its axis as its layout gives it and, across it, as thick as the larger of comp.slider.container.size and comp.slider.handle.height.small for size small (and so on for each size); it SHALL extend its hit area across its axis to sys.target.touch for touch input and sys.target.pointer for fine pointers without changing that size (a platform that cannot tell the input type SHALL use sys.target.touch), the whole slider being the hit area, and a handle drawn smaller than the target SHALL NOT make the hit area smaller. It SHALL draw the track comp.slider.track.thickness.small thick for size small (and so on), centered across the axis and inset from each end of the slider by half of comp.slider.container.size, so that a handle and its state layer stay inside the slider at min and max; a handle's center SHALL travel between the two points half the track's thickness in from the track's ends, concentric with its rounded ends. |
SLD-8 | THE slider SHALL draw the track in comp.slider.standard.track.color and the active track over it in comp.slider.standard.active-track.color. WHILE comp.slider.track.gap is 0 the track and the active track SHALL run under each handle and meet at its center, so that nothing lies between the active track and the handle; WHILE it is above 0 they SHALL stop that far from each side of each handle, measured from the handle's edge. The pieces SHALL be rounded by comp.slider.track.shape.small for size small (and so on), clamped to half the thickness, at the track's two ends and, WHILE comp.slider.track.gap is above 0, beside a handle; they SHALL be square where two pieces meet (under a handle while the gap is 0, and at an origin inside the travel). It SHALL draw each handle centered on the track's midline, comp.slider.standard.handle.width along the axis and comp.slider.handle.height.small across it for size small (and so on), rounded by comp.slider.handle.shape clamped to half its smaller side, painted as SLD-24 says, above the tracks — each part from the tokens of the state SLD-11 names. |
SLD-9 | THE slider SHALL draw a dot of comp.slider.stop-indicator.size.small for size small (and so on) centered on the track's midline at each end of the handles' travel that lies on the track rather than on the active track, and WHILE stops is true and step is greater than 0 also at every value the slider can take; a dot SHALL be drawn in comp.slider.standard.stop-indicator.color where it lies on the track and in comp.slider.standard.active-stop-indicator.color where it lies on the active track, SHALL NOT be drawn where a handle or its track gap covers it, and a size of 0 SHALL draw none. |
SLD-10 | THE slider SHALL draw each handle's container, a shape of comp.slider.container.size on each side with corners comp.slider.container.shape, centered on the handle and moving with it, filled with comp.slider.standard.container.color from the handle's state, behind the handle and above the tracks; it may extend beyond the track without affecting layout, and a size of 0 SHALL draw none. |
SLD-11 | WHILE a handle is hovered, keyboard-focused or pressed THE slider SHALL render that handle and its container from the component tokens of that handle's highest-precedence active state, with precedence pressed over focused over hovered, and the tracks, stop dots and opacity from the highest-precedence state of any of its handles; a handle is hovered while a fine pointer is over the slider and that handle is the one a press there would move; focus gained by pointer or touch SHALL NOT select the focused state. WHEN the colors change between states THE slider SHALL animate them over comp.slider.motion.state-duration with comp.slider.motion.state-easing, and at once where motion is reduced. |
SLD-12 | WHEN a handle receives keyboard focus THE slider SHALL show the focus ring around that handle without animation; focus gained by pointer or touch SHALL NOT show it. |
SLD-13 | WHEN the slider is pressed by pointer or touch THE slider SHALL show the pressed state of the handle the press moves without delay, SHALL keep it for as long as the press lasts, and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner. |
SLD-14 | WHILE pressed THE slider 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; handle, tracks, stop dots, 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.slider.motion.feedback-duration with comp.slider.motion.state-easing, fades over comp.slider.motion.state-duration with comp.slider.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced. The slider's point of contact is the pressed handle's center, because the handle moves to the press. |
SLD-15 | THE slider SHALL ease its container, handle and track 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. |
SLD-16 | WHEN a value changes by a key, by assistive technology, by a press on the track that did not drag, or because the product set it, THE slider SHALL move the handle and the active track to it over comp.slider.motion.value-duration with comp.slider.motion.value-easing; WHILE a press drags a handle, the handle SHALL follow the press without delay; WHERE motion is reduced every change SHALL be shown at once. WHEN the product sets value or startValue THE slider SHALL NOT emit input or change. |
SLD-17 | WHILE valueIndicator is always, or valueIndicator is active and a handle is pressed or has keyboard focus, THE slider SHALL draw that handle's value indicator comp.slider.value-indicator.offset beyond the handle's outer edge across the axis — above the handle in a horizontal slider, at its inline start in a vertical one; for a round handle beyond the top of its circle, outline included, which lies half of comp.slider.handle.height.small from the track's midline for size small (and so on) — with its center on the handle's center along the axis, shifted along the axis only as far as it must to stay inside the window: the handle's value text on one line in comp.slider.value-indicator.label.typescale and comp.slider.value-indicator.label.color, centered in a container of comp.slider.value-indicator.container.color at least comp.slider.value-indicator.container.height high and as wide as the text plus comp.slider.value-indicator.container.padding-inline on each side but never narrower than it is high, rounded by comp.slider.value-indicator.container.shape. The value indicator SHALL be drawn above neighbouring content and above the handle and its container, without affecting layout or being clipped by the slider, SHALL take no focus and no input (a read overlay), SHALL be hidden from assistive technology, and SHALL fade in and out over comp.slider.motion.state-duration with comp.slider.motion.state-easing, at once where motion is reduced. |
SLD-18 | THE slider SHALL give each handle a value text: valueText for the only handle and a range's end handle, startValueText for a range's start handle; or, while that is empty, what the product's own function writes for that handle's value, WHERE the product gave the slider such a function in the platform's idiom; or, with neither, the value formatted as a number in the platform's locale with as many fraction digits as the keyboard step has, at most two; the value indicator SHALL show it and assistive technology SHALL read it as the handle's value. THE slider SHALL ask the function again at every change of a value and WHEN the function itself changes, SHALL take an empty answer as no answer, and SHALL announce nothing for a change of the words alone. |
SLD-19 | THE slider SHALL expose each handle as a slider (the adjustable trait on Apple platforms) named by label, or by startLabel for a range's start handle, with its value, its value text, the lowest and highest value it can take (for a range, bounded by the other handle), its orientation and its disabled state; the tracks, stop dots, container and value indicator SHALL be hidden from assistive technology. WHILE a handle's label (label, or startLabel for a range's start handle) is not empty THE slider SHALL expose it as that handle's accessible name, over a name the product gives the slider on the element (aria-label or aria-labelledby). WHILE label is empty and the product gives the slider a name of its own on the element — aria-label, or aria-labelledby naming an element — THE slider SHALL expose that name on each handle whose own label is empty. WHILE label is empty and the product gives it none, or range is true and startLabel is empty, THE slider SHALL still render, and in debug builds report that a handle has no accessible name: one name of the product's does not tell a range's two handles apart. |
SLD-20 | WHILE disabled is true THE slider SHALL NOT change a value or emit input or change, SHALL NOT be focusable, SHALL show no value indicator, SHALL expose the disabled state to assistive technology, and SHALL render its container, handles, tracks, stop dots and opacity from the disabled component tokens. |
SLD-21 | WHILE orientation is vertical THE slider SHALL run its track from the bottom (min) to the top (max), be as tall as its layout gives it, and lay out every part SLD-7 to SLD-17 name turned a quarter turn; WHEN the layout direction is right-to-left THE slider SHALL run a horizontal track from the right (min) to the left (max), mirroring the active track, the stop dots and the arrow keys (SLD-3), and SHALL NOT mirror a vertical slider. WHILE a value indicator is drawn in a right-to-left layout THE slider SHALL keep it centred on its handle and shift it along the axis only as far as it must to stay inside the window, away from whichever edge of the window it would cross, as in left-to-right (SLD-17): the shift is physical and is not mirrored. |
SLD-22 | IF value, startValue or origin lies outside min and max, or off a step, THE slider SHALL draw and expose it clamped and snapped without emitting input or change; IF startValue is greater than value while range is true THE slider SHALL draw both handles at value; IF max is not greater than min THE slider SHALL draw its handles at the track's start and take no input; IF step is below 0 THE slider SHALL treat it as 0. In debug builds it SHALL report each of these. |
SLD-23 | WHEN size names a value that the active design system does not have, or orientation or valueIndicator a value the component does not define, THE slider SHALL render with the default value (small, horizontal, none), and in debug builds report the unknown value. |
SLD-24 | THE slider SHALL fill the whole shape of each handle with comp.slider.standard.handle.color and draw the handle's outline over the fill, comp.slider.handle-outline.width wide inside the handle's edge, in comp.slider.standard.handle-outline.color, so that the outline never changes the handle's width or height and a width of 0 draws none; it SHALL raise the handle by comp.slider.standard.handle.elevation. The parts under a handle (the tracks where they meet, a stop dot, the container) SHALL show through it only as far as its fill is translucent. |
SLD-25 | THE slider 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 slider is shown THE slider SHALL draw itself for the new direction at once, without a motion of its own, keeping its values and its focus, each value indicator placed again by the new direction. |
SLD-26 | THE slider SHALL lay out a handle's value text in its value indicator as text of its own direction, isolated from the text around it: each takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right word, a number with its sign or unit, a telephone number and an address keep their own order in a right-to-left layout and reorder nothing beside them; THE slider SHALL still place the indicator and align its lines by the layout direction, not by the text's own. |
SLD-27 | WHERE the platform has ARIA attributes (the web), WHEN the product sets an aria- attribute on the host, by the attribute or by the ARIA property that reflects it, THE slider 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 the element that carries its role (every handle carries them) — an id reference by the elements it names in the host's tree or a tree around it, an error message as part of the description while the slider is invalid — except those the slider owns (aria-disabled), which it SHALL move and not expose. WHEN the product removes the aria- attribute or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaDescribedByElements…) to null, THE slider SHALL take it off that element. WHEN the product sets an aria- attribute the slider owns THE slider SHALL report it in debug builds. |
مطابقة الأسماء بين المنصات
التكافؤ لا يعني واجهات برمجية متطابقة. تعبّر كل منصة عن العقد نفسه بأسلوبها.
| المواصفة | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| المكوّن | tanrei-slider | TanreiSlider | TanreiSlider | TanreiSlider | Slider |
size · الخاصية | size | size | size | size | size |
orientation · الخاصية | orientation | orientation | orientation | orientation | orientation |
value · الخاصية | value | value | value | value | value |
startValue · الخاصية | startValue | value | value | start | startValue |
range · الخاصية | range | value | value | range | range |
min · الخاصية | min | bounds | valueRange | min | minimumValue |
max · الخاصية | max | bounds | valueRange | max | maximumValue |
step · الخاصية | step | step | step | step | step |
origin · الخاصية | origin | origin | origin | origin | origin |
stops · الخاصية | stops | showsStops | showStops | showStops | stops |
valueIndicator · الخاصية | valueIndicator | valueIndicator | valueIndicator | valueIndicator | valueIndicator |
disabled · الخاصية | disabled | disabled | enabled | onChanged | disabled |
label · الخاصية | label | label | contentDescription | semanticLabel | accessibilityLabel |
startLabel · الخاصية | startLabel | startLabel | startContentDescription | startSemanticLabel | startAccessibilityLabel |
valueText · الخاصية | valueText | valueText | stateDescription | semanticValue | valueText |
startValueText · الخاصية | startValueText | startValueText | startStateDescription | startSemanticValue | startValueText |
input · الحدث | input | value | onValueChange | onChanged | onValueChange |
change · الحدث | change | onCommit | onValueChangeFinished | onChangeEnd | onSlidingComplete |
| ملاحظات | Attributes are kebab-case (start-value, value-indicator, start-label, value-text, start-value-text). Each handle is an element with role="slider" and its aria-value attributes, aria-orientation and aria-label in the shadow root (not ElementInternals, which axe cannot see). Not <input type="range">: it has one handle, no gap, no stop dots, and its parts cannot be styled alike in every engine. The handle's outline is its box's border with box-sizing: border-box, over its background (the fill), so it keeps its width and height (SLD-24); while track.gap is 0 the two pieces of the tracks meet at the handle's center under it (SLD-8). Form-associated: it takes name and submits value (a range submits startValue, then value, under the same name), and it sets its own value and startValue before firing input and change, as a native control does. Snapshot harness: the stages of SLD-7. The product's function for a value's words (SLD-18) is formatValue, a property and never an attribute: ((value: number) => string) | null, null by default; it is asked for each handle at every change of a value and when the property itself is set. | Slider idiom: TanreiSlider(_ label:, value: Binding<Double>, in bounds: ClosedRange<Double> = 0...100, step:); a range is the initializer whose value is a Binding<ClosedRange<Double>> (lower bound startValue, upper bound value) and which also takes startLabel. Every change writes the binding, which is the input event. onCommit is Tanrei's own parameter, called when a change is finished (SLD-2, SLD-3, SLD-4), as the text field's is; SwiftUI's onEditingChanged reports a drag's start and end, not a change. SwiftUI's own Slider is not used: its track and handle cannot take the tokens. Each handle is an adjustable element (.accessibilityAdjustableAction, .accessibilityValue); disabled follows .disabled(_:). Lagging: ships an earlier form of the slider — a solid round handle, tracks cut at the handle's edge (square there while track.gap is 0), one stop-dot size for every size. It does not draw yet: the handle's fill and outline (SLD-24), the tracks meeting under the handle while track.gap is 0 (SLD-8), the stop dot per size (SLD-9) and the value indicator's placement over a round handle (SLD-17). Not built on this platform yet: the product's function for a value's words (SLD-18) is a format: ((Double) -> String)? = nil parameter. Not built on this platform yet: the stage color a fixture's surface names, which the continuous-on-container-highest fixture draws on. | Compose idiom (as Slider and RangeSlider): TanreiSlider(value: Float, onValueChange, modifier, enabled, valueRange: ClosedFloatingPointRange<Float> = 0f..100f, step: Float = 0f, onValueChangeFinished, …); a range is the overload whose value is a ClosedFloatingPointRange<Float> (start and end) and which also takes startContentDescription and startStateDescription. step is a size, not Material's count of steps. State hoisting: the caller moves value from onValueChange. enabled is the inverse flag. Each handle has Compose's slider semantics (progressBarRangeInfo and setProgress), with stateDescription as its value text. Lagging: ships an earlier form of the slider — a solid round handle with its shape clipped out of the tracks, one stop-dot size for every size. It does not draw yet: the handle's fill and outline (SLD-24), the tracks meeting under the handle while track.gap is 0 (SLD-8), the stop dot per size (SLD-9) and the value indicator's placement over a round handle (SLD-17). Not built on this platform yet: the product's function for a value's words (SLD-18) is a format: ((Float) -> String)? = null parameter. Not built on this platform yet: the stage color a fixture's surface names, which the continuous-on-container-highest fixture draws on. | Flutter idiom (as Slider): TanreiSlider(value:, onChanged:, onChangeEnd:, min: 0, max: 100, step: 0, …), with step a size rather than Material's divisions; a range is the named constructor TanreiSlider.range(start:, end:, onChanged: (start, end) {…}, …), since Flutter's RangeValues belongs to Material. A null onChanged disables it. orientation is Flutter's Axis. Each handle is a Semantics(slider: true, value:, increasedValue:, decreasedValue:, onIncrease:, onDecrease:) node; the widgets library draws everything else. Lagging: ships an earlier form of the slider — a solid round handle, tracks cut at the handle's edge and rounded there (a notch between the round end and the handle), one stop-dot size for every size. It does not draw yet: the handle's fill and outline (SLD-24), the tracks meeting under the handle while track.gap is 0 (SLD-8), the stop dot per size (SLD-9) and the value indicator's placement over a round handle (SLD-17). Not built on this platform yet: the product's function for a value's words (SLD-18) is format: String Function(double)?. Not built on this platform yet: the stage color a fixture's surface names, which the continuous-on-container-highest fixture draws on. | Controlled, in the community slider's idiom (value, minimumValue, maximumValue, step, onValueChange, onSlidingComplete), without depending on it: React Native has no slider in its core. A range adds range and startValue, and both callbacks receive (value, startValue). Each handle is a view with accessibilityRole="adjustable", accessibilityValue ({ min, max, now, text }) and the increment and decrement accessibility actions; the drag is a the touch responder props (onStartShouldSetResponder and the rest) that yields to an enclosing ScrollView as SLD-2 says. The arrow keys work where a hardware keyboard is attached, as the tabs row's do. Lagging: ships an earlier form of the slider — a solid round handle, tracks cut at the handle's edge and rounded there (a notch between the round end and the handle), one stop-dot size for every size. It does not draw yet: the handle's fill and outline (SLD-24), the tracks meeting under the handle while track.gap is 0 (SLD-8), the stop dot per size (SLD-9) and the value indicator's placement over a round handle (SLD-17). Not built on this platform yet: the product's function for a value's words (SLD-18) is a formatValue prop, (value: number) => string. Not built on this platform yet: the stage color a fixture's surface names, which the continuous-on-container-highest fixture draws on. |
الرموز
| الرمز | يشير إلى | القيمة المحلولة (فاتح) |
|---|---|---|
--tanrei-comp-slider-container-shape | sys.shape.corner.full | 9999px |
--tanrei-comp-slider-container-size | — | 40px |
--tanrei-comp-slider-disabled-opacity | — | 1 |
--tanrei-comp-slider-focused-opacity | — | 1 |
--tanrei-comp-slider-handle-outline-width | — | 3px |
--tanrei-comp-slider-handle-height-large | — | 20px |
--tanrei-comp-slider-handle-height-medium | — | 20px |
--tanrei-comp-slider-handle-height-small | — | 20px |
--tanrei-comp-slider-handle-shape | sys.shape.corner.full | 9999px |
--tanrei-comp-slider-hovered-opacity | — | 1 |
--tanrei-comp-slider-motion-feedback-duration | sys.motion.role.feedback | 450ms |
--tanrei-comp-slider-motion-state-duration | sys.motion.role.state.compact | 200ms |
--tanrei-comp-slider-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-slider-motion-value-duration | sys.motion.role.selection.travel | 250ms |
--tanrei-comp-slider-motion-value-easing | sys.motion.easing.spatial | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-slider-pressed-opacity | — | 1 |
--tanrei-comp-slider-standard-active-stop-indicator-color | sys.color.on-primary | |
--tanrei-comp-slider-standard-active-track-color | sys.color.primary | |
--tanrei-comp-slider-standard-container-color | — | |
--tanrei-comp-slider-standard-disabled-active-stop-indicator-color | — | |
--tanrei-comp-slider-standard-disabled-active-track-color | — | |
--tanrei-comp-slider-standard-disabled-container-color | — | |
--tanrei-comp-slider-standard-disabled-handle-outline-color | — | |
--tanrei-comp-slider-standard-disabled-handle-color | — | |
--tanrei-comp-slider-standard-disabled-handle-elevation | — | |
--tanrei-comp-slider-standard-disabled-handle-width | — | 20px |
--tanrei-comp-slider-standard-disabled-state-layer-color | — | |
--tanrei-comp-slider-standard-disabled-stop-indicator-color | — | |
--tanrei-comp-slider-standard-disabled-track-color | — | |
--tanrei-comp-slider-standard-focused-active-stop-indicator-color | — | |
--tanrei-comp-slider-standard-focused-active-track-color | — | |
--tanrei-comp-slider-standard-focused-container-color | — | |
--tanrei-comp-slider-standard-focused-handle-outline-color | — | |
--tanrei-comp-slider-standard-focused-handle-color | — | |
--tanrei-comp-slider-standard-focused-handle-elevation | — | |
--tanrei-comp-slider-standard-focused-handle-width | — | 20px |
--tanrei-comp-slider-standard-focused-state-layer-color | — | |
--tanrei-comp-slider-standard-focused-stop-indicator-color | — | |
--tanrei-comp-slider-standard-focused-track-color | — | |
--tanrei-comp-slider-standard-handle-outline-color | sys.color.primary | |
--tanrei-comp-slider-standard-handle-color | sys.color.surface | |
--tanrei-comp-slider-standard-handle-elevation | sys.elevation.level0 | |
--tanrei-comp-slider-standard-handle-width | — | 20px |
--tanrei-comp-slider-standard-hovered-active-stop-indicator-color | — | |
--tanrei-comp-slider-standard-hovered-active-track-color | — | |
--tanrei-comp-slider-standard-hovered-container-color | — | |
--tanrei-comp-slider-standard-hovered-handle-outline-color | — | |
--tanrei-comp-slider-standard-hovered-handle-color | — | |
--tanrei-comp-slider-standard-hovered-handle-elevation | — | |
--tanrei-comp-slider-standard-hovered-handle-width | — | 20px |
--tanrei-comp-slider-standard-hovered-state-layer-color | — | |
--tanrei-comp-slider-standard-hovered-stop-indicator-color | — | |
--tanrei-comp-slider-standard-hovered-track-color | — | |
--tanrei-comp-slider-standard-pressed-active-stop-indicator-color | — | |
--tanrei-comp-slider-standard-pressed-active-track-color | — | |
--tanrei-comp-slider-standard-pressed-container-color | — | |
--tanrei-comp-slider-standard-pressed-handle-outline-color | — | |
--tanrei-comp-slider-standard-pressed-handle-color | — | |
--tanrei-comp-slider-standard-pressed-handle-elevation | — | |
--tanrei-comp-slider-standard-pressed-handle-width | — | 20px |
--tanrei-comp-slider-standard-pressed-state-layer-color | — | |
--tanrei-comp-slider-standard-pressed-stop-indicator-color | — | |
--tanrei-comp-slider-standard-pressed-track-color | — | |
--tanrei-comp-slider-standard-state-layer-color | comp.slider.standard.handle-outline.color | |
--tanrei-comp-slider-standard-stop-indicator-color | sys.color.on-surface-variant | |
--tanrei-comp-slider-standard-track-color | sys.color.surface-variant | |
--tanrei-comp-slider-stop-indicator-size-large | — | 4px |
--tanrei-comp-slider-stop-indicator-size-medium | — | 3px |
--tanrei-comp-slider-stop-indicator-size-small | — | 2px |
--tanrei-comp-slider-track-gap | sys.space.space0 | 0px |
--tanrei-comp-slider-track-shape-large | sys.shape.corner.full | 9999px |
--tanrei-comp-slider-track-shape-medium | sys.shape.corner.full | 9999px |
--tanrei-comp-slider-track-shape-small | sys.shape.corner.full | 9999px |
--tanrei-comp-slider-track-thickness-large | — | 8px |
--tanrei-comp-slider-track-thickness-medium | — | 6px |
--tanrei-comp-slider-track-thickness-small | — | 4px |
--tanrei-comp-slider-value-indicator-container-color | sys.color.inverse-surface | |
--tanrei-comp-slider-value-indicator-container-height | — | 24px |
--tanrei-comp-slider-value-indicator-container-padding-inline | sys.space.space100 | 8px |
--tanrei-comp-slider-value-indicator-container-shape | sys.shape.corner.small | 6px |
--tanrei-comp-slider-value-indicator-label-color | sys.color.inverse-on-surface | |
--tanrei-comp-slider-value-indicator-offset | sys.space.space100 | 8px |
--tanrei-comp-slider-value-indicator-label-typescale | sys.typescale.label-small | 500 12px/1.3333 |
نماذج الاختبار
عروض مرجعية. تلتقط كل المنصات لقطة لكل نموذج بالمعرّف نفسه حتى يمكن مقارنة النتائج.
size: small (9)
continuous
value: 40 label: Volume continuous-on-container-highest
value: 40 label: Volume discrete-stops
value: 30 step: 10 stops: true label: Brightness range
value: 60 startValue: 20 range: true label: Maximum price startLabel: Minimum price centered
value: 20 min: -50 max: 50 origin: 0 label: Balance value-indicator
value: 40 valueIndicator: always label: Volume vertical
orientation: vertical value: 60 label: Volume disabled
value: 40 disabled: true label: Volume disabled-stops
value: 60 step: 20 stops: true disabled: true label: Brightness size: medium (1)
medium
size: medium value: 40 label: Volume size: large (1)
large
size: large value: 40 label: Volume مولَّد من specs/slider.spec.json, tokens/comp/slider.tokens.json, design/tokens/
استخدم شريط التمرير حين يختار الأشخاص قيمة بالإحساس ويرون أثرها وهم يحرّكون: مستوى الصوت، السطوع، تعريض صورة، نصف قطر البحث في خريطة. وشريط التمرير ذو المدى يناسب عامل تصفية له حد أدنى وحد أعلى، كالسعر.
حين يكون الرقم الدقيق أهم من موضعه، كمبلغ من المال أو كمية، استخدم حقل نص، أو ضع واحدًا بجانب شريط التمرير ليستطيع الشخص استخدام أيهما شاء. وحين لا يكون هناك إلا بضعة خيارات مسمّاة، مثل منخفض ومتوسط وعالٍ، فإن أزرار الاختيار تسمّي كل واحد منها، أو الزر المقسَّم حيث يقدّمه النظام.
- المستمر (القيمة 0 للخاصية
step) يأخذ أي قيمة بينminوmax. استخدمه حين يكون للقيم البينية معنى ويظهر الأثر فورًا. - المدرَّج (قيمة
stepفوق 0) ينجذب إلىminمضافًا إليه مضاعفات صحيحة منstep. استخدمه حين لا معنى إلا للوحدات الكاملة: نجوم، حجم خط بالنقاط، نسبة مئوية بالعشرات. - الخاصية
stopsترسم نقطة عند كل قيمة يستطيع شريط تمرير مدرَّج أن يأخذها. فعِّلها حين تكون الدرجات قليلة، ليستطيع الناس عدّها. ومع الدرجات الكثيرة تزدحم النقاط على المسار، فاتركها موقوفة.
مفاتيح الأسهم تحرّك بدرجة واحدة، أو بجزء من مئة من المدى في شريط التمرير المستمر. والمفتاحان Page Up و Page Down يحرّكان بعشر درجات.
الخاصية range ترسم مقبضين، من startValue إلى value. يجوز أن يلتقي المقبضان ولا يتجاوز أحدهما الآخر أبدًا. كل منهما موضع توقف مستقل للمفتاح Tab وعنصر تحكم مستقل لقارئ الشاشة، الذي يسمع المدى الذي ما زال المقبض يستطيع بلوغه. سمِّ المقبضين كليهما بالخاصيتين startLabel («أدنى سعر») و label («أعلى سعر»).
الخاصية origin تعيّن أين يبدأ المسار النشط. إن تُركت فارغة بدأ عند min. والقيمة الواقعة داخل المدى، مثل 0 في عنصر تحكم بالتوازن من -50 إلى 50، تجعل المسار النشط يكبر من هناك نحو أي من الجهتين. ويحتفظ طرفا المسار بنقطتي التوقف، فيبقى الحدّان كلاهما ظاهرين.
الخاصية valueIndicator تعرض قيمة المقبض في تسمية صغيرة بجانبه.
| القيمة | تعرض القيمة | يُستخدم لـ |
|---|---|---|
none (الافتراضي) |
أبدًا | أشرطة التمرير التي يظهر أثرها في موضع آخر من الشاشة: مستوى الصوت، السطوع |
active |
ما دام المقبض مضغوطًا أو عليه تركيز لوحة المفاتيح | القيم التي يحتاج الناس إلى قراءتها وهم يضبطونها، حيث تغطي الإصبع المقبض |
always |
طوال الوقت | قيمة يجب أن تبقى مقروءة، حين لا مكان لنص من عندك بجانب شريط التمرير |
يقع المؤشر فوق مقبض شريط التمرير الأفقي، وعند بداية السطر في العمودي. ويعرض نص الخاصية valueText حين تعطيه، وإلا عرض الرقم بالإعدادات المحلية للمنصة، بعدد من المنازل العشرية يساوي ما في درجة لوحة المفاتيح، حتى منزلتين. وهو مجرد عرض للقيمة: لا يأخذ تركيزًا ولا إدخالًا، وقارئ الشاشة يقرأ القيمة من المقبض.
اضبط الخاصية valueText على الكلمات التي تعبّر عن القيمة الحالية حين يكون الرقم المجرّد غير واضح: «40%»، «3 نجوم»، «$300». وهذا النص يحلّ محل الرقم في مؤشر القيمة وفي ما يقوله قارئ الشاشة معًا. وللمدى تفعل الخاصية startValueText الشيء نفسه لمقبض البداية. حدِّثه كلما تغيرت القيمة.
والكلمات التي تُكتب مرة واحدة تصير خطأ بعد أول سحب. لذلك يأخذ شريط التمرير أيضًا دالة واحدة تحوّل القيمة إلى كلماتها، تُعطى مرة واحدة: يسأل الدالة عن كل مقبض عند كل تغيّر، وتبقى الغلبة للخاصيتين valueText و startValueText حيث تضبطهما. على الويب هي formatValue، وهي خاصية للعنصر وليست خاصية HTML أبدًا. أما المنصات الأخرى فلم تنفّذها بعد.
const dollars = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
document.querySelector('[name="price"]').formatValue = (value) => dollars.format(value);يُستخدم في حقل شريط التمرير: حقل وشريط تمرير في مكوّن واحد، تُرسم فيه هذه الكلمات في نهاية صف التسمية. استخدمه حيثما احتاج شريط التمرير إلى تسمية مرسومة أو مساعدة أو خطأ.
الحجم small هو شريط التمرير اليومي. والحجمان medium و large يعطيان عنصر تحكم بارزًا، كشريط مستوى الصوت أو السطوع في شاشة وسائط، مسارًا أثقل. وكل حجم يستوفي الحد الأدنى للهدف.
شريط التمرير العمودي يمتد من الأسفل (min) إلى الأعلى (max) في كل اتجاه للتخطيط. والأفقي يمتد من بداية السطر، ففي التخطيط من اليمين إلى اليسار تكون min على اليمين.
- ضع تسميتك المرئية بجانب شريط التمرير، بالكلمات نفسها التي في
label. - أظهِر أثر القيمة والشخص يسحب، واحفظها عند
change، لا عند كلinput. - اختر
minوmaxوstepبحيث تكون كل قيمة يستطيع شريط التمرير أن يأخذها قيمة قد يريدها الناس. - أعطِ
valueTextوحدة حين لا يقول الرقم وحده ما الذي يعدّه.
- لا تستخدم شريط تمرير لقيمة يجب أن يضبطها الناس بدقة، كتاريخ أو مبلغ من المال.
- لا تستخدم شريط تمرير لإعداد ليس إلا مفعَّلًا أو موقوفًا. استخدم مفتاح تبديل.
- لا تعرض نقاط التوقف على شريط تمرير كثير الدرجات.
- لا تضع شريط تمرير داخل شريط أدوات. فهو يحتاج إلى مفاتيح الأسهم التي ينقل بها شريط الأدوات التركيز.
- الدور
slider- التسمية
- label names the slider, or a range's end handle; startLabel names a range's start handle. Neither is drawn: a visible label is the product's text beside the slider, in the same words. valueText replaces the spoken number ("40 %", "3 stars"). The tracks, stop dots, state layer and value indicator are decorative.
- الحد الأدنى للهدف
- تستوفي مساحة اللمس الحد الأدنى لحجم الهدف حتى لو كان الحجم المرئي أصغر. minimum 32px · pointer 44px · spacing 8px · touch 48px
لوحة المفاتيح
| المفاتيح | الإجراء |
|---|---|
| Tab / Shift+Tab | Moves focus to the handle, and for a range to the start handle, then the end handle. |
| Right Arrow / Up Arrow | Increases the focused handle's value by one keyboard step (Right Arrow decreases it in a right-to-left horizontal slider). |
| Left Arrow / Down Arrow | Decreases the value by one keyboard step (Left Arrow increases it in a right-to-left horizontal slider). |
| Page Up / Page Down | Increases or decreases the value by ten keyboard steps. |
| Home / End | Sets the value to the lowest or highest the handle can take. |
ملاحظات
- Each handle is one slider for assistive technology: role slider with aria-valuemin, aria-valuemax, aria-valuenow, aria-valuetext and aria-orientation on the web; the adjustable trait with an accessibility value on Apple platforms (a vertical swipe increments and decrements); a range with a current value and the set-progress action on Android; a slider semantics node with increase and decrease actions in Flutter; role adjustable with accessibilityValue and increment and decrement actions in React Native.
- A range is two sliders, the WAI-ARIA multi-thumb pattern: each handle's lowest and highest value is bounded by the other handle, so a screen reader announces the range each can still reach.
- The value is read from the handle and the active track. The handle must be told apart from each thing it lies on — the track, the active track and the surface behind the slider — by its outline (comp.slider.standard.handle-outline.color, where comp.slider.handle-outline.width is above 0) or by its fill (comp.slider.standard.handle.color), at 3:1 or more; comp.slider.standard.active-track.color must stay at least 3:1 against the track and the surface. In the default system the outline carries it against the track and the surface, and the fill against the active track. A faint track keeps its end visible by the stop dot at the end of the travel (SLD-9).
- The handle may be drawn smaller than the minimum target (20 against 48 in the default system): the whole slider takes the press across its axis at the target's size (SLD-7), so every handle keeps its whole target, a range's two handles included, and no target is reported larger than the area that takes the press.
- Text size does not change the slider: it has no text of its own except the value indicator, which grows with the text.
- How a state looks is a value decision of the active design system; components read the state's tokens and never compute the effect themselves.
مولَّد من specs/slider.spec.json, tokens/sys/measure.tokens.json
- كل مقبض شريط تمرير (slider) عند التقنيات المساعدة، تسمّيه الخاصية
label(أوstartLabelلمقبض بداية المدى)، مع قيمته، ونص قيمته، وأدنى قيمة وأعلى قيمة يستطيع أخذهما، واتجاهه، وحالة تعطيله. وعلى منصات Apple هو عنصر قابل للتعديل (adjustable): التمرير العمودي بالإصبع يحرّكه درجة واحدة. - المدى شريطا تمرير، وفق نمط WAI-ARIA لتعدد المقابض (multi-thumb). وحدود كل مقبض يقيّدها المقبض الآخر، فيُعلِن قارئ الشاشة المدى الذي ما زال يستطيع بلوغه.
- المساران ونقاط التوقف وطبقة الحالة ومؤشر القيمة مخفيّة عن التقنيات المساعدة.
- كل مقبض موضع توقف للمفتاح Tab، ومقبض البداية أولًا. مفاتيح الأسهم تحرّك درجة واحدة، والمفتاحان Page Up و Page Down عشر درجات، والمفتاحان Home و End إلى أدنى قيمة وأعلاها. وفي شريط تمرير أفقي من اليمين إلى اليسار يتبادل مفتاحا السهمين الأيمن والأيسر دوريهما.
- إجراءا الزيادة والنقصان في قارئ الشاشة يحرّكان درجة واحدة؛ وتعيين قيمة مباشرة، حيث تسمح المنصة، يُحصر في المدى ويُجذب إلى الدرجة.
- الضغط في أي موضع على شريط التمرير ينقل المقبض الأقرب إلى هناك، والسحب يتبع. وفي اللمس، الضغط الذي يتحرك أولًا في اتجاه متعامد مع المسار يُترك لعرض التمرير (scroll view) المحيط، فلا يلتقط شريط التمرير حركة تمرير.
- شريط التمرير كله هو مساحة اللمس، ويبلغ الحد الأدنى للهدف في الاتجاه المتعامد مع المسار. المقبض مرسوم أصغر من الهدف، لكن ذلك لا يصغّر مساحة اللمس، فيحتفظ كل مقبض في المدى بالهدف كاملًا أيضًا.
- يعرض شريط التمرير مؤشر التركيز حول المقبض الذي عليه التركيز، عند تركيز لوحة المفاتيح فقط.
- يتميّز المقبض عن كل ما يقع عليه بتباين 3:1 أو أكثر في النظام الافتراضي: بحدّه مقابل المسار والصفحة، وبتعبئته مقابل المسار النشط. ويحافظ المسار النشط على 3:1 مقابل المسار والصفحة، وتبقى نهاية المسار الباهت ظاهرة بنقطة التوقف.
- شريط التمرير المعطَّل لا يقبل التركيز، ولا يعرض مؤشر قيمة، ويُعرض على أنه معطَّل.
- حجم النص لا يغيّر إلا مؤشر القيمة، الذي يكبر مع النص.
- تبلّغ بنيات التنقيح (debug) عن
labelأوstartLabelالناقصة، وعن قيمة أو قيمة بداية أو origin خارج المدى أو خارج الدرجات، وعن قيمة بداية أعلى من القيمة، وعنmaxليست أعلى منmin، وعن درجة سالبة، وعن إعداد غير معروف للحجم أو الاتجاه أو مؤشر القيمة.
فجوات معروفة في المنصات:
- على الويب لكل مقبض دور slider في الجذر الظلّي (shadow root)، لا عبر
ElementInternals، لأن axe-core لا يستطيع رؤية الدلالات المعيَّنة بتلك الطريقة. وليس<input type="range">، الذي له مقبض واحد وأجزاء لا ينسّقها محرّكان بالطريقة نفسها. - الويب: تضبط التقنيات المساعدة شريط تمرير ARIA بمفاتيح الأسهم التي يرسلها المتصفح إليه، فلا يمكن تعيين قيمة مباشرة.
- الويب: مؤشر القيمة ليس في الطبقة العليا (top layer). العنصر السلف الذي له
overflow: hiddenيقصّه، والعنصر الشقيق اللاحق ذو الموضع الذي لهz-indexفوق 1 يغطيه. - لا يستطيع SwiftUI عرض أدنى قيمة وأعلى قيمة للمقبض ولا اتجاهه، وعلى macOS ليس المقبض شريط تمرير عند التقنيات المساعدة.
- لا يستطيع SwiftUI التفريق بين اللمس والمؤشر: على iOS كل ضغط لمس، وضغط مؤشر iPad كذلك، وعلى macOS كل ضغط ضغطُ مؤشر. وقبل iOS 18 يكون سحب اللمس إيماءة من SwiftUI، قد لا يستطيع عرض التمرير المحيط بشريط التمرير أن يتسلّمها.
- في SwiftUI: مؤشر القيمة يبقى داخل شريط التمرير لا داخل النافذة، والعرض المرسوم بعد شريط التمرير قد يغطيه.
- في SwiftUI: المفاتيح مختبَرة على أنها قواعد، لا بلوحة مفاتيح حقيقية بعد، لأن المحاكي لا يعطي تركيز لوحة مفاتيح تحت الأتمتة.
- دلالات شريط التمرير في Compose ليس فيها اتجاه، فلا يُعرض اتجاه المقبض.
- لا يعرض Flutter أدنى قيمة ولا أعلى قيمة ولا اتجاهًا للمقبض، ولا إجراء لتعيين قيمة مباشرة.
- يكتب Flutter الرقم دائمًا بالعلامة
.فاصلةً عشرية، في كل الإعدادات المحلية. اضبط الخاصيةvalueTextحيث يهم ذلك. - في Flutter: لا تكبر مساحة اللمس في الاتجاه المتعامد مع المسار إلا حيث يكون أب شريط التمرير أكبر منه. والأب الذي بمقاس شريط التمرير تمامًا يقطعها.
- ليس في React Native إجراء لتعيين قيمة مباشرة ولا خاصية اتجاه، فلا يُعرض أي منهما.
- على React Native لا تعمل مفاتيح الأسهم إلا حيث تكون لوحة مفاتيح فعلية موصولة، كما في صف علامات التبويب.
- يعامل React Native كل ضغط على أنه لمس: ضغط الفأرة أو القلم ينتظر حتى يتحرك أو ينتهي قبل أن يحرّك المقبض.
- يرسم React Native مؤشر القيمة داخل شريط التمرير، لا في طبقة التراكب، فيبقى داخل شريط التمرير لا داخل النافذة، والعرض المرسوم بعد شريط التمرير قد يغطيه.
- في React Native: التخطيط، والسحب وكيف يفسح المجال لعرض التمرير، والمقابض القابلة للتعديل لم تُفحص بعد على جهاز.
- ما زالت SwiftUI و Compose و Flutter و React Native ترسم المظهر السابق: مقبض مصمت، ومقاس واحد لنقاط التوقف في كل الأحجام، ومساران مقطوعان عند المقبض بدل أن يلتقيا تحته. وحيث تقطع، تنهي المسار كل واحدة بطريقة: مربعًا على SwiftUI، ومدوَّرًا مع ثلمة على Flutter و React Native، ومقطوعًا على شكل المقبض على Compose.
- تحت
cupertinoيبلغ تباين المقبض الأبيض على صفحة بيضاء 1.0:1 في المخططات اللونية الفاتحة، أي دون 3:1 الذي يحتاج إليه جزء يُظهر القيمة. ليس له حدّ، كما ترسمه Apple، ويتميّز بظله وبالمسار النشط الملوَّن بجانبه؛ ولا ثابت (invariant) يفحص المقبض مقابل الصفحة. والنسبة 1.0:1 قياس يُحفظ معلومةً فقط: معايير إمكانية الوصول في Tanrei لا تنطبق على إعداد جاهز يحاكي نظامًا آخر. وتحتcupertinoلا يرسم شريط التمرير نقاط توقف أيضًا، ولا حتى عند طرفي المسار. - تحت
m3-likeيرسم شريط التمرير شريط Material القائم، من مقاسات Material المنشورة. ولم تُفحص بعد مقابل مرجع المطابقة. وتحتm3-expressive-likeلا مكان للرسم الذي يضعه Material داخل مسار ثخين (فجوة المحاكاةslider-inset-icon): ضع أيقونتك بجانب شريط التمرير.
- أعطِ كل شريط تمرير الخاصية
label، وأعطِ المدى الخاصيةstartLabelأيضًا، بلغة منتجك. واعرض الكلمات نفسها تسميةً مرئية بجانبه. - اضبط الخاصية
valueTextحين يكون الرقم وحده غير واضح، وأبقِها متوافقة مع القيمة. - أظهِر نتيجة التغيّر في موضع يراه الناس، وأخبرهم نصًّا إن تعذّر تطبيق تغيّر. شريط التمرير لا يُعلِن إلا قيمته هو.
- تحت
cupertino، حيث المقبض أبيض والمسار بلا نقاط عند طرفيه، أبعِد شريط التمرير عن السطح الأبيض البسيط متى استطعت. - على سطح بأعلى درجات الحاوية، كبطاقة مملوءة، يصعب رؤية المسار غير النشط: فدرجته تكاد تكون نفسها. وحيث يقف شريط التمرير على سطح كهذا، وجِّه
comp.slider.standard.track.colorإلى دور أقوى في طبقة. ويبقى المقبض والمسار النشط يُظهران القيمة. - على الويب أعطِ شريط التمرير الخاصية
nameليرسل قيمته مع نموذج.