Skip to content
shadcn.io is not affiliated with official shadcn/ui

Shadcn Angle Slider for React and Tailwind

A control for selecting an angle in a circular range.

0deg

Installation

bunx --bun shadcn@latest add https://kit.dev/r/angle-slider.json

For a progress-ring style dial, see Circular Slider.

Anatomy

AngleSlider
├── AngleSliderContext
├── AngleSliderLabel
├── AngleSliderControl
│   ├── AngleSliderMarkerGroup
│   │   └── AngleSliderMarker
│   └── AngleSliderThumb
├── AngleSliderValueText
└── AngleSliderHiddenInput

Usage

import {
  AngleSlider,
  AngleSliderControl,
  AngleSliderHiddenInput,
  AngleSliderLabel,
  AngleSliderMarker,
  AngleSliderMarkerGroup,
  AngleSliderThumb,
  AngleSliderValueText,
} from "@/components/ui/angle-slider";
<AngleSlider>
  <AngleSliderLabel>Rotation</AngleSliderLabel>
  <AngleSliderControl>
    <AngleSliderMarkerGroup>
      {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => (
        <AngleSliderMarker key={value} value={value} />
      ))}
    </AngleSliderMarkerGroup>
    <AngleSliderThumb />
  </AngleSliderControl>
  <AngleSliderValueText />
  <AngleSliderHiddenInput />
</AngleSlider>

Controlled

Use value and onValueChange to control the angle.

Root Provider

Use useAngleSlider with AngleSliderRootProvider when you need the API outside the tree.

States

Disabled

Examples

Steps

Use step to snap the thumb to discrete angles.

Context

Use AngleSliderContext or useAngleSliderContext to read the current value.

API Reference

asChild merges props onto a single child element. The thumb is a role="slider" with values from 0 to 360.

AngleSlider

Root. Renders a div. Sets --value and --angle on the element.

PropTypeDefaultDescription
aria-labelstring-Accessible name for the thumb when there is no visible label.
aria-labelledbystring-Id of the element that labels the thumb. Defaults to the label id.
asChildbooleanfalseRender the child element instead of a div.
classNamestring-Class names on the root.
defaultValuenumber0Uncontrolled initial angle in degrees.
dir"ltr" | "rtl"-Text direction. Usually inherited from LocaleProvider.
disabledboolean-Disable pointer and keyboard input.
idstring-Unique id for the machine.
idsPartial<{ root: string; thumb: string; hiddenInput: string; control: string; valueText: string; label: string }>-Element ids for composition.
invalidboolean-Marks the slider as invalid.
namestring-Name for form submission (hidden input).
onValueChange(details: ValueChangeDetails) => void-Called when the value changes. ValueChangeDetails is { value: number }.
onValueChangeEnd(details: ValueChangeDetails) => void-Called when dragging or stepping ends.
readOnlyboolean-Focusable but not editable.
stepnumber1Snap increment in degrees.
valuenumber-Controlled angle in degrees (0360).
AttributeDescription
data-slotangle-slider
data-scopeangle-slider
data-partroot
data-disabledPresent when disabled
data-invalidPresent when invalid
data-readonlyPresent when read-only
CSS variableDescription
--valueCurrent numeric value
--angleDisplay angle used to rotate the thumb (accounts for dir)

AngleSliderLabel

Visible label. Clicking it focuses the thumb. Renders a label.

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the label.
AttributeDescription
data-slotangle-slider-label
data-scopeangle-slider
data-partlabel
data-disabledPresent when disabled
data-invalidPresent when invalid
data-readonlyPresent when read-only

AngleSliderControl

Circular track. Pointer down on the ring or thumb starts dragging. Renders a div.

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the control. Override --size, --track-width, or --thumb-width here.
AttributeDescription
data-slotangle-slider-control
data-scopeangle-slider
data-partcontrol
data-disabledPresent when disabled
data-invalidPresent when invalid
data-readonlyPresent when read-only
CSS variableDefaultDescription
--size100pxDiameter of the dial
--track-width4pxThickness of the outer ring
--thumb-width3pxWidth of the rotating needle

AngleSliderThumb

Draggable needle. Renders a div with role="slider". Rotated with --angle.

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the thumb.
AttributeDescription
data-slotangle-slider-thumb
data-scopeangle-slider
data-partthumb
data-disabledPresent when disabled
data-invalidPresent when invalid
data-readonlyPresent when read-only

AngleSliderMarkerGroup

Container for tick marks. Renders a div.

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the group.
AttributeDescription
data-slotangle-slider-marker-group
data-scopeangle-slider
data-partmarker-group

AngleSliderMarker

A tick at a given angle. Renders a div. Rotated to its value.

PropTypeDefaultDescription
valuenumberrequiredAngle of the marker in degrees.
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the marker.
AttributeDescription
data-slotangle-slider-marker
data-scopeangle-slider
data-partmarker
data-valueThe marker angle
data-state"under-value", "at-value", or "over-value"
data-disabledPresent when disabled

AngleSliderValueText

Displays valueAsDegree unless you pass children. Renders a div.

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the value.
childrenReactNode-Custom content. Defaults to the formatted degree string.
AttributeDescription
data-slotangle-slider-value-text
data-scopeangle-slider
data-partvalue-text

AngleSliderHiddenInput

Hidden input for form submission. Renders an input type="hidden".

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
AttributeDescription
data-slotangle-slider-hidden-input

AngleSliderRootProvider

Root alternative that takes the API from useAngleSlider. Renders a div.

PropTypeDefaultDescription
valueUseAngleSliderReturnrequiredReturn value of useAngleSlider().
asChildbooleanfalseRender the child element instead of a div.
classNamestring-Class names on the root.

Pass defaultValue, step, disabled, and other machine options to useAngleSlider(), not to AngleSliderRootProvider.

useAngleSlider

Creates the angle slider API for AngleSliderRootProvider. Accepts the same options as AngleSlider except asChild and className.

const angleSlider = useAngleSlider({ defaultValue: 45, step: 15 });

AngleSliderContext / useAngleSliderContext

Render-prop or hook access to slider state. Use inside AngleSlider or AngleSliderRootProvider.

PropertyTypeDescription
valuenumberCurrent angle in degrees.
valueAsDegreestringFormatted degree string (for example "45deg").
draggingbooleanWhether the thumb is being dragged.
setValue(value: number) => voidSet the angle.

AngleSliderContext children: (context) => ReactNode.

Accessibility

The thumb is a role="slider" with aria-valuemin={0}, aria-valuemax={360}, and aria-valuenow set to the current value. Pair it with AngleSliderLabel, or pass aria-label / aria-labelledby on AngleSlider.

Keyboard support

KeyDescription
ArrowRightIncrease the value by step.
ArrowLeftDecrease the value by step.
ArrowUpDecrease the value by step.
ArrowDownIncrease the value by step.
HomeSet the value to 0.
EndSet the value to 360.
Shift + ArrowLarger step (native event step multiplier).