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.jsonpnpm dlx shadcn@latest add https://kit.dev/r/angle-slider.jsonnpx shadcn@latest add https://kit.dev/r/angle-slider.jsonyarn shadcn@latest add https://kit.dev/r/angle-slider.jsonInstall the following dependencies:
bun add @ark-ui/reactpnpm add @ark-ui/reactnpm install @ark-ui/reactyarn add @ark-ui/reactCopy and paste the following code into your project.
"use client";
import {
AngleSlider as ArkAngleSlider,
useAngleSlider as useArkAngleSlider,
useAngleSliderContext as useArkAngleSliderContext,
} from "@ark-ui/react/angle-slider";
import type React from "react";
import { cn } from "@/lib/utils";
export const useAngleSlider = useArkAngleSlider;
export const useAngleSliderContext = useArkAngleSliderContext;
export const AngleSliderContext = ArkAngleSlider.Context;
const angleSliderRootClassName = cn(
"inline-flex flex-col items-center gap-4",
"data-disabled:pointer-events-none data-disabled:opacity-64 data-disabled:grayscale"
);
export const AngleSlider = (
props: React.ComponentProps<typeof ArkAngleSlider.Root>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.Root
className={cn(angleSliderRootClassName, className)}
data-slot="angle-slider"
{...rest}
/>
);
};
export const AngleSliderRootProvider = (
props: React.ComponentProps<typeof ArkAngleSlider.RootProvider>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.RootProvider
className={cn(angleSliderRootClassName, className)}
data-slot="angle-slider"
{...rest}
/>
);
};
export const AngleSliderLabel = (
props: React.ComponentProps<typeof ArkAngleSlider.Label>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.Label
className={cn("select-none font-medium text-sm", className)}
data-slot="angle-slider-label"
{...rest}
/>
);
};
export const AngleSliderControl = (
props: React.ComponentProps<typeof ArkAngleSlider.Control>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.Control
className={cn(
"relative flex size-[var(--size)] items-center justify-center rounded-full",
"select-none bg-muted",
"[--size:100px] [--thumb-width:3px] [--track-width:4px]",
"shadow-[inset_0_2px_4px_rgb(0_0_0/0.06)]",
"before:pointer-events-none before:absolute before:inset-[var(--track-width)] before:rounded-full before:bg-background before:shadow-[inset_0_1px_3px_rgb(0_0_0/0.08)]",
"after:pointer-events-none after:absolute after:z-1 after:size-1.5 after:rounded-full after:bg-muted-foreground",
"has-focus-visible:ring-[3px] has-focus-visible:ring-ring/32",
className
)}
data-slot="angle-slider-control"
{...rest}
/>
);
};
export const AngleSliderThumb = (
props: React.ComponentProps<typeof ArkAngleSlider.Thumb>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.Thumb
className={cn(
"absolute inset-y-0 z-2 w-[var(--thumb-width)] outline-none",
"left-[calc(50%-var(--thumb-width)/2)]",
"before:absolute before:top-1 before:left-1/2 before:size-2.5 before:-translate-x-1/2",
"before:rounded-full before:border-2 before:border-background before:bg-primary",
"before:shadow-xs before:transition-transform",
"after:absolute after:top-3.5 after:left-1/2 after:w-0.5 after:-translate-x-1/2",
"after:h-[calc(var(--size)/2-18px)] after:rounded-px",
"after:bg-linear-to-b after:from-primary after:to-transparent",
"active:before:-translate-x-1/2 active:before:scale-110",
"motion-reduce:before:transition-none!",
className
)}
data-slot="angle-slider-thumb"
{...rest}
/>
);
};
export const AngleSliderMarkerGroup = (
props: React.ComponentProps<typeof ArkAngleSlider.MarkerGroup>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.MarkerGroup
className={cn(
"pointer-events-none absolute inset-0 z-0 rounded-full",
className
)}
data-slot="angle-slider-marker-group"
{...rest}
/>
);
};
export const AngleSliderMarker = (
props: React.ComponentProps<typeof ArkAngleSlider.Marker>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.Marker
className={cn(
"absolute inset-y-0 w-0.5",
"left-[calc(50%-1px)]",
"before:absolute before:top-1.5 before:left-1/2 before:h-1.5 before:w-0.5 before:-translate-x-1/2",
"before:rounded-px before:bg-border",
"data-[state=at-value]:before:bg-primary",
"data-[state=under-value]:before:bg-primary/40",
className
)}
data-slot="angle-slider-marker"
{...rest}
/>
);
};
export const AngleSliderValueText = (
props: React.ComponentProps<typeof ArkAngleSlider.ValueText>
) => {
const { className, ...rest } = props;
return (
<ArkAngleSlider.ValueText
className={cn(
"font-semibold text-xl tabular-nums leading-none",
className
)}
data-slot="angle-slider-value-text"
{...rest}
/>
);
};
export const AngleSliderHiddenInput = (
props: React.ComponentProps<typeof ArkAngleSlider.HiddenInput>
) => (
<ArkAngleSlider.HiddenInput data-slot="angle-slider-hidden-input" {...props} />
);Update the import paths to match your project setup.
Anatomy
AngleSlider
├── AngleSliderLabel
├── AngleSliderThumb
├── AngleSliderValueText
├── AngleSliderControl
├── AngleSliderTrack
└── AngleSliderMarker
└── AngleSliderMarkerGroupUsage
import {
AngleSlider,
AngleSliderControl,
AngleSliderHiddenInput,
AngleSliderLabel,
AngleSliderMarker,
AngleSliderMarkerGroup,
AngleSliderThumb,
AngleSliderValueText,
} from "@/components/ui/angle-slider";const MARKERS = [0, 45, 90, 135, 180, 225, 270, 315];
const Example = () => (
<AngleSlider>
<AngleSliderLabel>Rotation</AngleSliderLabel>
<AngleSliderControl>
<AngleSliderMarkerGroup>
{MARKERS.map((value) => (
<AngleSliderMarker key={value} value={value} />
))}
</AngleSliderMarkerGroup>
<AngleSliderThumb />
</AngleSliderControl>
<AngleSliderValueText />
<AngleSliderHiddenInput />
</AngleSlider>
);Accessibility
| Key | Description |
|---|---|
ArrowLeft | Decrease the value. |
ArrowUp | Decrease the value. |
ArrowRight | Increase the value. |
ArrowDown | Increase the value. |
Home | Go to the start. |
End | Go to the end. |
Demos
Context
Controlled
Disabled
Root Provider
Step
API Reference
AngleSlider
div
PropType
AttributeType
CSS variableType
AngleSliderLabel
label
PropType
AttributeType
AngleSliderThumb
div
PropType
AttributeType
CSS variableType
AngleSliderValueText
div
PropType
AttributeType
AngleSliderControl
div
PropType
AttributeType
CSS variableType
AngleSliderMarkerGroup
div
PropType
AttributeType
AngleSliderMarker
div
PropType
AttributeType
CSS variableType
AngleSliderHiddenInput
input
PropType
AttributeType
AngleSliderRootProvider
div
PropType
AttributeType
CSS variableType
useAngleSlider
PropType
AngleSliderContext
PropType