AngleSlider

Pick angle value between 0 and 360

Usage

Use AngleSlider component to pick angle value between 0 and 360:

0
Size
Thumb size
import { AngleSlider } from '@mantine/core';

function Demo() {
  return <AngleSlider aria-label="Angle slider" size={60} thumbSize={8} />;
}

Controlled

AngleSlider value is a number between 0 and 360.

import { useState } from 'react';
import { AngleSlider } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState(180);
  return <AngleSlider value={value} onChange={setValue} />;
}

formatLabel

Use the formatLabel prop to change the angle label format. It accepts a function that takes the angle value and returns a React node:

import { AngleSlider } from '@mantine/core';

function Demo() {
  return <AngleSlider aria-label="Angle slider" formatLabel={(value) => `${value}°`} />;
}

Marks

Set the marks prop to display marks on the slider. Mark is an object of value (required, number between 0 and 360) and label (optional, React node). To restrict selection to marks only, set the restrictToMarks prop:

import { AngleSlider, Group } from '@mantine/core';

function Demo() {
  return (
    <Group p="lg" gap={50}>
      <AngleSlider
        aria-label="Angle slider"
        formatLabel={(value) => `${value}°`}
        size={100}
        restrictToMarks
        marks={[
          { value: 0 },
          { value: 45 },
          { value: 90 },
          { value: 135 },
          { value: 180 },
          { value: 225 },
          { value: 270 },
          { value: 315 },
        ]}
      />

      <AngleSlider
        aria-label="Angle slider"
        formatLabel={(value) => `${value}°`}
        size={100}
        marks={[
          { value: 0, label: '0°' },
          { value: 45, label: '45°' },
          { value: 90, label: '90°' },
          { value: 135, label: '135°' },
          { value: 180, label: '180°' },
          { value: 225, label: '225°' },
          { value: 270, label: '270°' },
          { value: 315, label: '315°' },
        ]}
      />
    </Group>
  );
}

onChangeEnd

The onChangeEnd callback fires when the user stops dragging the slider or changes its value with the keyboard. Use it as a debounced callback to prevent frequent updates.

0

Current value: 0

End value: 0

import { useState } from 'react';
import { AngleSlider, Text } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState(0);
  const [endValue, setEndValue] = useState(0);

  return (
    <>
      <AngleSlider value={value} onChange={setValue} onChangeEnd={setEndValue} />
      <Text mt="md">Current value: {value}</Text>
      <Text>End value: {endValue}</Text>
    </>
  );
}

disabled

disabled prop disables the component and prevents user interaction:

0
import { AngleSlider } from '@mantine/core';

function Demo() {
  return <AngleSlider aria-label="Angle slider" disabled />;
}

Accessibility

To make the component accessible for screen readers, set the aria-label prop:

import { AngleSlider } from '@mantine/core';

function Demo() {
  return <AngleSlider aria-label="Gradient angle" />;
}

Keyboard interactions when the component is focused:

KeyDescription
ArrowDownDecreases value by step
ArrowLeftDecreases value by step
ArrowUpIncreases value by step
ArrowRightIncreases value by step
HomeSets value to 0
EndSets value to 359

Based on use-radial-move

AngleSlider is based on the use-radial-move hook. You can build a custom radial slider using this hook if you need more control over the component's behavior.

115°
import { useState } from 'react';
import { Box } from '@mantine/core';
import { useRadialMove } from '@mantine/hooks';
import classes from './Demo.module.css';

function Demo() {
  const [value, setValue] = useState(115);
  const { ref } = useRadialMove(setValue);

  return (
    <Box className={classes.root} ref={ref} style={{ '--angle': `${value}deg` }}>
      <div className={classes.value}>{value}°</div>
      <div className={classes.thumb} />
    </Box>
  );
}