컴포넌트
Slider
범위 안에서 숫자를 조절합니다.
설치
pnpm dlx ply-ui add slider공통 설치 설정을 먼저 적용합니다.
사용법
min/max/step으로 범위와 이동 단위를 지정합니다.
Label과 Value는 설명과 현재 수치를 표시합니다. value/onValueChange로 상태를 연결합니다.
구성
| 구성 요소 | 역할 |
|---|---|
Root | 값과 min, max, step을 관리합니다. |
Label / Value | 이름과 현재 값을 표시합니다. |
Control | 포인터 조작 영역입니다. |
Track | 전체 범위를 표시합니다. |
Indicator | 선택된 값 또는 구간을 표시합니다. |
Thumb | 키보드와 포인터로 조작하는 손잡이입니다. |
범위 선택
값 두 개와 Thumb 두 개로 구간을 선택합니다. 각 Thumb에 서로 다른 이름을 지정합니다.
비활성
Root.disabled는 모든 Thumb의 조작을 막습니다.
구현 코드
components/ui/slider.tsx
"use client";
import type { ComponentProps } from "react";
import { Slider as Primitive } from "@base-ui/react/slider";
import { withClassName } from "../../lib/cx";
import "./slider.css";
// 동작과 접근성은 Base UI가 담당합니다. 이 파일은 스타일 연결만 담당합니다.
function SliderRoot({
className,
...props
}: ComponentProps<typeof Primitive.Root>) {
return (
<Primitive.Root
{...props}
className={withClassName("rbx-slider", className)}
/>
);
}
function SliderLabel({
className,
...props
}: ComponentProps<typeof Primitive.Label>) {
return (
<Primitive.Label
{...props}
className={withClassName("rbx-label", className)}
/>
);
}
function SliderValue({
className,
...props
}: ComponentProps<typeof Primitive.Value>) {
return (
<Primitive.Value
{...props}
className={withClassName("rbx-description", className)}
/>
);
}
function SliderControl({
className,
...props
}: ComponentProps<typeof Primitive.Control>) {
return (
<Primitive.Control
{...props}
className={withClassName("rbx-slider-control", className)}
/>
);
}
function SliderTrack({
className,
...props
}: ComponentProps<typeof Primitive.Track>) {
return (
<Primitive.Track
{...props}
className={withClassName("rbx-slider-track", className)}
/>
);
}
function SliderIndicator({
className,
...props
}: ComponentProps<typeof Primitive.Indicator>) {
return (
<Primitive.Indicator
{...props}
className={withClassName("rbx-slider-indicator", className)}
/>
);
}
function SliderThumb({
className,
...props
}: ComponentProps<typeof Primitive.Thumb>) {
return (
<Primitive.Thumb
{...props}
className={withClassName("rbx-slider-thumb", className)}
/>
);
}
// Root/Portal 등 스타일 없는 파트와 제네릭 API는 원본을 그대로 보존합니다.
export const Slider = {
...Primitive,
Root: SliderRoot,
Label: SliderLabel,
Value: SliderValue,
Control: SliderControl,
Track: SliderTrack,
Indicator: SliderIndicator,
Thumb: SliderThumb,
};
components/ui/slider.css
/* Slider: 공통 구조는 theme.css, 컴포넌트 전용 조정은 아래에 작성합니다. */
.rbx-slider {
display: grid;
gap: 8px;
width: 100%;
}
.rbx-slider-control {
display: flex;
align-items: center;
height: 28px;
touch-action: none;
}
.rbx-slider-track {
position: relative;
height: 6px;
border-radius: 99px;
background: var(--rbx-color-shift-300);
width: 100%;
}
.rbx-slider-indicator {
position: absolute;
border-radius: inherit;
background: var(--rbx-color-system-emphasis);
}
.rbx-slider-thumb {
width: 20px;
height: 20px;
border: 3px solid var(--rbx-color-system-emphasis);
border-radius: 50%;
background: var(--rbx-color-extended-white-100);
}
.rbx-slider[data-orientation="vertical"] .rbx-slider-control {
width: 28px;
height: 180px;
justify-content: center;
}
.rbx-slider[data-orientation="vertical"] .rbx-slider-track {
width: 6px;
height: 100%;
}