Files
skills/docs/ui/react/react-control-surface/src/controls/slider-v/slider-v.md
2026-05-29 08:20:56 +01:00

3.5 KiB

<SliderV>

(no submodules)

Purpose

Vertical slider control. Pointer interaction sets the value directly from clientY against the rendered track rect — drag is a single continuous gesture from pointerdown through pointermove until pointerup / pointercancel. Keyboard handling delegates to the shared keyboardStep helper so the up/down behaviour stays in lockstep with <SliderH> (which uses left/right). Detents snap nearby values to caller-provided breakpoints, useful for mix-engineering faders that want a hard 0 dB stop.

Features

  • Pointer capture for jitter-free drag past the SVG bounds.
  • Optional detent snapping with a per-control or default threshold.
  • Keyboard accessibility: arrow keys, Home, End, PageUp, PageDown, Shift fine-mode.
  • aria-slider with aria-orientation="vertical".
  • CSS-variable theming (--cs-slider-track-color, --cs-slider-thumb-color, --cs-slider-detent-color).
  • Auto-rendered detent ticks on the track.
  • Step-quantized output via step (default 0.01).

Usage: Basic

import { useState } from "react";
import { SliderV } from "@suaveplan/react-control-surface";

export function VolumeSlider() {
    const [v, setV] = useState(0.5);
    return (
        <SliderV
            value={v}
            onChange={setV}
            min={0}
            max={1}
            step={0.01}
            label="Volume"
        />
    );
}

Usage: Advanced

Mixer-style fader in dB with detents at -∞ / -20 / 0:

import { useState } from "react";
import { SliderV } from "@suaveplan/react-control-surface";

export function ChannelFader() {
    const [db, setDb] = useState(0);
    return (
        <SliderV
            value={db}
            onChange={setDb}
            min={-60}
            max={12}
            step={0.5}
            label="Channel 1"
            detents={[
                { at: -60, label: "-∞" },
                { at: -20, label: "-20" },
                { at: 0, label: "0 dB" },
            ]}
            snapThreshold={0.5}
            trackPx={240}
            thicknessPx={32}
        />
    );
}

API Reference

Prop Type Default
value number required
onChange (v: number) => void required
min number required
max number required
step number 0.01
disabled boolean false
label string —
ariaLabel string —
detents SliderDetent[] —
snapThreshold number 2% span
trackPx number 160
thicknessPx number 24
fineModeFactor number 0.1
className string —

Implementation Notes

The slider derives value from the rendered SVG rect (not the bare trackPx) so it remains accurate when the host container resizes it via CSS. The internal helper module slider-helpers.ts is shared verbatim with <SliderH>; the orientation flip lives entirely inside keyboardStep and the visual rendering. When the rect height collapses to 0 (offscreen / display:none), the math falls back to trackPx so drag interactions continue to produce a sensible value.