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⁠

BlazorReactWebOverviewExamplesAPIStylingAccessibility

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⁠

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 value-label to value when the readout needs units or formatting, since it holds one fixed string.
  • Leave touch-target at its default so a small dial keeps a touch area of at least 48 by 48 pixels.

Value and origin⁠

A continuous dial has no minimum or maximum. value is the cumulative rotation in degrees, so two full clockwise turns read 720, and it saturates only at 100000 in either direction.

step sets how far one arrow key press moves the value, and page-value sets PageUp and PageDown, ten times step when unset. origin-angle moves the zero position by that many degrees from 12 o'clock. labeled adds a value label over the handle.

Size⁠

size takes one of five values, from extra-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 unless you have changed it.

touch-target sets the area that takes a touch, at least 48 by 48 pixels and centered on the dial. Omit it and the dial takes overflow from your style configuration: the touch area extends past the dial. wrapper makes the element occupy the touch area, and none reduces it to the dial's own size.

Forms⁠

A continuous dial takes part in forms. name is the key its value is submitted under, as a string, and a reset restores the value 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 switches the dial off for pointer and keyboard alike. A dial inside a disabled <fieldset> is disabled too.

Change mode⁠

input fires on every turn. change follows change-mode: by default interaction-ended, when the user lifts the pointer or releases the key. immediate fires it on each turn instead, and debounced and throttled pace it by rate-limit-delay, 150 milliseconds unless set.

adaptive fires no more often than once per rate-limit-delay, and paces change against the work in asyncSink, and sink-duty-cycle caps the share of that work's time the dial may use. Only code can supply asyncSink, so the demo leaves adaptive out. Without an asyncSink, adaptive paces as throttled does. Event pacing explains the measurement. Setting value from code fires neither event. The demo reports the input event and shows the bound value beside it.

Direction⁠

direction sets which way the value grows. With clockwise, the default, turning clockwise adds to the value. With counterclockwise it is turning counterclockwise that adds, measured from origin-angle.

Tickmarks⁠

tickmarks takes three values. contrast-end-stop is the default, values adds marks along the track, and none removes them. Content in the track-background slot replaces the marks, so tickmarks has no effect while the slot is filled.

Properties⁠

PropertyAttributeTypeDescription
ariaDescribedByaria-describedbystringThe IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found.
ariaDescriptionaria-descriptionstringNot announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found.
ariaErrorMessagearia-errormessagestringThe ID of the element describing the value's error. Used only while ariaInvalid is "true".
ariaInvalidaria-invalidstringWhether the control's value is invalid. A screen reader announces it; the control's appearance does not change.
ariaLabelledByaria-labelledbystringThe IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label.
asyncSinkValueChangeSinkThe 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.
changeModechange-modedebounced, immediate, interaction-ended, throttled, adaptiveChangeEventModeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEndedWhen 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.
directiondirectionclockwise, counterclockwiseDialDirectionDialDirection.Clockwise, .CounterClockwisedefault DialDirection.ClockwiseSets which way the value increases around the dial, measured from originAngle. See Direction.
disableddisabledbooleanWhether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled.
formread-onlyHTMLFormElementThe form the component belongs to, or null when it has none.
labeledlabeledbooleandefault falseWhether 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-onlyNodeListThe <label> elements associated with the element.
namenamestringThe name the element's value is submitted under with its form. See Forms.
originAngleorigin-anglenumberdefault 0The 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.
pageValuepage-valuenumberHow 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.
rateLimitDelayrate-limit-delaynumberdefault 150The 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.
sinkDutyCyclesink-duty-cyclenumberdefault 1The 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.
sizesizeextra-small, small, medium, large, extra-largeSizeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configurationSets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size.
softDisabledsoft-disabledbooleandefault falseDisables 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.
stepstepnumberdefault 1The 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.
tickmarkstickmarksnone, contrast-end-stop, valuesSliderTickmarkSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStopThe type of tickmarks to show. Ignored while the track-background slot is filled. See Tickmarks.
touchTargettouch-targetnone, overflow, wrapperTouchTargetTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configurationThe 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.
valuevaluenumberThe 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.
valueLabelvalue-labelstringText 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⁠

SlotDescription
track-backgroundContent 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⁠

EventTypeDetailDescription
inputInputEvent—Fires during value changes as the user rotates. It bubbles and is composed.
changeEvent—Fires when the value is committed (timing controlled by changeMode). It bubbles.

Setting value from code fires neither input nor change.

Props⁠

PropTypeDescription
ariaDescribedBystringThe IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found.
ariaDescriptionstringNot announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found.
ariaErrorMessagestringThe ID of the element describing the value's error. Used only while ariaInvalid is "true".
ariaInvalidstringWhether the control's value is invalid. A screen reader announces it; the control's appearance does not change.
ariaLabelledBystringThe IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label.
asyncSinkValueChangeSinkThe 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.
changeModeChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEndedWhen 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.
directionDialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.ClockwiseSets which way the value increases around the dial, measured from originAngle. See Direction.
disabledbooleanWhether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled.
formread-only (ref)HTMLFormElementThe form the component belongs to, or null when it has none.
labeledbooleandefault falseWhether 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)NodeListThe <label> elements associated with the element.
namestringThe name the element's value is submitted under with its form. See Forms.
originAnglenumberdefault 0The 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.
pageValuenumberHow 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.
rateLimitDelaynumberdefault 150The 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.
sinkDutyCyclenumberdefault 1The 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.
sizeSizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configurationSets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size.
softDisabledbooleandefault falseDisables 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.
stepnumberdefault 1The 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.
tickmarksSliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStopThe type of tickmarks to show. Ignored while the slot="track-background" child is filled. See Tickmarks.
touchTargetTouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configurationThe 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.
valuenumberThe 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.
valueLabelstringText 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⁠

ChildDescription
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⁠

PropArgumentDescription
onInputReact.ChangeEvent<HTMLInputElement>Fires during value changes as the user rotates. It bubbles and is composed.
onChangeReact.ChangeEvent<HTMLInputElement>Fires when the value is committed (timing controlled by changeMode). It bubbles.

Setting value from code fires neither input nor change.

Parameters⁠

ParameterTypeDescription
AriaDescribedBystring?The IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found.
AriaDescriptionstring?Not announced by assistive technology. AriaDescribedBy is no substitute: an ID elsewhere on the page is not found.
AriaErrorMessagestring?The ID of the element describing the value's error. Used only while AriaInvalid is "true".
AriaInvalidstring?Whether the control's value is invalid. A screen reader announces it; the control's appearance does not change.
AriaLabelledBystring?The IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label.
AsyncSinkValueChangeSink?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.
ChangeModeChangeEventMode?ChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEndedWhen 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.
DirectionDialDirection?DialDirection.Clockwise, .CounterClockwisedefault DialDirection.ClockwiseSets which way the value increases around the dial, measured from OriginAngle. See Direction.
Disabledbool?Whether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled.
Labeledbool?default falseWhether 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.
Namestring?The name the element's value is submitted under with its form. See Forms.
OriginAngledouble?default 0The 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.
PageValuedouble?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.
RateLimitDelayint?default 150The 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.
SinkDutyCycledouble?default 1The 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.
SizeSize?Size.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configurationSets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size.
SoftDisabledbool?default falseDisables 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.
Stepdouble?default 1The 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.
TickmarksSliderTickmark?SliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStopThe type of tickmarks to show. Ignored while the TrackBackground render fragment is filled. See Tickmarks.
TouchTargetTouchTarget?TouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configurationThe 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.
Valuedouble?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.
ValueExpressionExpression<Func<double?>>?Gets or sets an expression that identifies the bound value.
ValueLabelstring?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⁠

ParameterTypeDescription
TrackBackgroundRenderFragment?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⁠

ParameterTypeDescription
OnInputEventCallback<ChangeEventArgs>Fires during value changes as the user rotates. It bubbles and is composed.
OnChangeEventCallback<ChangeEventArgs>Fires when the value is committed (timing controlled by ChangeMode). It bubbles.

Setting value from code fires neither input nor change.

Inputs⁠

InputTypeDescription
ariaDescribedBystringThe IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found.
ariaDescriptionstringNot announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found.
ariaErrorMessagestringThe ID of the element describing the value's error. Used only while ariaInvalid is "true".
ariaInvalidstringWhether the control's value is invalid. A screen reader announces it; the control's appearance does not change.
ariaLabelledBystringThe IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label.
asyncSinkValueChangeSinkThe 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.
changeModeChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEndedWhen 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.
directionDialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.ClockwiseSets which way the value increases around the dial, measured from originAngle. See Direction.
disabledbooleanWhether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled.
labeledbooleandefault falseWhether 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.
namestringThe name the element's value is submitted under with its form. See Forms.
originAnglenumberdefault 0The 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.
pageValuenumberHow 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.
rateLimitDelaynumberdefault 150The 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.
sinkDutyCyclenumberdefault 1The 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.
sizeSizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configurationSets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size.
softDisabledbooleandefault falseDisables 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.
stepnumberdefault 1The 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.
tickmarksSliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStopThe type of tickmarks to show. Ignored while the track-background slot is filled. See Tickmarks.
touchTargetTouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configurationThe 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.
valuenumberThe 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.
valueLabelstringText 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⁠

ContentDescription
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⁠

OutputEventDescription
cwInputInputEventFires during value changes as the user rotates. It bubbles and is composed.
cwChangeEventFires when the value is committed (timing controlled by changeMode). It bubbles.

Setting value from code fires neither input nor change.

Props⁠

PropTypeDescription
ariaDescribedBystringThe IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found.
ariaDescriptionstringNot announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found.
ariaErrorMessagestringThe ID of the element describing the value's error. Used only while ariaInvalid is "true".
ariaInvalidstringWhether the control's value is invalid. A screen reader announces it; the control's appearance does not change.
ariaLabelledBystringThe IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label.
asyncSinkValueChangeSinkThe 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.
changeModeChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEndedWhen 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.
directionDialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.ClockwiseSets which way the value increases around the dial, measured from originAngle. See Direction.
disabledbooleanWhether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled.
labeledbooleandefault falseWhether 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.
namestringThe name the element's value is submitted under with its form. See Forms.
originAnglenumberdefault 0The 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.
pageValuenumberHow 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.
rateLimitDelaynumberdefault 150The 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.
sinkDutyCyclenumberdefault 1The 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.
sizeSizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configurationSets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size.
softDisabledbooleandefault falseDisables 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.
stepnumberdefault 1The 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.
tickmarksSliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStopThe type of tickmarks to show. Ignored while the track-background slot is filled. See Tickmarks.
touchTargetTouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configurationThe 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.
valuenumberThe 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.
valueLabelstringText 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⁠

SlotDescription
track-backgroundContent 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⁠

EventTypeDescription
inputInputEventFires during value changes as the user rotates. It bubbles and is composed.
changeEventFires when the value is committed (timing controlled by changeMode). It bubbles.

Setting value from code fires neither input nor change.

Props⁠

PropTypeDescription
ariaDescribedBystringThe IDs of the elements that describe the control, space-separated. An element elsewhere on the page is not found.
ariaDescriptionstringNot announced by assistive technology. ariaDescribedBy is no substitute: an ID elsewhere on the page is not found.
ariaErrorMessagestringThe ID of the element describing the value's error. Used only while ariaInvalid is "true".
ariaInvalidstringWhether the control's value is invalid. A screen reader announces it; the control's appearance does not change.
ariaLabelledBystringThe IDs of the elements that label the control, space-separated. An element elsewhere on the page is not found: use aria-label.
asyncSinkValueChangeSinkThe 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.
changeModeChangeEventModeTypeChangeEventMode.Debounced, .Immediate, .InteractionEnded, .Throttled, .Adaptivedefault ChangeEventMode.InteractionEndedWhen 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.
directionDialDirectionTypeDialDirection.Clockwise, .CounterClockwisedefault DialDirection.ClockwiseSets which way the value increases around the dial, measured from originAngle. See Direction.
disabledbooleanWhether the element is disabled. Also reads true while a disabled <fieldset> contains it. See Disabled.
labeledbooleandefault falseWhether 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.
namestringThe name the element's value is submitted under with its form. See Forms.
originAnglenumberdefault 0The 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.
pageValuenumberHow 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.
rateLimitDelaynumberdefault 150The 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.
sinkDutyCyclenumberdefault 1The 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.
sizeSizeTypeSize.ExtraSmall, .Small, .Medium, .Large, .ExtraLargedefault Size.ExtraSmall, from the style configurationSets how large the component is, from extra-small to extra-large. A larger size makes it taller. See Size.
softDisabledbooleandefault falseDisables 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.
stepnumberdefault 1The 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.
tickmarksSliderTickmarkTypeSliderTickmark.None, .ContrastEndStop, .Valuesdefault SliderTickmark.ContrastEndStopThe type of tickmarks to show. Ignored while the trackBackgroundSnippet snippet is filled. See Tickmarks.
touchTargetTouchTargetTypeTouchTarget.None, .Overflow, .Wrapperdefault TouchTarget.Overflow, from the style configurationThe 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.
valuenumberThe 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.
valueLabelstringText 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⁠

SnippetDescription
trackBackgroundSnippetContent 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⁠

PropTypeDescription
onInputInputEventFires during value changes as the user rotates. It bubbles and is composed.
onChangeEventFires when the value is committed (timing controlled by changeMode). It bubbles.

Setting value from code fires neither input 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.

Nameextra-smallsmallmediumlargeextra-large
diameter112px --ct-dial-xsmall-diameter120px --ct-dial-small-diameter160px --ct-dial-medium-diameter212px --ct-dial-large-diameter292px --ct-dial-xlarge-diameter
handle-length44px --ct-dial-xsmall-handle-length44px --ct-dial-small-handle-length44px --ct-dial-medium-handle-length68px --ct-dial-large-handle-length108px --ct-dial-xlarge-handle-length
track-corner-end-end-radiussame as track-corner-radius --ct-dial-xsmall-track-corner-end-end-radiussame as track-corner-radius --ct-dial-small-track-corner-end-end-radiussame as track-corner-radius --ct-dial-medium-track-corner-end-end-radiussame as track-corner-radius --ct-dial-large-track-corner-end-end-radiussame as track-corner-radius --ct-dial-xlarge-track-corner-end-end-radius
track-corner-end-start-radiussame as track-corner-radius --ct-dial-xsmall-track-corner-end-start-radiussame as track-corner-radius --ct-dial-small-track-corner-end-start-radiussame as track-corner-radius --ct-dial-medium-track-corner-end-start-radiussame as track-corner-radius --ct-dial-large-track-corner-end-start-radiussame as track-corner-radius --ct-dial-xlarge-track-corner-end-start-radius
track-corner-radius8px --ct-dial-xsmall-track-corner-radius8px --ct-dial-small-track-corner-radius12px --ct-dial-medium-track-corner-radius16px --ct-dial-large-track-corner-radius28px --ct-dial-xlarge-track-corner-radius
track-corner-start-end-radiussame as track-corner-radius --ct-dial-xsmall-track-corner-start-end-radiussame as track-corner-radius --ct-dial-small-track-corner-start-end-radiussame as track-corner-radius --ct-dial-medium-track-corner-start-end-radiussame as track-corner-radius --ct-dial-large-track-corner-start-end-radiussame as track-corner-radius --ct-dial-xlarge-track-corner-start-end-radius
track-corner-start-start-radiussame as track-corner-radius --ct-dial-xsmall-track-corner-start-start-radiussame as track-corner-radius --ct-dial-small-track-corner-start-start-radiussame as track-corner-radius --ct-dial-medium-track-corner-start-start-radiussame as track-corner-radius --ct-dial-large-track-corner-start-start-radiussame as track-corner-radius --ct-dial-xlarge-track-corner-start-start-radius
track-thickness16px --ct-dial-xsmall-track-thickness24px --ct-dial-small-track-thickness40px --ct-dial-medium-track-thickness56px --ct-dial-large-track-thickness96px --ct-dial-xlarge-track-thickness

Other tokens⁠

These stay the same whatever the size.

TokenValue
--ct-dial-active-handle-space5px --ct-dial-active-handle-space
--ct-dial-active-handle-width2px --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-opacity1 --ct-dial-active-tick-mark-opacity
--ct-dial-active-track-color--ct-sys-color-primary --ct-dial-active-track-color
--ct-dial-center-space4px --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-opacity0.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-opacity0.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-opacity0.12 --ct-dial-disabled-inactive-track-opacity
--ct-dial-disabled-tick-mark-opacity0.38 --ct-dial-disabled-tick-mark-opacity
--ct-dial-handle-color--ct-sys-color-primary --ct-dial-handle-color
--ct-dial-handle-space6px --ct-dial-handle-space
--ct-dial-handle-width4px --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-opacity1 --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-size4px --ct-dial-tick-mark-size
--ct-dial-value-indicator-block-space12px --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-space16px --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 value-label, else the current number. Give every dial an aria-label, since the number alone names nothing.
  • A screen reader announces the value as the dial's own aria-valuetext if you set one, else value-label, else the number.
  • 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, aria-invalid, and aria-errormessage. Any other ARIA attribute has no effect.
  • A screen reader announces the aria-errormessage text only while aria-invalid is "true".
  • An ID that points to an element elsewhere on the page is not found, so name the dial with aria-label rather than aria-labelledby.
  • aria-description is not announced, and aria-describedby cannot stand in for it.

Keyboard and focus⁠

Key Action
Tab Moves focus to the dial or away from it.
Arrow keys Move the value by one step; on a counterclockwise dial, Right Arrow and Left Arrow swap directions.
PageUp and PageDown Move the value by page-value, ten times step unless set.
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.
  • disabled removes the dial from the Tab order. A dial inside a disabled <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-target set to none reduces it to the dial's own size, which is at least 112 pixels across at the smallest size. See Size for the three settings.

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:

  • 2.1.1 Keyboard (A)
  • 2.4.7 Focus Visible (AA)
  • 2.5.8 Target Size (Minimum) (AA)

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-label with the same words.
  • 3.3.1 Error Identification (A): when the value is invalid, set aria-invalid and point aria-errormessage at text that says what is wrong.