āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/diceui/angle-slider ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
A circular slider component for selecting angles with precise control and customizable appearance.
npx shadcn@latest add @diceui/angle-slider
Copy and paste the component source code into your project.
import {
AngleSlider,
AngleSliderRange,
AngleSliderThumb,
AngleSliderTrack,
AngleSliderValue,
} from "@/components/ui/angle-slider";
<AngleSlider>
<AngleSliderTrack>
<AngleSliderRange />
</AngleSliderTrack>
<AngleSliderThumb />
<AngleSliderValue />
</AngleSlider>
Import the parts and compose them together:
import {
AngleSlider,
AngleSliderRange,
AngleSliderThumb,
AngleSliderTrack,
AngleSliderValue,
} from "@/components/ui/angle-slider";
<AngleSlider>
<AngleSliderTrack>
<AngleSliderRange />
</AngleSliderTrack>
<AngleSliderThumb />
<AngleSliderValue />
</AngleSlider>
A slider with controlled state management and custom actions:
const [angle, setAngle] = React.useState([45]);
<AngleSlider value={angle} onValueChange={setAngle}>
<AngleSliderTrack>
<AngleSliderRange />
</AngleSliderTrack>
<AngleSliderThumb />
<AngleSliderValue />
</AngleSlider>
Use multiple thumbs to create angle ranges with minimum step constraints:
<AngleSlider
defaultValue={[0, 180]}
minStepsBetweenThumbs={10}
>
<AngleSliderTrack>
<AngleSliderRange />
</AngleSliderTrack>
<AngleSliderThumb index={0} />
<AngleSliderThumb index={1} />
<AngleSliderValue />
</AngleSlider>
Integrate the angle slider with form validation and submission:
<form onSubmit={handleSubmit}>
<AngleSlider name="rotation" defaultValue={[0]}>
<AngleSliderTrack>
<AngleSliderRange />
</AngleSliderTrack>
<AngleSliderThumb />
<AngleSliderValue />
</AngleSlider>
<button type="submit">Submit</button>
</form>
You can customize the appearance by targeting specific components:
Use [&>[data-slot='angle-slider-track-rail']] to style the background track:
<AngleSliderTrack className="[&>[data-slot='angle-slider-track-rail']]:stroke-green-100" />
<AngleSliderRange className="stroke-green-500" />
<AngleSliderThumb className="border-green-500 bg-green-50 ring-green-500/50" />
<AngleSliderValue className="text-green-600 dark:text-green-400" />
The main container component for the angle slider.
| Prop | Type | Description | Default |
| :--- | :--- | :--- | :--- |
| value | number[] | Controlled value of the slider | - |
| defaultValue | number[] | Default value when uncontrolled | [0] |
| onValueChange | (value: number[]) => void | Callback fired when value changes | - |
| onValueCommit | (value: number[]) => void | Callback fired when interaction ends | - |
| min | number | Minimum value | 0 |
| max | number | Maximum value | 100 |
| step | number | Step increment | 1 |
| minStepsBetweenThumbs | number | Minimum steps between thumbs | 0 |
| size | number | Radius of the circular track | 60 |
| thickness | number | Thickness of the track | 8 |
| startAngle | number | Starting angle in degrees | -90 |
| endAngle | number | Ending angle in degrees | 270 |
| disabled | boolean | Whether the slider is disabled | false |
| inverted | boolean | Inverts the slider direction | false |
| dir | "ltr" \| "rtl" | Text direction | "ltr" |
| name | string | Name for form submission | - |
| form | string | Associated form id | - |
Data Attributes:
| Data Attribute | Value |
| :--- | :--- |
| [data-disabled] | Present when the angle slider is disabled. |
The circular track that represents the full range of possible values.
Data Attributes:
| Data Attribute | Value |
| :--- | :--- |
| [data-disabled] | Present when the angle slider is disabled. |
| [data-slot='angle-slider-track-rail'] | Present on the rail of the track. |
The portion of the track that represents the selected range.
Data Attributes:
| Data Attribute | Value |
| :--- | :--- |
| [data-disabled] | Present when the angle slider is disabled. |
The draggable handle for selecting values.
| Prop | Type | Description | Default |
| :--- | :--- | :--- | :--- |
| index | number | Index of the thumb in multi-thumb scenarios | 0 |
Data Attributes:
| Data Attribute | Value |
| :--- | :--- |
| [data-disabled] | Present when the angle slider is disabled. |
Displays the current value(s) with customizable formatting.
| Prop | Type | Description | Default |
| :--- | :--- | :--- | :--- |
| unit | string | Unit to display after the value | "°" |
| formatValue | (value: number \| number[]) => string | Custom formatter function | - |
Data Attributes:
| Data Attribute | Value |
| :--- | :--- |
| [data-disabled] | Present when the angle slider is disabled. |
The angle slider component includes comprehensive accessibility features:
| Key | Action |
| :--- | :--- |
| ArrowUp / ArrowRight | Increase the value by one step. |
| ArrowDown / ArrowLeft | Decrease the value by one step. |
| PageUp | Increase the value by ten steps. |
| PageDown | Decrease the value by ten steps. |
| Shift + Arrow Keys | Increase/decrease the value by ten steps. |
| Home | Set the value to the minimum. |
| End | Set the value to the maximum. |
role="slider" semanticsaria-valuemin, aria-valuenow, aria-valuemax attributesā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā