Continuous dial
A continuous dial is a knob with no stops: every turn adds to its value, so a second full rotation reads 720 rather than starting over. Choose it when the amount turned matters more than where the handle ends up, as with a jog wheel. Press and turn the jog wheel or the scrub wheel below to see its running total.
Reference docs
Choosing sliders and dials
Four components pick a value with a handle the reader drags. Each suits a different job:
- Slider: one value picked along a track, such as volume or brightness.
- Range slider: a low and a high value on one track, such as a price range.
- Dial: one value picked by turning a knob between two stops, such as an oven temperature.
- Continuous dial: a knob with no stops that adds up every turn, such as a jog wheel or a fine-tuning control.
One job belongs elsewhere. An exact number the reader knows is a number field.
Built in
- Its
keeps accumulating in either direction, so turns add up instead of wrapping at 360 degrees (Value and origin).value - Arrow keys move the value by one
, PageUp and PageDown bystep , and Home returns it to 0 (Keyboard and focus).page-value shows the running total above the handle while it is pressed or focused (Value and origin).labeled decides whenchange-modechangefires, from every turn to the end of a drag (Change mode).- It submits its value under
with the form it sits in (Forms).name - Its touch target is at least 48 by 48 pixels, even on the smallest size (Pointer and touch).
Using continuous dials
Material 3 Expressive has no dial, so these rules adapt its guidance for sliders, which a dial resembles.
- Choose a dial when the value has a minimum and a maximum, and a slider when the user should pick a position along a track.
- Bind
tovalue-label when the readout needs units or formatting, since it holds one fixed string.value - Leave
at its default so a small dial keeps a touch area of at least 48 by 48 pixels.touch-target
Value and origin
A continuous dial has no minimum or maximum. value
steppage-valuesteporigin-anglelabeled
Size
sizeextra-small to extra-large, the same five sizes as a bounded dial. Omit it and the dial takes its size from your style configuration, which is extra-small
touch-targetoverflowwrappernone
Forms
A continuous dial takes part in forms. namevaluevalue attribute or, with none, the default of 0.
The preview cannot submit a form, so the demo reads the value from the button's click instead. Your own page submits the form as usual.
Disabled
disabled<fieldset> is disabled too.
Change mode
input fires on every turn. change follows change-modeinteraction-endedimmediatedebouncedthrottledrate-limit-delay
adaptiverate-limit-delaychange against the work in asyncSinksink-duty-cycleasyncSinkasyncSinkthrottledvalueinput event and shows the bound value beside it.
Direction
directionclockwisecounterclockwiseorigin-angle
Tickmarks
tickmarkscontrast-end-stopvaluesnonetrack-background slot replaces the marks, so tickmarks
Properties
| Property | Attribute | Type | Description |
|---|---|---|---|
ariaDescribedBy | aria-describedby | string | The IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found. |
ariaDescription | aria-description | string | Not announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found. |
ariaErrorMessage | aria-errormessage | string | The ID of the element describing the value's error. Used only while ariaInvalid is "true". |
ariaInvalid | aria-invalid | string | Whether the control's value is invalid. A screen reader announces it; the control's appearance does not change. |
ariaLabelledBy | aria-labelledby | string | The IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label. |
asyncSink | ValueChangeSink | The async work, such as a request to a server, that ChangeEventMode.Adaptive paces change events against: the control asks for the next one only when the last has finished, no faster than rateLimitDelay. A slow sink is asked less often, and is not called once per value change. Read the control's value inside it, as a change listener would. Ignored in every other mode. See Change mode. | |
changeMode | change-modedebounced, immediate, interaction-ended, throttled, adaptive | ChangeEventModeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEnded | When the control fires change while the user is still moving it. Debounced, Throttled and Adaptive are paced by rateLimitDelay, which Adaptive treats as a target, and Adaptive also paces against asyncSink. See Change mode. |
direction | directionclockwise, counterclockwise | DialDirectionDialDirection.Clockwise, .CounterClockwisedefault DialDirection.Clockwise | Sets which way the value increases around the dial, measured from originAngle. See Direction. |
disabled | disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
formread-only | HTMLFormElement | The form the component belongs to, or null when it has none. | |
labeled | labeled | booleandefault false | Whether a label with the handle's value appears while the handle is pressed or focused. It stays briefly after a press ends. See Value and origin. |
labelsread-only | NodeList | The <label> elements associated with the element. | |
name | name | string | The name the element's value is submitted under with its form. See Forms. |
originAngle | origin-angle | numberdefault 0 | The origin angle offset in degrees from 12 o'clock position. Rotates the entire dial coordinate system. For example, setting this to 90° makes the right side (3 o'clock) the zero position: a value is measured from originAngle in the dial's direction, both where it is drawn and where a press reads it. The value is cumulative rotation and is not wrapped to 0-360°.An assignment that is not a finite number is ignored, and originAngle keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin, Direction. |
pageValue | page-value | number | How far PageUp and PageDown move the value. Defaults to ten times step.An assignment that is not a finite number is ignored, and pageValue keeps the value it already had. Assigning null or undefined unsets it, restoring the default. See Value and origin. |
rateLimitDelay | rate-limit-delay | numberdefault 150 | The delay in milliseconds that paces change events in the Debounced, Throttled and Adaptive change modes. Other modes ignore it.An assignment that is not a finite number is ignored, and rateLimitDelay keeps the value it already had. null and undefined are ignored on the same rule. See Change mode. |
sinkDutyCycle | sink-duty-cycle | numberdefault 1 | The share of the sink's time this control may occupy, above 0 and up to 1, for ChangeEventMode.Adaptive only. At 1 the next call goes out as soon as the last one finishes. Lower it when the sink is shared, so one person dragging does not saturate it: at 0.25 the control leaves three quarters of the time idle.An assignment that is not a finite number in (0, 1] is ignored, and the property keeps the value it already had. See Change mode. |
size | sizeextra-small, small, medium, large, extra-large | SizeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configuration | Sets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size. |
softDisabled | soft-disabled | booleandefault false | Disables the control but keeps it focusable and in the Tab order. It carries aria-disabled="true", and neither the pointer nor the keyboard changes its value. Use it when a disabled control must stay reachable by keyboard and screen reader. For when this is needed, see WAI-ARIA Authoring Practices: disabled controls. |
step | step | numberdefault 1 | The step between values. Where the control has a range, a step above the range is set to the range, and a step of 0 or less to 1.An assignment that is not a finite number is ignored, and step keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin. |
tickmarks | tickmarksnone, contrast-end-stop, values | SliderTickmarkSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStop | The type of tickmarks to show. Ignored while the track-background slot is filled. See Tickmarks. |
touchTarget | touch-targetnone, overflow, wrapper | TouchTargetTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Size. |
value | value | number | The control's current value.An assignment that is not a finite number -- NaN, Infinity, or a string that does not parse as a number -- is ignored, and value keeps the last valid value it held. Assigning null or undefined unsets it, restoring the default. See Value and origin, Forms, Change mode. |
valueLabel | value-label | string | Text shown and announced in place of the value; if not set, the value itself. A screen reader reads it as the value, and as the control's name when aria-label is not set. |
Slots
| Slot | Description |
|---|---|
track-background | Content that shows through the dial's track in place of its colors. Tickmarks and the end stop are not drawn while it is filled. |
Events
| Event | Type | Detail | Description |
|---|---|---|---|
input | InputEvent | — | Fires during value changes as the user rotates. It bubbles and is composed. |
change | Event | — | Fires when the value is committed (timing controlled by changeMode). It bubbles. |
Setting valueinput nor change.
Props
| Prop | Type | Description |
|---|---|---|
ariaDescribedBy | string | The IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found. |
ariaDescription | string | Not announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found. |
ariaErrorMessage | string | The ID of the element describing the value's error. Used only while ariaInvalid is "true". |
ariaInvalid | string | Whether the control's value is invalid. A screen reader announces it; the control's appearance does not change. |
ariaLabelledBy | string | The IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label. |
asyncSink | ValueChangeSink | The async work, such as a request to a server, that ChangeEventMode.Adaptive paces change events against: the control asks for the next one only when the last has finished, no faster than rateLimitDelay. A slow sink is asked less often, and is not called once per value change. Read the control's value inside it, as a change listener would. Ignored in every other mode. See Change mode. |
changeMode | ChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEnded | When the control fires change while the user is still moving it. Debounced, Throttled and Adaptive are paced by rateLimitDelay, which Adaptive treats as a target, and Adaptive also paces against asyncSink. See Change mode. |
direction | DialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.Clockwise | Sets which way the value increases around the dial, measured from originAngle. See Direction. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
formread-only (ref) | HTMLFormElement | The form the component belongs to, or null when it has none. |
labeled | booleandefault false | Whether a label with the handle's value appears while the handle is pressed or focused. It stays briefly after a press ends. See Value and origin. |
labelsread-only (ref) | NodeList | The <label> elements associated with the element. |
name | string | The name the element's value is submitted under with its form. See Forms. |
originAngle | numberdefault 0 | The origin angle offset in degrees from 12 o'clock position. Rotates the entire dial coordinate system. For example, setting this to 90° makes the right side (3 o'clock) the zero position: a value is measured from originAngle in the dial's direction, both where it is drawn and where a press reads it. The value is cumulative rotation and is not wrapped to 0-360°.An assignment that is not a finite number is ignored, and originAngle keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin, Direction. |
pageValue | number | How far PageUp and PageDown move the value. Defaults to ten times step.An assignment that is not a finite number is ignored, and pageValue keeps the value it already had. Assigning null or undefined unsets it, restoring the default. See Value and origin. |
rateLimitDelay | numberdefault 150 | The delay in milliseconds that paces change events in the Debounced, Throttled and Adaptive change modes. Other modes ignore it.An assignment that is not a finite number is ignored, and rateLimitDelay keeps the value it already had. null and undefined are ignored on the same rule. See Change mode. |
sinkDutyCycle | numberdefault 1 | The share of the sink's time this control may occupy, above 0 and up to 1, for ChangeEventMode.Adaptive only. At 1 the next call goes out as soon as the last one finishes. Lower it when the sink is shared, so one person dragging does not saturate it: at 0.25 the control leaves three quarters of the time idle.An assignment that is not a finite number in (0, 1] is ignored, and the property keeps the value it already had. See Change mode. |
size | SizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configuration | Sets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size. |
softDisabled | booleandefault false | Disables the control but keeps it focusable and in the Tab order. It carries aria-disabled="true", and neither the pointer nor the keyboard changes its value. Use it when a disabled control must stay reachable by keyboard and screen reader. For when this is needed, see WAI-ARIA Authoring Practices: disabled controls. |
step | numberdefault 1 | The step between values. Where the control has a range, a step above the range is set to the range, and a step of 0 or less to 1.An assignment that is not a finite number is ignored, and step keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin. |
tickmarks | SliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStop | The type of tickmarks to show. Ignored while the slot="track-background" child is filled. See Tickmarks. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Size. |
value | number | The control's current value.An assignment that is not a finite number -- NaN, Infinity, or a string that does not parse as a number -- is ignored, and value keeps the last valid value it held. Assigning null or undefined unsets it, restoring the default. See Value and origin, Forms, Change mode. |
valueLabel | string | Text shown and announced in place of the value; if not set, the value itself. A screen reader reads it as the value, and as the control's name when aria-label is not set. |
Children
| Child | Description |
|---|---|
a child with slot="track-background" | Content that shows through the dial's track in place of its colors. Tickmarks and the end stop are not drawn while it is filled. |
Events
| Prop | Argument | Description |
|---|---|---|
onInput | React.ChangeEvent<HTMLInputElement> | Fires during value changes as the user rotates. It bubbles and is composed. |
onChange | React.ChangeEvent<HTMLInputElement> | Fires when the value is committed (timing controlled by changeMode). It bubbles. |
Setting valueinput nor change.
Parameters
| Parameter | Type | Description |
|---|---|---|
AriaDescribedBy | string? | The IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found. |
AriaDescription | string? | Not announced by assistive technology. AriaDescribedBy is no substitute: an ID elsewhere on the page is not found. |
AriaErrorMessage | string? | The ID of the element describing the value's error. Used only while AriaInvalid is "true". |
AriaInvalid | string? | Whether the control's value is invalid. A screen reader announces it; the control's appearance does not change. |
AriaLabelledBy | string? | The IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label. |
AsyncSink | ValueChangeSink? | The async work, such as a request to a server, that ChangeEventMode.Adaptive paces change events against: the control asks for the next one only when the last has finished, no faster than RateLimitDelay. A slow sink is asked less often, and is not called once per value change. Read the control's value inside it, as a change listener would. Ignored in every other mode. See Change mode. |
ChangeMode | ChangeEventMode?ChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEnded | When the control fires change while the user is still moving it. Debounced, Throttled and Adaptive are paced by RateLimitDelay, which Adaptive treats as a target, and Adaptive also paces against AsyncSink. See Change mode. |
Direction | DialDirection?DialDirection.Clockwise, .CounterClockwisedefault DialDirection.Clockwise | Sets which way the value increases around the dial, measured from OriginAngle. See Direction. |
Disabled | bool? | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
Labeled | bool?default false | Whether a label with the handle's value appears while the handle is pressed or focused. It stays briefly after a press ends. See Value and origin. |
Name | string? | The name the element's value is submitted under with its form. See Forms. |
OriginAngle | double?default 0 | The origin angle offset in degrees from 12 o'clock position. Rotates the entire dial coordinate system. For example, setting this to 90° makes the right side (3 o'clock) the zero position: a value is measured from OriginAngle in the dial's Direction, both where it is drawn and where a press reads it. The value is cumulative rotation and is not wrapped to 0-360°.An assignment that is not a finite number is ignored, and OriginAngle keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin, Direction. |
PageValue | double? | How far PageUp and PageDown move the value. Defaults to ten times Step.An assignment that is not a finite number is ignored, and PageValue keeps the value it already had. Assigning null or undefined unsets it, restoring the default. See Value and origin. |
RateLimitDelay | int?default 150 | The delay in milliseconds that paces change events in the Debounced, Throttled and Adaptive change modes. Other modes ignore it.An assignment that is not a finite number is ignored, and RateLimitDelay keeps the value it already had. null and undefined are ignored on the same rule. See Change mode. |
SinkDutyCycle | double?default 1 | The share of the sink's time this control may occupy, above 0 and up to 1, for ChangeEventMode.Adaptive only. At 1 the next call goes out as soon as the last one finishes. Lower it when the sink is shared, so one person dragging does not saturate it: at 0.25 the control leaves three quarters of the time idle.An assignment that is not a finite number in (0, 1] is ignored, and the property keeps the value it already had. See Change mode. |
Size | Size?Size.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configuration | Sets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size. |
SoftDisabled | bool?default false | Disables the control but keeps it focusable and in the Tab order. It carries aria-disabled="true", and neither the pointer nor the keyboard changes its value. Use it when a disabled control must stay reachable by keyboard and screen reader. For when this is needed, see WAI-ARIA Authoring Practices: disabled controls. |
Step | double?default 1 | The step between values. Where the control has a range, a step above the range is set to the range, and a step of 0 or less to 1.An assignment that is not a finite number is ignored, and Step keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin. |
Tickmarks | SliderTickmark?SliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStop | The type of tickmarks to show. Ignored while the TrackBackground render fragment is filled. See Tickmarks. |
TouchTarget | TouchTarget?TouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Size. |
Value | double? | The control's current value.An assignment that is not a finite number -- NaN, Infinity, or a string that does not parse as a number -- is ignored, and Value keeps the last valid value it held. Assigning null or undefined unsets it, restoring the default. See Value and origin, Forms, Change mode. |
ValueExpression | Expression<Func<double?>>? | Gets or sets an expression that identifies the bound value. |
ValueLabel | string? | Text shown and announced in place of the value; if not set, the value itself. A screen reader reads it as the value, and as the control's name when aria-label is not set. |
Render fragments
| Parameter | Type | Description |
|---|---|---|
TrackBackground | RenderFragment? | Content that shows through the dial's track in place of its colors. Tickmarks and the end stop are not drawn while it is filled. |
Event callbacks
| Parameter | Type | Description |
|---|---|---|
OnInput | EventCallback<ChangeEventArgs> | Fires during value changes as the user rotates. It bubbles and is composed. |
OnChange | EventCallback<ChangeEventArgs> | Fires when the value is committed (timing controlled by ChangeMode). It bubbles. |
Setting valueinput nor change.
Inputs
| Input | Type | Description |
|---|---|---|
ariaDescribedBy | string | The IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found. |
ariaDescription | string | Not announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found. |
ariaErrorMessage | string | The ID of the element describing the value's error. Used only while ariaInvalid is "true". |
ariaInvalid | string | Whether the control's value is invalid. A screen reader announces it; the control's appearance does not change. |
ariaLabelledBy | string | The IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label. |
asyncSink | ValueChangeSink | The async work, such as a request to a server, that ChangeEventMode.Adaptive paces change events against: the control asks for the next one only when the last has finished, no faster than rateLimitDelay. A slow sink is asked less often, and is not called once per value change. Read the control's value inside it, as a change listener would. Ignored in every other mode. See Change mode. |
changeMode | ChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEnded | When the control fires change while the user is still moving it. Debounced, Throttled and Adaptive are paced by rateLimitDelay, which Adaptive treats as a target, and Adaptive also paces against asyncSink. See Change mode. |
direction | DialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.Clockwise | Sets which way the value increases around the dial, measured from originAngle. See Direction. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
labeled | booleandefault false | Whether a label with the handle's value appears while the handle is pressed or focused. It stays briefly after a press ends. See Value and origin. |
name | string | The name the element's value is submitted under with its form. See Forms. |
originAngle | numberdefault 0 | The origin angle offset in degrees from 12 o'clock position. Rotates the entire dial coordinate system. For example, setting this to 90° makes the right side (3 o'clock) the zero position: a value is measured from originAngle in the dial's direction, both where it is drawn and where a press reads it. The value is cumulative rotation and is not wrapped to 0-360°.An assignment that is not a finite number is ignored, and originAngle keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin, Direction. |
pageValue | number | How far PageUp and PageDown move the value. Defaults to ten times step.An assignment that is not a finite number is ignored, and pageValue keeps the value it already had. Assigning null or undefined unsets it, restoring the default. See Value and origin. |
rateLimitDelay | numberdefault 150 | The delay in milliseconds that paces change events in the Debounced, Throttled and Adaptive change modes. Other modes ignore it.An assignment that is not a finite number is ignored, and rateLimitDelay keeps the value it already had. null and undefined are ignored on the same rule. See Change mode. |
sinkDutyCycle | numberdefault 1 | The share of the sink's time this control may occupy, above 0 and up to 1, for ChangeEventMode.Adaptive only. At 1 the next call goes out as soon as the last one finishes. Lower it when the sink is shared, so one person dragging does not saturate it: at 0.25 the control leaves three quarters of the time idle.An assignment that is not a finite number in (0, 1] is ignored, and the property keeps the value it already had. See Change mode. |
size | SizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configuration | Sets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size. |
softDisabled | booleandefault false | Disables the control but keeps it focusable and in the Tab order. It carries aria-disabled="true", and neither the pointer nor the keyboard changes its value. Use it when a disabled control must stay reachable by keyboard and screen reader. For when this is needed, see WAI-ARIA Authoring Practices: disabled controls. |
step | numberdefault 1 | The step between values. Where the control has a range, a step above the range is set to the range, and a step of 0 or less to 1.An assignment that is not a finite number is ignored, and step keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin. |
tickmarks | SliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStop | The type of tickmarks to show. Ignored while the track-background slot is filled. See Tickmarks. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Size. |
value | number | The control's current value.An assignment that is not a finite number -- NaN, Infinity, or a string that does not parse as a number -- is ignored, and value keeps the last valid value it held. Assigning null or undefined unsets it, restoring the default. See Value and origin, Forms, Change mode. |
valueLabel | string | Text shown and announced in place of the value; if not set, the value itself. A screen reader reads it as the value, and as the control's name when aria-label is not set. |
Content projection
| Content | Description |
|---|---|
an element with slot="track-background" | Content that shows through the dial's track in place of its colors. Tickmarks and the end stop are not drawn while it is filled. |
Outputs
| Output | Event | Description |
|---|---|---|
cwInput | InputEvent | Fires during value changes as the user rotates. It bubbles and is composed. |
cwChange | Event | Fires when the value is committed (timing controlled by changeMode). It bubbles. |
Setting valueinput nor change.
Props
| Prop | Type | Description |
|---|---|---|
ariaDescribedBy | string | The IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found. |
ariaDescription | string | Not announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found. |
ariaErrorMessage | string | The ID of the element describing the value's error. Used only while ariaInvalid is "true". |
ariaInvalid | string | Whether the control's value is invalid. A screen reader announces it; the control's appearance does not change. |
ariaLabelledBy | string | The IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label. |
asyncSink | ValueChangeSink | The async work, such as a request to a server, that ChangeEventMode.Adaptive paces change events against: the control asks for the next one only when the last has finished, no faster than rateLimitDelay. A slow sink is asked less often, and is not called once per value change. Read the control's value inside it, as a change listener would. Ignored in every other mode. See Change mode. |
changeMode | ChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEnded | When the control fires change while the user is still moving it. Debounced, Throttled and Adaptive are paced by rateLimitDelay, which Adaptive treats as a target, and Adaptive also paces against asyncSink. See Change mode. |
direction | DialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.Clockwise | Sets which way the value increases around the dial, measured from originAngle. See Direction. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
labeled | booleandefault false | Whether a label with the handle's value appears while the handle is pressed or focused. It stays briefly after a press ends. See Value and origin. |
name | string | The name the element's value is submitted under with its form. See Forms. |
originAngle | numberdefault 0 | The origin angle offset in degrees from 12 o'clock position. Rotates the entire dial coordinate system. For example, setting this to 90° makes the right side (3 o'clock) the zero position: a value is measured from originAngle in the dial's direction, both where it is drawn and where a press reads it. The value is cumulative rotation and is not wrapped to 0-360°.An assignment that is not a finite number is ignored, and originAngle keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin, Direction. |
pageValue | number | How far PageUp and PageDown move the value. Defaults to ten times step.An assignment that is not a finite number is ignored, and pageValue keeps the value it already had. Assigning null or undefined unsets it, restoring the default. See Value and origin. |
rateLimitDelay | numberdefault 150 | The delay in milliseconds that paces change events in the Debounced, Throttled and Adaptive change modes. Other modes ignore it.An assignment that is not a finite number is ignored, and rateLimitDelay keeps the value it already had. null and undefined are ignored on the same rule. See Change mode. |
sinkDutyCycle | numberdefault 1 | The share of the sink's time this control may occupy, above 0 and up to 1, for ChangeEventMode.Adaptive only. At 1 the next call goes out as soon as the last one finishes. Lower it when the sink is shared, so one person dragging does not saturate it: at 0.25 the control leaves three quarters of the time idle.An assignment that is not a finite number in (0, 1] is ignored, and the property keeps the value it already had. See Change mode. |
size | SizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configuration | Sets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size. |
softDisabled | booleandefault false | Disables the control but keeps it focusable and in the Tab order. It carries aria-disabled="true", and neither the pointer nor the keyboard changes its value. Use it when a disabled control must stay reachable by keyboard and screen reader. For when this is needed, see WAI-ARIA Authoring Practices: disabled controls. |
step | numberdefault 1 | The step between values. Where the control has a range, a step above the range is set to the range, and a step of 0 or less to 1.An assignment that is not a finite number is ignored, and step keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin. |
tickmarks | SliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStop | The type of tickmarks to show. Ignored while the track-background slot is filled. See Tickmarks. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Size. |
value | number | The control's current value.An assignment that is not a finite number -- NaN, Infinity, or a string that does not parse as a number -- is ignored, and value keeps the last valid value it held. Assigning null or undefined unsets it, restoring the default. See Value and origin, Forms, Change mode. |
valueLabel | string | Text shown and announced in place of the value; if not set, the value itself. A screen reader reads it as the value, and as the control's name when aria-label is not set. |
Slots
| Slot | Description |
|---|---|
track-background | Content that shows through the dial's track in place of its colors. Tickmarks and the end stop are not drawn while it is filled. |
Events
| Event | Type | Description |
|---|---|---|
input | InputEvent | Fires during value changes as the user rotates. It bubbles and is composed. |
change | Event | Fires when the value is committed (timing controlled by changeMode). It bubbles. |
Setting valueinput nor change.
Props
| Prop | Type | Description |
|---|---|---|
ariaDescribedBy | string | The IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found. |
ariaDescription | string | Not announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found. |
ariaErrorMessage | string | The ID of the element describing the value's error. Used only while ariaInvalid is "true". |
ariaInvalid | string | Whether the control's value is invalid. A screen reader announces it; the control's appearance does not change. |
ariaLabelledBy | string | The IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label. |
asyncSink | ValueChangeSink | The async work, such as a request to a server, that ChangeEventMode.Adaptive paces change events against: the control asks for the next one only when the last has finished, no faster than rateLimitDelay. A slow sink is asked less often, and is not called once per value change. Read the control's value inside it, as a change listener would. Ignored in every other mode. See Change mode. |
changeMode | ChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEnded | When the control fires change while the user is still moving it. Debounced, Throttled and Adaptive are paced by rateLimitDelay, which Adaptive treats as a target, and Adaptive also paces against asyncSink. See Change mode. |
direction | DialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.Clockwise | Sets which way the value increases around the dial, measured from originAngle. See Direction. |
disabled | boolean | Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled. |
labeled | booleandefault false | Whether a label with the handle's value appears while the handle is pressed or focused. It stays briefly after a press ends. See Value and origin. |
name | string | The name the element's value is submitted under with its form. See Forms. |
originAngle | numberdefault 0 | The origin angle offset in degrees from 12 o'clock position. Rotates the entire dial coordinate system. For example, setting this to 90° makes the right side (3 o'clock) the zero position: a value is measured from originAngle in the dial's direction, both where it is drawn and where a press reads it. The value is cumulative rotation and is not wrapped to 0-360°.An assignment that is not a finite number is ignored, and originAngle keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin, Direction. |
pageValue | number | How far PageUp and PageDown move the value. Defaults to ten times step.An assignment that is not a finite number is ignored, and pageValue keeps the value it already had. Assigning null or undefined unsets it, restoring the default. See Value and origin. |
rateLimitDelay | numberdefault 150 | The delay in milliseconds that paces change events in the Debounced, Throttled and Adaptive change modes. Other modes ignore it.An assignment that is not a finite number is ignored, and rateLimitDelay keeps the value it already had. null and undefined are ignored on the same rule. See Change mode. |
sinkDutyCycle | numberdefault 1 | The share of the sink's time this control may occupy, above 0 and up to 1, for ChangeEventMode.Adaptive only. At 1 the next call goes out as soon as the last one finishes. Lower it when the sink is shared, so one person dragging does not saturate it: at 0.25 the control leaves three quarters of the time idle.An assignment that is not a finite number in (0, 1] is ignored, and the property keeps the value it already had. See Change mode. |
size | SizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configuration | Sets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size. |
softDisabled | booleandefault false | Disables the control but keeps it focusable and in the Tab order. It carries aria-disabled="true", and neither the pointer nor the keyboard changes its value. Use it when a disabled control must stay reachable by keyboard and screen reader. For when this is needed, see WAI-ARIA Authoring Practices: disabled controls. |
step | numberdefault 1 | The step between values. Where the control has a range, a step above the range is set to the range, and a step of 0 or less to 1.An assignment that is not a finite number is ignored, and step keeps the value it already had. null and undefined are ignored on the same rule. See Value and origin. |
tickmarks | SliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStop | The type of tickmarks to show. Ignored while the trackBackgroundSnippet snippet is filled. See Tickmarks. |
touchTarget | TouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configuration | The area that takes a touch, at least 48 by 48 pixels and centered on the component. overflow extends it past the component without changing the component's layout size, wrapper makes the component take up the whole area in the layout, and none limits it to the component's own size. See Size. |
value | number | The control's current value.An assignment that is not a finite number -- NaN, Infinity, or a string that does not parse as a number -- is ignored, and value keeps the last valid value it held. Assigning null or undefined unsets it, restoring the default. See Value and origin, Forms, Change mode. |
valueLabel | string | Text shown and announced in place of the value; if not set, the value itself. A screen reader reads it as the value, and as the control's name when aria-label is not set. |
Snippets
| Snippet | Description |
|---|---|
trackBackgroundSnippet | Content that shows through the dial's track in place of its colors. Tickmarks and the end stop are not drawn while it is filled. |
Events
| Prop | Type | Description |
|---|---|---|
onInput | InputEvent | Fires during value changes as the user rotates. It bubbles and is composed. |
onChange | Event | Fires when the value is committed (timing controlled by changeMode). It bubbles. |
Setting valueinput nor change.
Each attribute value has its own tokens; a cell shows its token's value, and selecting the cell shows the token's fallback path, with each name and value ready to copy. For example, the extra-small column's diameter row is --ct-dial-xsmall-diameter, which defaults to 112px.
Size
Token names spell extra-small as xsmall and extra-large as xlarge.
| Name | extra-small | small | medium | large | extra-large |
|---|---|---|---|---|---|
diameter | 112px --ct-dial-xsmall-diameter | 120px --ct-dial-small-diameter | 160px --ct-dial-medium-diameter | 212px --ct-dial-large-diameter | 292px --ct-dial-xlarge-diameter |
handle-length | 44px --ct-dial-xsmall-handle-length | 44px --ct-dial-small-handle-length | 44px --ct-dial-medium-handle-length | 68px --ct-dial-large-handle-length | 108px --ct-dial-xlarge-handle-length |
track-corner-end-end-radius | same as track-corner-radius --ct-dial-xsmall-track-corner-end-end-radius | same as track-corner-radius --ct-dial-small-track-corner-end-end-radius | same as track-corner-radius --ct-dial-medium-track-corner-end-end-radius | same as track-corner-radius --ct-dial-large-track-corner-end-end-radius | same as track-corner-radius --ct-dial-xlarge-track-corner-end-end-radius |
track-corner-end-start-radius | same as track-corner-radius --ct-dial-xsmall-track-corner-end-start-radius | same as track-corner-radius --ct-dial-small-track-corner-end-start-radius | same as track-corner-radius --ct-dial-medium-track-corner-end-start-radius | same as track-corner-radius --ct-dial-large-track-corner-end-start-radius | same as track-corner-radius --ct-dial-xlarge-track-corner-end-start-radius |
track-corner-radius | 8px --ct-dial-xsmall-track-corner-radius | 8px --ct-dial-small-track-corner-radius | 12px --ct-dial-medium-track-corner-radius | 16px --ct-dial-large-track-corner-radius | 28px --ct-dial-xlarge-track-corner-radius |
track-corner-start-end-radius | same as track-corner-radius --ct-dial-xsmall-track-corner-start-end-radius | same as track-corner-radius --ct-dial-small-track-corner-start-end-radius | same as track-corner-radius --ct-dial-medium-track-corner-start-end-radius | same as track-corner-radius --ct-dial-large-track-corner-start-end-radius | same as track-corner-radius --ct-dial-xlarge-track-corner-start-end-radius |
track-corner-start-start-radius | same as track-corner-radius --ct-dial-xsmall-track-corner-start-start-radius | same as track-corner-radius --ct-dial-small-track-corner-start-start-radius | same as track-corner-radius --ct-dial-medium-track-corner-start-start-radius | same as track-corner-radius --ct-dial-large-track-corner-start-start-radius | same as track-corner-radius --ct-dial-xlarge-track-corner-start-start-radius |
track-thickness | 16px --ct-dial-xsmall-track-thickness | 24px --ct-dial-small-track-thickness | 40px --ct-dial-medium-track-thickness | 56px --ct-dial-large-track-thickness | 96px --ct-dial-xlarge-track-thickness |
Other tokens
These stay the same whatever the size.
| Token | Value |
|---|---|
--ct-dial-active-handle-space | 5px --ct-dial-active-handle-space |
--ct-dial-active-handle-width | 2px --ct-dial-active-handle-width |
--ct-dial-active-tick-mark-color | --ct-sys-color-on-primary --ct-dial-active-tick-mark-color |
--ct-dial-active-tick-mark-opacity | 1 --ct-dial-active-tick-mark-opacity |
--ct-dial-active-track-color | --ct-sys-color-primary --ct-dial-active-track-color |
--ct-dial-center-space | 4px --ct-dial-center-space |
--ct-dial-disabled-active-tick-mark-color | --ct-sys-color-inverse-on-surface --ct-dial-disabled-active-tick-mark-color |
--ct-dial-disabled-active-track-color | --ct-sys-color-on-surface --ct-dial-disabled-active-track-color |
--ct-dial-disabled-active-track-opacity | 0.38 --ct-dial-disabled-active-track-opacity |
--ct-dial-disabled-handle-color | --ct-sys-color-on-surface --ct-dial-disabled-handle-color |
--ct-dial-disabled-handle-opacity | 0.38 --ct-dial-disabled-handle-opacity |
--ct-dial-disabled-inactive-tick-mark-color | --ct-sys-color-on-surface --ct-dial-disabled-inactive-tick-mark-color |
--ct-dial-disabled-inactive-track-color | --ct-sys-color-on-surface --ct-dial-disabled-inactive-track-color |
--ct-dial-disabled-inactive-track-opacity | 0.12 --ct-dial-disabled-inactive-track-opacity |
--ct-dial-disabled-tick-mark-opacity | 0.38 --ct-dial-disabled-tick-mark-opacity |
--ct-dial-handle-color | --ct-sys-color-primary --ct-dial-handle-color |
--ct-dial-handle-space | 6px --ct-dial-handle-space |
--ct-dial-handle-width | 4px --ct-dial-handle-width |
--ct-dial-inactive-tick-mark-color | --ct-sys-color-on-secondary-container --ct-dial-inactive-tick-mark-color |
--ct-dial-inactive-tick-mark-opacity | 1 --ct-dial-inactive-tick-mark-opacity |
--ct-dial-inactive-track-color | --ct-sys-color-secondary-container --ct-dial-inactive-track-color |
--ct-dial-tick-mark-size | 4px --ct-dial-tick-mark-size |
--ct-dial-value-indicator-block-space | 12px --ct-dial-value-indicator-block-space |
--ct-dial-value-indicator-container-color | --ct-sys-color-inverse-surface --ct-dial-value-indicator-container-color |
--ct-dial-value-indicator-inline-space | 16px --ct-dial-value-indicator-inline-space |
--ct-dial-value-indicator-label-font | --ct-sys-typescale-label-large-font --ct-dial-value-indicator-label-font |
--ct-dial-value-indicator-label-line-height | --ct-sys-typescale-label-large-line-height --ct-dial-value-indicator-label-line-height |
--ct-dial-value-indicator-label-size | --ct-sys-typescale-label-large-size --ct-dial-value-indicator-label-size |
--ct-dial-value-indicator-label-text-color | --ct-sys-color-inverse-on-surface --ct-dial-value-indicator-label-text-color |
--ct-dial-value-indicator-label-tracking | --ct-sys-typescale-label-large-tracking --ct-dial-value-indicator-label-tracking |
--ct-dial-value-indicator-label-weight | --ct-sys-typescale-label-large-weight --ct-dial-value-indicator-label-weight |
Names and states
A continuous dial has the slider role, which follows the WAI-ARIA Authoring Practices: Slider pattern.
- The accessible name is the dial's
aria-label, else , else the current number. Give every dial anvalue-labelaria-label, since the number alone names nothing. - A screen reader announces the value as the dial's own
aria-valuetextif you set one, else , else the number.value-label - The dial has no minimum or maximum, so it announces no limits. Choose a dial when the value has limits.
- Six settings shape what a screen reader announces:
aria-label,aria-valuetext, ,aria-labelledby ,aria-describedby , andaria-invalid . Any other ARIA attribute has no effect.aria-errormessage - A screen reader announces the
text only whilearia-errormessage isaria-invalid"true". - An ID that points to an element elsewhere on the page is not found, so name the dial with
aria-labelrather than .aria-labelledby is not announced, andaria-description cannot stand in for it.aria-describedby
Keyboard and focus
| Key | Action |
|---|---|
| Tab | Moves focus to the dial or away from it. |
| Arrow keys | Move the value by one step |
| PageUp and PageDown | Move the value by page-valuestep |
| Home | Sets the value to 0. |
| End | Does nothing, since the dial has no end. |
The dial ignores these keys while a pointer drag is in progress.
- Focus draws a ring on the handle and nowhere else.
removes the dial from the Tab order. A dial inside a disableddisabled<fieldset>is disabled too.- There is no soft-disabled state: a dial is either focusable or disabled.
Pointer and touch
The touch target is at least 48 by 48 pixels, centered on the dial, against the 24 by 24 pixels that WCAG 2.5.8 asks for. touch-targetnone
Display settings
- Forced colors: the handle, track, and value label take system colors with visible borders, and the handle gains a thicker ring on hover and while dragged.
- Reduced motion: the transitions on the handle, the value label, the focus ring and the fill are turned off.
- Right-to-left: nothing mirrors. The keys and the drawing stay as they are.
Standards
With its defaults, a continuous dial meets three WCAG 2.2 success criteria:
Three more depend on how you use it:
- 4.1.2 Name, Role, Value (A): give every dial an
aria-label. - 2.5.3 Label in Name (A): where visible text labels the dial, start its
aria-labelwith the same words. - 3.3.1 Error Identification (A): when the value is invalid, set
and pointaria-invalid at text that says what is wrong.aria-errormessage