Slider
Slider
단일 썸으로 값을 선택하는 슬라이더 컴포넌트예요.
출처: 문서
본문
사용법 (Usage)
Slider로 값을 선택해요. color, size, radius, label 관련 prop을 지원해요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider defaultValue={50} />;
}
제어 방식 (Controlled)
import { useState } from 'react';
import { Slider } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(40);
return <Slider value={value} onChange={setValue} />;
}
비제어 방식 (Uncontrolled)
Slider은 네이티브 인풋 요소와 같은 방식으로 비제어 폼에서 사용할 수 있어요. 폼 제출 시 FormData 객체에 슬라이더 값을 포함하려면 name 속성을 설정해요. 비제어 모드에서 초기 값을 설정하려면 defaultValue prop을 사용해요.
FormData와 함께 비제어 Slider을 사용하는 예시:
import { Slider } from '@mantine/core';
function Demo() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
console.log('Slider value:', formData.get('volume'));
}}
>
<Slider name="volume" />
<button type="submit">Submit</button>
</form>
);
}
비활성 (Disabled)
import { Slider } from '@mantine/core';
function Demo() {
return <Slider defaultValue={40} disabled />;
}
onChangeEnd
onChangeEnd 콜백은 사용자가 슬라이더 드래그를 멈추거나 키보드로 값을 변경할 때 호출돼요. 너무 빈번한 업데이트를 피하고자 디바운스된 콜백으로 사용할 수 있어요.
import { useState } from 'react';
import { Slider, Text, Box } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(50);
const [endValue, setEndValue] = useState(50);
return (
<Box>
<Slider value={value} onChange={setValue} onChangeEnd={setEndValue} />
<Text>onChange value: {value}</Text>
<Text>onChangeEnd value: {endValue}</Text>
</Box>
);
}
라벨 제어 (Control label)
라벨 동작과 모양을 바꾸려면 다음 prop을 설정해요.
label– 포맷터 함수, 값 인자를 받고, 라벨을 비활성화하려면 null 설정, 기본값은f => flabelAlwaysOn– true면 라벨이 항상 표시되고, 기본적으로는 사용자가 드래그할 때만 보여요labelTransitionProps– Transition 컴포넌트에 전달되는 prop, 라벨 애니메이션을 커스터마이즈하는 데 사용
import { Slider, Text } from '@mantine/core';
function Demo() {
return (
<>
<Text>No label</Text>
<Slider label={null} defaultValue={40} />
<Text>Formatted label</Text>
<Slider label={(value) => `${value} °C`} defaultValue={40} />
<Text>Label always visible</Text>
<Slider labelAlwaysOn defaultValue={40} />
<Text>Custom label transition</Text>
<Slider labelTransitionProps={{ transition: 'skew-up' }} defaultValue={40} />
</>
);
}
min, max와 step
import { Slider, Text } from '@mantine/core';
const marks = [
{ value: 0, label: 'xs' },
{ value: 25, label: 'sm' },
{ value: 50, label: 'md' },
{ value: 75, label: 'lg' },
{ value: 100, label: 'xl' },
];
function Demo() {
return (
<>
<Text>Decimal step</Text>
<Slider min={0} max={1} label={(value) => value.toFixed(1)} step={0.1} styles={{ markLabel: { display: 'none' } }} />
<Text>Step matched with marks</Text>
<Slider label={(val) => marks.find((mark) => mark.value === val)!.label} step={25} marks={marks} styles={{ markLabel: { display: 'none' } }} />
</>
);
}
도메인 (Domain)
기본적으로 min과 max prop이 시각적 범위(트랙 표시)와 선택 가능한 범위(가능한 값)를 모두 정의해요. domain prop으로 선택 가능한 범위를 독립적으로 제어할 수 있어요. (컨텍스트를 위해) 더 넓은 트랙을 표시하면서 실제 선택을 일부로 제한하고 싶을 때 유용해요.
아래 예시에서 트랙은 0100(80(min/max)을 표시하지만 썸은 20domain) 사이에서만 드래그할 수 있어요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider min={0} max={100} domain={[20, 80]} defaultValue={50} />;
}
소수 값 (Decimal values)
Slider을 소수 값과 함께 사용하려면 min, max, step prop을 설정해요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider min={0} max={1} step={0.1} defaultValue={0.4} />;
}
마크 (Marks)
marks prop을 객체 배열로 설정하면 슬라이더에 원하는 수의 마크를 추가할 수 있어요.
const marks = [
{ value: 20 }, // -> 슬라이더 트랙에 마크 표시
{ value: 40, label: '40%' }, // -> 슬라이더 트랙 아래에 마크 라벨 추가
];
마크 값은 너비가 아니라 슬라이더 값에 상대적이에요.
import { Slider } from '@mantine/core';
function Demo() {
return (
<Slider
defaultValue={50}
marks={[
{ value: 20, label: '20%' },
{ value: 50, label: '50%' },
{ value: 80, label: '80%' },
]}
/>
);
}
마크로 선택 제한 (Restrict selection to marks)
restrictToMarks prop으로 슬라이더 값을 마크로만 제한할 수 있어요. 이 경우 step prop은 무시돼요.
import { Slider } from '@mantine/core';
function Demo() {
return (
<Slider defaultValue={50} restrictToMarks marks={[{ value: 0 }, { value: 25 }, { value: 50 }, { value: 75 }, { value: 100 }]} />
);
}
썸 크기 (Thumb size)
thumbSize prop으로 썸 크기를 설정할 수 있어요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider defaultValue={40} thumbSize={26} />;
}
썸 children (Thumb children)
썸 안에 아이콘 같은 React 노드를 넣을 수 있어요.
import { Slider, RangeSlider } from '@mantine/core';
import { HeartIcon, HeartBreakIcon } from '@phosphor-icons/react';
function Demo() {
return (
<>
<Slider
color="red"
label={null}
defaultValue={40}
thumbSize={26}
thumbChildren={<HeartIcon size={14} />}
styles={{ thumb: { borderWidth: 2, padding: 3 } }}
/>
<RangeSlider
color="red"
label={null}
defaultValue={[25, 75]}
thumbSize={26}
thumbChildren={[<HeartBreakIcon key={1} size={14} />, <HeartIcon key={2} size={14} />]}
/>
</>
);
}
스케일 (Scale)
scale prop으로 값을 다른 스케일로 표현할 수 있어요. 아래 데모에서 값 x는 2^x를 나타내요. x를 1만큼 올리면 표현된 값이 x의 2제곱만큼 커져요.
import { RangeSlider, Slider } from '@mantine/core';
function valueLabelFormat(value: number) {
const units = ['KB', 'MB', 'GB', 'TB'];
let unitIndex = 0;
let scaledValue = value;
while (scaledValue >= 1024 && unitIndex < units.length - 1) {
unitIndex += 1;
scaledValue /= 1024;
}
return `${scaledValue} ${units[unitIndex]}`;
}
function Demo() {
return (
<>
<Slider min={0} max={10} step={0.01} label={valueLabelFormat} scale={(v) => 2 ** v} defaultValue={250} />
</>
);
}
시작점 (Start point)
startPointValue prop으로 채워진 막대의 원점을 변경할 수 있어요. 설정하면 막대가 주어진 값에서 현재 값 쪽으로 뻗어요. 시작점보다 낮은 값에서는 왼쪽으로, 높은 값에서는 오른쪽으로 뻗어요. inverted가 설정되면 이 prop은 무시돼요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider min={-100} max={100} startPointValue={0} defaultValue={50} />;
}
뒤집기 (Inverted)
inverted prop으로 트랙을 뒤집을 수 있어요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider inverted defaultValue={40} />;
}
Styles API
Slider은 Styles API를 지원해요. classNames prop으로 컴포넌트의 내부 요소에 스타일을 추가할 수 있어요.
Styles API 셀렉터:
root– 루트 요소label– 썸 라벨thumb– 썸 요소trackContainer– 트랙 요소를 감싸는 요소track– 슬라이더 트랙bar– 트랙의 채워진 부분markWrapper–mark와markLabel요소를 포함mark– 트랙에 표시되는 마크markLabel– 연관 마크의 라벨, 트랙 아래에 표시
세로 슬라이더 (Vertical slider)
orientation="vertical"로 설정하면 슬라이더를 세로로 렌더링해요. 세로 방향에서는 최소값이 아래, 최대값이 위에 있어요.
import { RangeSlider, Slider } from '@mantine/core';
const marks = [
{ value: 20, label: '20%' },
{ value: 50, label: '50%' },
{ value: 80, label: '80%' },
];
function Demo() {
return (
<>
<Slider orientation="vertical" marks={marks} defaultValue={50} />
<RangeSlider orientation="vertical" marks={marks} defaultValue={[20, 80]} />
</>
);
}
숨겨진 마크 (Hidden marks)
숨겨진 마크를 사용하면 트랙에 시각적으로 표시하지 않고 특정 값에 스냅할 수 있어요. 사용자에게 보여주고 싶지 않은 특정 값에 "끈적이는" 스냅 동작을 만들고 싶을 때 유용해요. 이 기능은 restrictToMarks prop과 함께 사용해요.
import { Slider, Text, Box } from '@mantine/core';
import { useState } from 'react';
function Demo() {
const [value, setValue] = useState(50);
return (
<>
<Text size="sm">
Hidden marks allow you to snap to specific values without displaying them visually.
Current value: {value}
</Text>
<Slider value={value} onChange={setValue} restrictToMarks hiddenMarks={[0, 25, 50, 75, 100]} />
</>
);
}
커스텀 슬라이더 만들기 (Build custom slider)
Slider 컴포넌트가 요구사항을 충족하지 못하면 use-move 훅으로 커스텀 슬라이더를 만들 수 있어요.
import { useState } from 'react';
import { DotsSixVerticalIcon } from '@phosphor-icons/react';
import { clamp, useMove } from '@mantine/hooks';
import classes from './Demo.module.css';
function Demo() {
const [value, setValue] = useState(0.3);
const { ref } = useMove(({ x }) => setValue(clamp(x, 0.1, 0.9)));
const labelFloating = value > 0.7 || value < 0.3;
return (
<div>
<div ref={ref} />
{(value * 100).toFixed(0)}
{((1 - value) * 100).toFixed(0)}
</div>
);
}
접근성 (Accessibility)
Slider 컴포넌트는 기본적으로 접근 가능해요.
- 썸은 포커스 가능해요
- 사용자가 마우스로 슬라이더를 조작하면 포커스가 슬라이더 트랙으로 이동하고, 화살표를 누르면 썸으로 이동해요
- 화살표 키로 step만큼 값을 증감할 수 있어요
스크린 리더를 위해 컴포넌트에 라벨을 지정하려면 썸에 라벨을 추가해요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider aria-label="Volume" />;
}
scale을 사용하거나 표시 값을 형식화(예: 통화나 백분율)한 경우, 스크린 리더가 읽을 수 있는 값을 제공하려면 thumbValueText를 설정해요. 이는 썸에 aria-valuetext로 렌더링돼요. 함수가 제공되면 스케일된 값을 받아요.
import { Slider } from '@mantine/core';
function Demo() {
return <Slider scale={(v) => v * 10} thumbValueText={(value) => `$${value}`} />;
}
키보드 상호작용 (Keyboard interactions)
| Key | Description |
|---|---|
| ArrowRight/ArrowUp | 슬라이더 값을 한 단계 증가 |
| ArrowLeft/ArrowDown | 슬라이더 값을 한 단계 감소 |
| Home | 슬라이더 값을 min 값으로 설정 |
| End | 슬라이더 값을 max 값으로 설정 |