Campo de control deslizante
Permite elegir un valor, o un intervalo de valores, en una escala como un campo completo. La pista bajo una etiqueta, con el valor dicho con palabras al final de la fila de la etiqueta, una línea de ayuda y el motivo por el que se rechazó un valor.
- Categoría
- Selección
- Tokens
comp.field- Nivel
- Compuesto
- Web
tanrei-slider-fieldschedule - SwiftUI
TanreiSliderFieldradio_button_unchecked - Jetpack Compose
TanreiSliderFieldradio_button_unchecked - Flutter
TanreiSliderFieldradio_button_unchecked - React Native
SliderFieldradio_button_unchecked
Generado a partir de docs/status/status.json, specs/slider-field.spec.json
Un campo de control deslizante, uno por pasos y un intervalo
Usa un campo de control deslizante para un valor que se elige a ojo y que se lee después con palabras: un tamaño de texto del 120 %, una distancia de 5 km, un precio de $100 a $300. Un control deslizante sin nada más no tiene ninguna etiqueta que se dibuje, y su pista no dice en qué valor está. El campo de control deslizante es el caso corriente, listo para usarse: una etiqueta, el valor con palabras, la pista, una línea de ayuda y un error.
Se compone de un campo y un control deslizante. El campo es el marco: la etiqueta, la marca de obligatorio o de opcional, el texto del valor al final de la fila de la etiqueta, la ayuda y el error. El control deslizante es el control: la pista, los tiradores y todo lo que la persona hace con ellos. El campo de control deslizante no dibuja nada propio y no tiene ningún token: todas sus propiedades son propiedades de uno de los dos, que recibe sin cambios, excepto valueHidden, que es propia.
Es tan ancho como el lugar en el que se pone, y su pista lo llena.
En la web es <tanrei-slider-field>. Las demás plataformas todavía no lo han implementado.
value es el valor del tirador, y el del tirador de fin de un intervalo; startValue es el del tirador de inicio del intervalo. Los dos eventos son los del propio control deslizante: input con cada cambio mientras la persona arrastra, y change una vez cuando el cambio ha terminado. Cuando se oye cualquiera de los dos, el value y el startValue del campo ya son los nuevos.
<form>
<tanrei-slider-field name="text-size" label="Tamaño del texto"
supporting-text="Se aplica a todas las páginas."
min="50" max="200" step="10" value="120"></tanrei-slider-field>
<!-- Un intervalo envía start-value y después value, con el mismo nombre. Da nombre a cada tirador. -->
<tanrei-slider-field name="price" label="Precio" range
min="0" max="500" step="10" start-value="100" value="300"
start-label="Precio mínimo" end-label="Precio máximo"></tanrei-slider-field>
</form>
<script type="module">
import '@tanrei/web/components/slider-field';
// Las palabras para un valor, dadas una sola vez: una propiedad, nunca un atributo.
const percent = new Intl.NumberFormat(document.documentElement.lang, { style: 'percent' });
const size = document.querySelector('[name="text-size"]');
size.formatValue = (value) => percent.format(value / 100);
size.addEventListener('input', () => applyTextSize(size.value));
const dollars = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
document.querySelector('[name="price"]').formatValue = (value) => dollars.format(value);
</script>import { SliderField } from '@tanrei/react';
<SliderField name="text-size" label="Tamaño del texto" supportingText="Se aplica a todas las páginas."
min={50} max={200} step={10} value={size}
formatValue={(value) => percent.format(value / 100)}
onInput={(event) => setSize(event.currentTarget.value)} />El valor se dibuja al final de la fila de la etiqueta, con las palabras que el control deslizante da a su tirador: las mismas que oye un lector de pantalla y que muestra el indicador de valor. Son, en este orden:
| Las palabras | Cuándo |
|---|---|
valueText, y startValueText para el tirador de inicio de un intervalo |
Escribes tú las palabras, y las vuelves a escribir en cada input. |
Lo que escribe formatValue |
Das una sola vez una función que va de un valor a sus palabras. El control deslizante se la pide para cada tirador en cada cambio. |
| El número en la configuración regional de la página | No se da ninguna de las dos cosas. |
Los dos valores de un intervalo se unen con una raya corta, en el orden de lectura: en un diseño de derecha a izquierda, las palabras del inicio quedan a la derecha, donde está el tirador de inicio. El campo de control deslizante no escribe por sí mismo ningún número, unidad ni palabra.
Un texto del valor que comparte la línea de la etiqueta, otro que ocupa una línea propia y un campo que lo oculta
El texto del valor se apoya en la línea de base de la primera línea de la etiqueta, y la etiqueta salta de línea en el sitio que queda. Donde eso dejaría a la etiqueta menos de la mitad de la fila, el texto del valor ocupa una línea propia después de la etiqueta, y salta de línea ahí si hace falta. valueHidden lo omite, para un control deslizante cuyo número no significa nada para la persona: un volumen, un brillo. El tirador sigue diciendo su valor a la tecnología de apoyo.
El mismo campo, escrito a mano con sus dos miembros, es la misma imagen y el mismo control deslizante para la tecnología de apoyo:
<tanrei-field label="Tamaño del texto" supporting-text="Se aplica a todas las páginas." value-text="120 %">
<tanrei-slider name="text-size" min="50" max="200" step="10" value="120"></tanrei-slider>
</tanrei-field>
<script type="module">
const field = document.querySelector('tanrei-field');
const slider = field.querySelector('tanrei-slider');
slider.formatValue = (value) => percent.format(value / 100);
// Lo que el campo de control deslizante hace por sí mismo: el texto del valor del campo es el del control deslizante, en cada cambio.
slider.addEventListener('input', () => (field.valueText = slider.shownValueText));
</script>El mismo campo escrito a mano: un campo con un control deslizante dentro, que recibe el texto del valor una sola vez; sin el listener de arriba no se mantiene sincronizado
Baja a ese nivel cuando necesites una organización que el campo de control deslizante no ofrezca:
| Necesitas | Usa |
|---|---|
| Una etiqueta, el valor con palabras, la pista, ayuda y un error | El campo de control deslizante |
| Un texto del valor que el control deslizante no dice (una frase, «Cualquier precio»), o algo tuyo dentro del marco | Un campo con un control deslizante dentro, y tu propio value-text |
| La pista sola, con el nombre de algo que se dibuja en otro lugar: la columna de una tabla, el glifo de una barra de herramientas, el control de volumen de un reproductor | El control deslizante sin nada más, con su propio label como nombre |
| Un control deslizante vertical | El control deslizante sin nada más: el campo de control deslizante no tiene orientación |
| Un valor que se conoce y se escribe | Un campo numérico, solo o junto a un control deslizante |
Lo que cambia un nivel más abajo es dónde se dicen las cosas. name, value y startValue están en el control deslizante, que es entonces el control que encuentra el formulario, y sus eventos se oyen en él. label y disabled se quedan en el campo, que los pasa al control deslizante. El tirador de fin de un intervalo recibe su nombre del label del propio control deslizante, que el campo de control deslizante llama endLabel.
Obligatorio con la palabra del producto, opcional, en error y deshabilitado
| Aspecto | Del campo | Del control deslizante |
|---|---|---|
| Propiedades | label, labelHidden, supportingText, errorText, error, disabled, required, optional, requiredMark, requiredText, optionalText |
value, startValue, range, min, max, step, origin, stops, size, valueIndicator, valueText, startValueText, startLabel y endLabel, que es el label del control deslizante |
| Eventos | — | input, change |
| Slots | label-icon |
— |
| Tokens | comp.field.* |
comp.slider.* |
Una propiedad es propia del campo de control deslizante: valueHidden. Y una propiedad del campo la rellena el propio campo de control deslizante, y no te corresponde definirla: el valueText del campo, a partir de las palabras del control deslizante.
El control deslizante tiene un disabled y un orientation propios. Ninguno de los dos es una propiedad del campo de control deslizante: el disabled del campo deshabilita el control deslizante, para que la etiqueta y el texto del valor lo sigan, y la pista siempre va en la dirección en línea: un campo de control deslizante no tiene orientación vertical.
Un control deslizante siempre tiene un valor, así que required no significa aquí «no vacío». Un formulario que marca cada control como obligatorio u opcional marca también este; lo que rechaza (un nivel de 0, un intervalo demasiado estrecho) te corresponde decirlo a ti con error y errorText. Un error no cambia nada de la pista: lo transmiten las palabras y el estado no válido.
Lo que hacen los tiradores (el arrastre, las teclas, los pasos, el indicador de valor) está en la página del control deslizante. Lo que hace el marco (la marca de obligatorio, el texto del valor, la ayuda, el error y cómo se anuncia) está en la página del campo.
El campo de control deslizante no tiene ningún token propio. Su marco lee los tokens del campo y su pista lee los del control deslizante, se definan donde se definan. Para cambiar una sola instancia, define en ella el token del miembro:
<tanrei-slider-field label="Volumen" value="40"
style="--tanrei-comp-field-standard-value-text-color: var(--tanrei-sys-color-on-surface)"></tanrei-slider-field>Anatomía
Anatomía
default, tal como lo dibuja el paquete web.| Parte | Descripción |
|---|---|
1 field | The Field itself: the label row with its label glyph, its requirement mark and, at its end, the value text; and the supporting row with the help and the error text. Drawn by the Field from the Field's tokens. A member: it frames the component. |
2 slider | The Slider itself, as the Field's one control: its track, active track, handles, stop dots, state layer, value indicator and focus ring, drawn by the Slider from the Slider's tokens. A member: it holds the component's value. |
Propiedades
| Propiedad | Tipo | Valor predeterminado | Descripción |
|---|---|---|---|
label | string | "" | Names the control, visibly and to assistive technology. Required, unless the control names itself (a checkbox or a switch with its own label): then leave it empty and the field adds only help and an error. — Field Drawn above the track and, for one handle, its accessible name. While range is true it is the visible name of the pair, and each handle is named by startLabel and endLabel (SLF-5). |
labelHidden | boolean | false | Does not draw the label, which stays the accessible name. For a control whose visible label is elsewhere (a table column, a toolbar). — Field The label row takes the value text with it (FLD-29). |
supportingText | string | "" | Help shown below the control and given to assistive technology as the control's description. While the field is in error it gives way to errorText, unless the design system keeps both (comp.field.error-text.placement append). — Field |
errorText | string | "" | Shown while error is true, in supportingText's place — or below it, which then stays, where the design system's comp.field.error-text.placement is append: what is wrong and how to put it right, in words. — Field |
error | boolean | false | Puts the field in the error condition: the error text is drawn, the control is exposed as invalid and, where it has an error condition of its own, drawn in it. What a value means is the product's to validate; the field never sets this itself. — Field A slider has no error condition of its own to draw (FLD-8): the track and the handles stay as they are, and each handle is exposed as invalid. |
disabled | boolean | false | Disables the control and draws the frame as disabled. Disable a framed control here, not on the control, so that its label follows. — Field The one disabled of the slider field: the Field passes it to the Slider (FLD-14, SLD-20), whose own disabled is not a prop here, so that the label and the value text always follow. |
required | boolean | false | What the form asks of the control: true exposes it as required and draws the required mark beside the label. It never validates: a missing answer is the product's to report with error. — Field |
optional | boolean | false | Draws the optional tag after the label and adds optionalText to the control's description, because assistive technology has no state for it. Ignored while required is true: a control is never both. — Field |
requiredMark | auto | tag | asterisk | none | "auto" | How this control shows that it is required: tag is a small filled Tag with requiredText, asterisk is "*" after the label, none draws nothing and keeps the semantics. Auto takes comp.field.requirement.mark, which follows sys.behavior.requirement-mark, the system's one answer. Ignored unless required is true. — Field |
requiredText | string | "" | The text of the required tag, in the product's language ("Required", "必須"). The product's: Tanrei has no word for it. Empty reads the product's words; with neither, FLD-24 says what is drawn. — Field |
optionalText | string | "" | The text of the optional tag, in the product's language ("Optional", "任意"); also read to assistive technology as part of the description. The product's: Tanrei has no word for it. Empty reads the product's words. — Field |
value | number | 0 | The value of the only handle, or of a range's end handle. — Slider |
startValue | number | 0 | The value of a range's start handle. Ignored while range is false. — Slider |
range | boolean | false | Draws two handles, choosing the range from startValue to value (a price filter). — Slider |
min | number | 0 | The lowest value, at the track's start. — Slider |
max | number | 100 | The highest value, at the track's end. — Slider |
step | number | 0 | 0 is continuous. Above 0 the slider is discrete: its values are min plus whole multiples of step, up to max. — Slider |
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. — Slider |
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. — Slider |
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. — Slider Changes nothing of the frame. |
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. — Slider |
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. — Slider Also drawn at the end of the label row (SLF-3). |
startValueText | string | "" | The start handle's valueText, for a range. — Slider |
startLabel | string | "" | Names a range's start handle ("Minimum price"). Required while range is true. — Slider |
endLabel | 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. — Slider The Slider's label under the name of the handle it names, because label is the visible name here. Read only while range is true, and required then (SLF-5). |
valueHidden | boolean | false | Does not draw the value at the end of the label row. For a slider set by feel, whose number means nothing to the person (a volume, a brightness). The handle still says its value to assistive technology, and valueIndicator still shows it. |
Slots
| Slot | Descripción |
|---|---|
label-icon | A glyph before the label. — Field |
Eventos
| Evento | Descripción |
|---|---|
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. — Slider |
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. — Slider |
Estados
Comportamiento
Requisitos en formato EARS. Cada implementación de plataforma se prueba contra estos identificadores. El texto de los requisitos se muestra tal como está en la especificación, en inglés.
| ID | Requisito |
|---|---|
SLF-1 | THE slider field SHALL be a Field whose one control is a Slider — the two components themselves, each drawn from its own tokens in every state and behaving by its own sentences (FLD-1 to FLD-24, FLD-29 and FLD-30; SLD-1 to SLD-26) — and SHALL draw nothing of its own, have no token of its own, and give neither member a look, a state or a size that the member does not have where it stands alone. |
SLF-2 | THE slider field SHALL give each member the value of every prop that is that member's, at once and whenever it changes, and SHALL hold none back: the Field takes label, labelHidden, supportingText, errorText, error, disabled, required, optional, requiredMark, requiredText, optionalText and the glyph of the label-icon slot; the Slider takes value, startValue, range, min, max, step, origin, stops, size, valueIndicator, valueText, startValueText, startLabel and, as its own label, endLabel. THE slider field SHALL give the Slider no orientation, so that the track always runs along the line (SLD-21), and SHALL NOT set the Slider's own disabled: the Field disables its control (FLD-14). |
SLF-3 | WHILE valueHidden is false THE slider field SHALL give the Field, as its value text (FLD-29), the words the Slider gives its handle as that handle's value (SLD-18): WHILE range is false the only handle's; WHILE range is true the start handle's, an en dash with a space on each side, and the end handle's, each of the two an isolated run and the two in reading order, so that in a right-to-left layout the start's words stand at the right of the dash as the start handle stands at the right of the track. THE slider field SHALL NOT write a number, a unit or a word itself. WHILE valueHidden is true THE slider field SHALL give the Field no value text. |
SLF-4 | WHEN a value changes — at every input of a drag, by a key, by assistive technology, because the product set value or startValue, or because min, max or step changed what the Slider draws (SLD-22) — or valueText, startValueText or the product's function for a value changes, THE slider field SHALL show the new value text in the same frame in which the handle is drawn at its new place, without a motion and without an announcement of its own: the handle says its value to assistive technology itself (SLD-19), and the Field keeps the drawn text from it (FLD-30). |
SLF-5 | WHILE range is false THE slider field SHALL have its handle named by label, as the Field names its control (FLD-10). WHILE range is true THE slider field SHALL have the start handle named by startLabel and the end handle by endLabel (SLD-19), which should each hold the words of label so that what is seen is in what is heard, and WHILE either is empty SHALL have that handle named by label and in debug builds report that a handle of a range has no name of its own. THE slider field SHALL have every handle described by the text the supporting row shows, with optionalText while optional is true (FLD-11), and exposed as invalid while error is true (FLD-8); WHILE required is true it SHALL have every handle exposed as required where the platform's slider has such a state and, where it has none (the web's slider role), SHALL have requiredText added to the handle's description instead. |
SLF-6 | THE slider field SHALL hold value and startValue as its own and report them as the Slider does: WHEN the Slider emits input or change THE slider field SHALL emit the same event exactly once, carrying value and, for a range, startValue (SLD-2 to SLD-4), with its own value and startValue already equal to what the event carries; WHEN the product sets value or startValue THE slider field SHALL emit nothing (SLD-16). WHERE the platform has forms THE slider field SHALL be the one control the form sees — it carries the name, submits what the Slider submits, is reset and restored as the Slider is, and submits nothing WHILE disabled is true — and neither member SHALL be a second one. |
SLF-7 | THE slider field SHALL add no stop to the focus order and handle no key: its only focus stops are the Slider's handles, in the Slider's order (SLD-5), and every key is the Slider's (SLD-3). WHEN focus is given to the slider field itself, or the person presses the label row (FLD-12), THE slider field SHALL move focus to the only handle and, WHILE range is true, to the start handle, and SHALL change no value. |
SLF-8 | WHILE disabled is true THE slider field SHALL be a disabled Field holding a disabled Slider (FLD-14, SLD-20): no handle takes focus or changes, no event is emitted, the value indicator is not shown, and the label, the requirement mark, the supporting row and the value text are drawn from the Field's disabled tokens; THE slider field SHALL keep the value text drawn, because what a disabled control is set to is still read. |
SLF-9 | WHILE the text size is enlarged THE slider field SHALL grow as the Field grows (FLD-16) and SHALL leave the Slider's track, handles and hit area as they are (SLD-7); at 200% in a width of 320 no text SHALL be cut, lie over another part or need scrolling in two directions: the label wraps beside the value text, and a value text too wide to share the label's line moves whole to a line of its own (FLD-29). |
SLF-10 | THE slider field SHALL take its layout direction from where it is used and have no direction setting of its own, and its two members SHALL take the same one (FLD-19, SLD-25). WHERE the layout direction is right-to-left the frame and the track mirror together — the label row starts at the right with the value text at its left end (FLD-18), the track runs from the right (min) to the left (max) and the arrow keys follow it (SLD-21) — and the words of a value SHALL NOT be mirrored: each is laid out as text of its own direction (FLD-21, SLD-26), so that a number keeps its digits, its sign and its unit in their own order. |
SLF-11 | WHERE the platform draws with a person's own forced colors THE slider field SHALL add nothing and remove nothing: the Field draws its texts as FLD-17 says and the Slider its track and handles as it does standing alone, and the error SHALL still be carried by the words of errorText and by the invalid state of each handle (FLD-8), never by a color. |
SLF-12 | THE slider field SHALL be, in what is drawn and in what assistive technology is told, exactly what a Field holding a Slider is when a product writes the two by hand with the same props and gives the Field the same value text, which is the one prop of a member the slider field fills itself: every fixture of the slider field and its twin among the Field's fixtures are the same picture, with the same names, descriptions, values and states, and a difference is a defect of the slider field. |
SLF-13 | THE slider field SHALL be a block as wide as its place in the layout, with no width of its own, and its Slider SHALL fill it from the start edge to the end edge, as a Slider standing in a Field does (FLD-1); the label row and the supporting row are as wide as the track's box. |
SLF-14 | 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 field 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 — 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 field is invalid — except those the slider field owns (aria-label, aria-labelledby, aria-disabled), which it SHALL move and not expose: its name is label (SLF-5). 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 field SHALL take it off that element. WHEN the product sets an aria- attribute the slider field owns THE slider field SHALL report it in debug builds. |
Correspondencia de nombres por plataforma
Paridad no significa API idénticas. Cada plataforma expresa el mismo contrato con su propio estilo.
| Especificación | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| Componente | tanrei-slider-field | TanreiSliderField | TanreiSliderField | TanreiSliderField | SliderField |
label · Propiedad | label | label | label | labelText | label |
labelHidden · Propiedad | labelHidden | labelsHidden | labelHidden | labelHidden | labelHidden |
supportingText · Propiedad | supportingText | supportingText | supportingText | helperText | supportingText |
errorText · Propiedad | errorText | errorText | errorText | errorText | errorText |
error · Propiedad | error | error | isError | isError | error |
disabled · Propiedad | disabled | disabled | enabled | enabled | disabled |
required · Propiedad | required | isRequired | required | required | required |
optional · Propiedad | optional | isOptional | optional | optional | optional |
requiredMark · Propiedad | requiredMark | requiredMark | requiredMark | requiredMark | requiredMark |
requiredText · Propiedad | requiredText | requiredText | requiredText | requiredText | requiredText |
optionalText · Propiedad | optionalText | optionalText | optionalText | optionalText | optionalText |
value · Propiedad | value | value | value | value | value |
startValue · Propiedad | startValue | value | value | start | startValue |
range · Propiedad | range | value | value | range | range |
min · Propiedad | min | bounds | valueRange | min | minimumValue |
max · Propiedad | max | bounds | valueRange | max | maximumValue |
step · Propiedad | step | step | step | step | step |
origin · Propiedad | origin | origin | origin | origin | origin |
stops · Propiedad | stops | showsStops | showStops | showStops | stops |
size · Propiedad | size | size | size | size | size |
valueIndicator · Propiedad | valueIndicator | valueIndicator | valueIndicator | valueIndicator | valueIndicator |
valueText · Propiedad | valueText | valueText | stateDescription | semanticValue | valueText |
startValueText · Propiedad | startValueText | startValueText | startStateDescription | startSemanticValue | startValueText |
startLabel · Propiedad | startLabel | startLabel | startContentDescription | startSemanticLabel | startAccessibilityLabel |
endLabel · Propiedad | endLabel | endLabel | endContentDescription | endSemanticLabel | endAccessibilityLabel |
valueHidden · Propiedad | valueHidden | valueHidden | valueHidden | valueHidden | valueHidden |
input · Evento | input | value | onValueChange | onChanged | onValueChange |
change · Evento | change | onCommit | onValueChangeFinished | onChangeEnd | onSlidingComplete |
| Notas | Class TanreiSliderField; React SliderField. A custom element with a shadow root that holds its members' own elements, composed as every field element is: <tanrei-field> in the shadow root, and in its default slot one <tanrei-slider> with no label of its own while range is false; the host's label-icon slot is passed on to the Field's. The host is display: block and as wide as its place (SLF-13). What differs here: (1) static formAssociated = true on the host, which carries name, submits what the Slider submits (the value; for a range the start value and then the value under the same name), and resets and restores it — the inner Slider has no name and is outside the form; (2) the shadow root does not delegate focus, because a press on the help or the error text must do nothing (FLD-12): focus() is overridden to go to the first handle, and the Slider's own shadow root delegates as before; (3) input and change leave the shadow root once each with the host as their target, after the host's value and startValue are set; (4) exportparts gives the Slider's documented parts under their own names and the Field's under theirs, with the two members' hosts as the parts field and slider, and the host has no other part of its own; (5) the host writes the Field's value-text from the Slider's value text at every input, in the same task, and joins a range's two in two <bdi> runs with an en dash between; (6) formatValue is a property of the host, never an attribute, ((value: number) => string) | null, null by default, handed to the Slider (field.formatValue = (value) => percent.format(value / 100)). Attributes are kebab-case and are the members': label-hidden, supporting-text, error-text, required-mark, required-text, optional-text, start-value, value-indicator, value-text, start-value-text, start-label, and end-label, value-hidden. No custom property of a member is written by the host: a token set on the host for one instance (--tanrei-comp-field-…, --tanrei-comp-slider-…) reaches the member by inheritance. Words: required-text and optional-text left empty read setWords(), as the Field's do. One level down, the same picture and the same tree: <tanrei-field label="Volume" value-text="40"><tanrei-slider name="volume" value="40"></tanrei-slider></tanrei-field>, with the product writing value-text at each input. With scripting off nothing of it is drawn and nothing is submitted, as for every control with a shadow root. | Planned. Not built on this platform yet, nor is this platform's Field: TanreiSliderField(_ label:, value: Binding<Double>, in bounds: ClosedRange<Double> = 0...100, step:, supportingText:, errorText:, error:, required:, optional:, format: ((Double) -> String)? = nil), a view whose body is TanreiField(label, valueText: …) { TanreiSlider(value: $value, in: bounds, …) }; a range is the initializer whose value is a Binding<ClosedRange<Double>> and which takes startLabel and endLabel. labelHidden follows .labelsHidden() and disabled follows .disabled(_:), as the Field's do. One field set apart: .tanreiTheme(_:) on the view. | Planned. Not built on this platform yet, nor is this platform's Field: TanreiSliderField(label = "Volume", value = volume, onValueChange = { volume = it }, valueRange = 0f..100f, supportingText = …, isError = …, format: ((Float) -> String)? = null), a composable that calls TanreiField(label, valueText = …) { TanreiSlider(…) }; a range is the overload whose value is a ClosedFloatingPointRange<Float>. enabled is the inverse flag. The Slider's names are kept for what is its own (stateDescription), though the slider field also draws that text. One field set apart: TanreiTheme(…) { } around the call. | Planned. Not built on this platform yet, nor is this platform's Field: TanreiSliderField(labelText: 'Volume', value: volume, onChanged: (v) => …, helperText: …, errorText: …, isError: …, format: (double value) => …), a widget that builds TanreiField(labelText:, valueText:, child: TanreiSlider(…)); a range is the named constructor TanreiSliderField.range(start:, end:, onChanged: (start, end) {…}). enabled is the inverse flag; a null onChanged also disables it, as the Slider's does. One field set apart: a TanreiTheme widget around it. | Planned. Not built on this platform yet, nor is this platform's Field: <SliderField label="Volume" value={volume} onValueChange={setVolume} supportingText="…" formatValue={(value) => …} />, a component that renders <Field label valueText={…}><Slider … /></Field>; a range adds range and startValue, and both callbacks receive (value, startValue). One field set apart: a provider around it. |
Tokens
| Token | Alias de | Valor resuelto (claro) |
|---|---|---|
--tanrei-comp-field-counter-gap | sys.space.space200 | 16px |
--tanrei-comp-field-error-text-gap | sys.space.space50 | 4px |
--tanrei-comp-field-error-text-placement | — | 0 |
--tanrei-comp-field-label-icon-gap | sys.space.space100 | 8px |
--tanrei-comp-field-label-icon-size | sys.icon.small | 20px |
--tanrei-comp-field-label-gap | sys.space.space100 | 8px |
--tanrei-comp-field-motion-state-duration | sys.motion.role.state.default | 250ms |
--tanrei-comp-field-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-field-requirement-asterisk-gap | sys.space.space25 | 2px |
--tanrei-comp-field-requirement-gap | sys.space.space100 | 8px |
--tanrei-comp-field-requirement-mark | sys.behavior.requirement-mark | 0 |
--tanrei-comp-field-standard-counter-color | sys.color.on-surface-variant | |
--tanrei-comp-field-standard-disabled-counter-color | — | |
--tanrei-comp-field-standard-disabled-error-text-color | — | |
--tanrei-comp-field-standard-disabled-error-counter-color | — | |
--tanrei-comp-field-standard-disabled-error-label-icon-color | — | |
--tanrei-comp-field-standard-disabled-error-label-color | — | |
--tanrei-comp-field-standard-disabled-error-required-asterisk-color | — | |
--tanrei-comp-field-standard-disabled-error-supporting-text-color | — | |
--tanrei-comp-field-standard-disabled-error-value-text-color | — | |
--tanrei-comp-field-standard-disabled-label-icon-color | — | |
--tanrei-comp-field-standard-disabled-label-color | — | |
--tanrei-comp-field-standard-disabled-required-asterisk-color | — | |
--tanrei-comp-field-standard-disabled-supporting-text-color | — | |
--tanrei-comp-field-standard-disabled-value-text-color | — | |
--tanrei-comp-field-standard-error-text-color | sys.color.error | |
--tanrei-comp-field-standard-error-counter-color | sys.color.on-surface-variant | |
--tanrei-comp-field-standard-error-label-icon-color | sys.color.on-surface-variant | |
--tanrei-comp-field-standard-error-label-color | sys.color.on-surface | |
--tanrei-comp-field-standard-error-required-asterisk-color | sys.color.primary | |
--tanrei-comp-field-standard-error-supporting-text-color | sys.color.on-surface-variant | |
--tanrei-comp-field-standard-error-value-text-color | sys.color.on-surface-variant | |
--tanrei-comp-field-standard-focused-counter-color | — | |
--tanrei-comp-field-standard-focused-error-text-color | — | |
--tanrei-comp-field-standard-focused-error-counter-color | — | |
--tanrei-comp-field-standard-focused-error-label-icon-color | — | |
--tanrei-comp-field-standard-focused-error-label-color | — | |
--tanrei-comp-field-standard-focused-error-required-asterisk-color | — | |
--tanrei-comp-field-standard-focused-error-supporting-text-color | — | |
--tanrei-comp-field-standard-focused-error-value-text-color | — | |
--tanrei-comp-field-standard-focused-label-icon-color | — | |
--tanrei-comp-field-standard-focused-label-color | — | |
--tanrei-comp-field-standard-focused-required-asterisk-color | — | |
--tanrei-comp-field-standard-focused-supporting-text-color | — | |
--tanrei-comp-field-standard-focused-value-text-color | — | |
--tanrei-comp-field-standard-label-icon-color | sys.color.on-surface-variant | |
--tanrei-comp-field-standard-label-color | sys.color.on-surface | |
--tanrei-comp-field-standard-required-asterisk-color | sys.color.primary | |
--tanrei-comp-field-standard-supporting-text-color | sys.color.on-surface-variant | |
--tanrei-comp-field-standard-value-text-color | sys.color.on-surface-variant | |
--tanrei-comp-field-supporting-text-gap | sys.space.space50 | 4px |
--tanrei-comp-field-value-text-gap | sys.space.space200 | 16px |
--tanrei-comp-field-label-typescale | sys.typescale.label | 500 14px/1.4286 |
--tanrei-comp-field-supporting-text-typescale | sys.typescale.label-small | 500 12px/1.3333 |
--tanrei-comp-field-value-text-typescale | sys.typescale.label | 500 14px/1.4286 |
Fixtures
Representaciones canónicas. Todas las plataformas capturan cada fixture con el mismo identificador para poder comparar los resultados.
default
label: Volume value: 40 supporting
label: Volume supportingText: Applies to alerts and media. value: 40 value-words
label: Text size value: 120 min: 50 max: 200 step: 10 valueText: 120 % value-hidden
label: Volume value: 40 valueHidden: true value-indicator
label: Volume value: 40 valueIndicator: always range
label: Price value: 60 startValue: 20 range: true startLabel: Minimum price endLabel: Maximum price range-words
label: Price supportingText: Per night, before taxes. value: 300 startValue: 100 range: true min: 0 max: 500 valueText: $300 startValueText: $100 startLabel: Minimum price endLabel: Maximum price required
label: Volume required: true requiredText: Required value: 40 optional
label: Volume optional: true optionalText: Optional value: 40 required-asterisk
label: Volume required: true requiredMark: asterisk value: 40 error
label: Volume supportingText: Applies to alerts and media. errorText: Choose a level above 0. error: true value: 0 required-error
label: Volume errorText: Choose a level above 0. error: true required: true requiredText: Required value: 0 error-without-text
label: Volume supportingText: Applies to alerts and media. error: true value: 0 disabled
label: Volume supportingText: Applies to alerts and media. disabled: true value: 40 label-hidden
label: Volume labelHidden: true supportingText: Applies to alerts and media. value: 40 label-icon
label: Volume value: 40 slots: label-icon long-label
label: How loud alerts, calls and media are pla… supportingText: A level the connected device cannot play… required: true requiredText: Required value: 40 long-value-text
label: Yearly income before tax value: 12500000 startValue: 3400000 range: true min: 0 max: 20000000 step: 100000 valueText: 12,500,000 startValueText: 3,400,000 startLabel: Lowest yearly income endLabel: Highest yearly income required-ja
label: 音量 supportingText: 通知とメディアに適用されます。 required: true requiredText: 必須 value: 40 error-ja
label: 音量 errorText: 0 より大きい値を選んでください。 error: true required: true requiredText: 必須 value: 0 rtl
label: مستوى الصوت supportingText: ينطبق على التنبيهات والوسائط. required: true requiredText: مطلوب value: 40 direction: rtl slots: label-icon error-rtl
label: עוצמת קול errorText: יש לבחור רמה מעל 0. error: true optional: true optionalText: רשות value: 0 direction: rtl range-rtl
label: السعر value: 300 startValue: 100 range: true min: 0 max: 500 valueText: $300 startValueText: $100 startLabel: أدنى سعر endLabel: أعلى سعر direction: rtl Generado a partir de specs/slider-field.spec.json, tokens/comp/field.tokens.json, design/tokens/
- El shadow root del elemento contiene un
<tanrei-field>con un<tanrei-slider>dentro, y nada más. Importar el elemento define los dos. - El elemento está asociado a formularios. Recibe
nameyform, envía el valor (un intervalo envía el valor de inicio y después el valor, con el mismo nombre; nada mientras está deshabilitado), se restablece a los valores de los atributosvalueystart-value, y sigue a un<fieldset>deshabilitado. Sus dos miembros no añaden ninguna entrada al formulario. inputychangeson los CustomEvents del control deslizante, condetail.value(ydetail.startValueen un intervalo). El destino de los dos es el elemento, yevent.target.valuees el valor nuevo en todos los listeners.formatValuees una propiedad y nunca un atributo:(value: number) => string, onull.- Los dos textos del valor de un intervalo se escriben en el único texto del
value-textdel campo, con una raya corta entre ellos. Cada uno es un tramo con su propia dirección (envuelto en un aislamiento de primer carácter fuerte, U+2068 y U+2069), a menos que sea un número sencillo como «$100» o «3,400,000», que ya es un solo tramo de izquierda a derecha en cualquiera de las dos direcciones y se escribe tal cual. - Partes:
fieldysliderson los dos miembros. Sus propias partes tienen aquí los mismos nombres que un nivel más abajo:label,label-icon,requirement-label,value-text,supporting-text;track,active-track,stop-indicator,container,handle,value-indicator. - El elemento no puede recibir el foco por sí mismo:
focus()va al tirador, o al tirador de inicio de un intervalo, y un<label for>propio de la página lleva el foco allí. - El elemento no tiene rol. Dale nombre con
label—conlabel-hiddendonde la etiqueta se dibuja en otro lugar— y nunca conaria-label, que aquí no nombra nada. - Los atributos son los de los propios miembros:
label-hidden,supporting-text,error-text,required-mark,required-text,optional-text,start-value,value-indicator,value-text,start-value-text,start-label; yend-label,value-hidden. - Antes de que el elemento esté definido no tiene tamaño y solo muestra un hijo
label-icon. Una página que deba funcionar sin script usa un<label>alrededor de un<input type="range">sencillo.
- Da las palabras para un valor con
formatValuecuando el número solo no quedaría claro: un porcentaje, una moneda, una unidad. - Da nombre a los dos tiradores de un intervalo, con
startLabelyendLabel, con palabras que contengan las delabel: «Precio mínimo», «Precio máximo» bajo «Precio». - Di en
supportingTextqué cambia el valor, donde la etiqueta no lo diga. - Di con palabras qué se rechaza, con
erroryerrorText. - Usa
valueHiddenpara un valor que se define a ojo y cuyo número no le dice nada a la persona.
- No escribas
valueTextuna sola vez en el marcado para un control deslizante que la persona puede mover: las palabras serían falsas después del primer arrastre. DaformatValue, o vuelve a escribirvalueTexten cadainput. - No pongas un campo de control deslizante dentro de un campo. Ya es un campo; una compilación de depuración lo dice.
- No le des nombre con
aria-label. Donde no deba dibujarse ninguna etiqueta, dalabelylabelHidden. - No uses
valueIndicator="always"para mostrar el valor: eso lo hace el texto del valor, y el indicador quedaría encima de la fila de la etiqueta. - No uses un campo de control deslizante para un valor que debe ser exacto. Usa un campo numérico, solo o junto a él.
- Rol
slider- Etiquetado
- The slider field has no role of its own: assistive technology meets the Slider's handles, each a slider (SLD-19), What the slider field ties together (SLF-5): label is the accessible name of the only handle; a range's two handles are named by startLabel and endLabel; the supporting text with, in error, the error text after it is every handle's description, with optionalText while optional is true; every handle is invalid while error is true and required, or described by requiredText where the role has no required state, while required is true. Each handle's value is said in the words of SLD-18 — valueText, or what the product's function writes, or the platform's number — and the same words are drawn at the end of the label row, where they are kept from assistive technology so that a value is not read twice (FLD-30).
- Objetivo mínimo
- El área de pulsación cumple el tamaño mínimo de objetivo aunque el tamaño visual sea menor. minimum 32px · pointer 44px · spacing 8px · touch 48px
Teclado
| Teclas | Acción |
|---|---|
| Tab / Shift+Tab | Moves focus to the handle — for a range to the start handle, then the end handle — and on from it: the stops are the Slider's, and the slider field adds none (SLF-7). |
| Every other key | The Slider's own, as its spec's keyboard table says (SLD-3). The slider field handles no key. |
Notas
- Everything else is a member's and is said in its spec: the Field's rows, requirement marks, error announcement and press on the label (FLD-2 to FLD-12); the Slider's roles, value limits, target size and contrast (SLD-7, SLD-19 and its accessibility notes).
- A value a person cannot read is a value only some people are told. The handle says its value to assistive technology, and a track does not say it to the eye; the value text at the end of the label row is drawn unless valueHidden says the number means nothing to the person.
- A number with a unit is words, and the words are the product's: valueText for a value the product writes itself, or one function from a value to its words, given once, which the Slider asks at every change (SLD-18). The slider field writes none, and joins a range's two with an en dash, which is a mark.
- A slider always has a value, so required does not mean "not empty" here: a product that marks every control of a form as required or optional marks this one too, and says with error and errorText what it refuses (a level of 0, a range too narrow).
- Dragging is never the only way (WCAG 2.5.7): a press on the track moves the handle to it, and the keys step it (SLD-2, SLD-3). A value that must be entered exactly is a number field, alone or beside a slider.
- 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.
Generado a partir de specs/slider-field.spec.json, tokens/sys/measure.tokens.json
- Cada tirador es un control deslizante. Un solo tirador recibe su nombre de
label, se dibuje o no; los dos de un intervalo, destartLabely deendLabel, y delabeldonde falta alguno, lo que una compilación de depuración notifica. - Cada tirador tiene como descripción el texto de apoyo o de error que se muestra, con el texto de opcional mientras el campo es opcional, y se expone como no válido mientras
errores true y como deshabilitado mientrasdisabledes true. El rol de control deslizante de la web no tiene estado obligatorio, así que un campo de control deslizante obligatorio dicerequiredTexten la descripción. - Cada tirador dice su valor con palabras. Las mismas palabras se dibujan al final de la fila de la etiqueta, donde quedan ocultas para la tecnología de apoyo, de modo que un valor se lee una sola vez.
- La etiqueta dibujada, la marca de obligatoriedad y el texto del valor no se exponen una segunda vez, y un cambio del texto del valor no se anuncia: el tirador dice su propio valor.
- Sus paradas del foco son los tiradores del control deslizante (uno, o los dos de un intervalo), y todas las teclas son las del control deslizante. Una pulsación en la fila de la etiqueta lleva el foco al tirador y no cambia nada; una pulsación en la ayuda no hace nada.
- Mientras está deshabilitado, el texto del valor se sigue dibujando: el valor en que está un control deshabilitado se sigue leyendo.
- La dirección, el texto ampliado y los colores forzados los resuelve cada miembro por su cuenta: en un diseño de derecha a izquierda, el marco y la pista se reflejan juntos y las palabras de un valor conservan su propio orden; con el texto al 200%, nada se corta y nada se desplaza hacia los lados.
- No tiene textos propios.
requiredTextyoptionalText, si se dejan vacíos, los lee el campo de los textos del producto.
Carencias conocidas en la web: antes de que el elemento esté definido no se dibuja nada, y los dos tiradores de un intervalo no se exponen como un solo grupo que reciba su nombre de label.
- Da
label, siempre, y tambiénstartLabelyendLabelen un intervalo. - Da las palabras del valor cuando un número solo no se entendería, y mantenlas ciertas mientras el valor cambia.
- Di qué se rechaza con
errorText. El color nunca es la única señal. - Ofrece un campo numérico junto al control deslizante donde la persona deba introducir un valor exacto: arrastrar nunca es la única forma de mover un tirador, pero sigue sin ser una forma de escribir un valor.