first commit
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
# `<SliderV>`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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
|
||||
|
||||
```tsx
|
||||
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:
|
||||
|
||||
```tsx
|
||||
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.
|
||||
Reference in New Issue
Block a user