This commit is contained in:
2026-05-31 18:09:55 +03:00
parent 22afa7e1a5
commit a5d2742c7c
6 changed files with 123 additions and 33 deletions
+56 -8
View File
@@ -1,14 +1,62 @@
import { type ComponentPropsWithoutRef } from 'react';
import { Slider as RSlider } from 'radix-ui';
export const Slider = (props: ComponentPropsWithoutRef<typeof RSlider.Root>) => (
<RSlider.Root className="modern-sk-slider" {...props}>
<RSlider.Track className="modern-sk-slider__track">
<RSlider.Range className="modern-sk-slider__range" />
</RSlider.Track>
<RSlider.Thumb className="modern-sk-slider__thumb" aria-label="Value" />
</RSlider.Root>
);
type Step = { value: number; label?: string };
type SliderProps = ComponentPropsWithoutRef<typeof RSlider.Root> & {
steps?: number | Step[];
};
function resolveSteps(steps: number | Step[], min: number, max: number): Step[] {
if (Array.isArray(steps)) return steps;
if (steps < 2) return [];
return Array.from({ length: steps }, (_, i) => ({
value: min + (i / (steps - 1)) * (max - min),
}));
}
export const Slider = ({ steps, min = 0, max = 100, ...props }: SliderProps) => {
const resolved = steps != null ? resolveSteps(steps, min, max) : [];
const hasSteps = resolved.length > 0;
return (
<RSlider.Root
className={`modern-sk-slider${hasSteps ? ' modern-sk-slider--has-steps' : ''}`}
min={min}
max={max}
{...props}
>
<RSlider.Track className="modern-sk-slider__track">
<RSlider.Range className="modern-sk-slider__range" />
{hasSteps && resolved.map((step) => (
<div
key={step.value}
className="modern-sk-slider__step-dot"
aria-hidden
style={{ left: `${((step.value - min) / (max - min)) * 100}%` }}
/>
))}
</RSlider.Track>
<RSlider.Thumb className="modern-sk-slider__thumb" aria-label="Value" />
{hasSteps && (
<div className="modern-sk-slider__steps" aria-hidden>
{resolved.map((step) => (
<div
key={step.value}
className="modern-sk-slider__step"
style={{ left: `${((step.value - min) / (max - min)) * 100}%` }}
>
<div className="modern-sk-slider__step-tick" />
{step.label != null && (
<span className="modern-sk-slider__step-label">{step.label}</span>
)}
</div>
))}
</div>
)}
</RSlider.Root>
);
};
export const Stepper = ({
onDecrement,