## slider (`poetry_slider`)

An input for selecting a value or range along a track.

Class: Poetry::Ui::Slider::Component - BEM block `poetry-ui-slider`.
- `described_by:` (string) - Field hint/error wiring -> aria-describedby on EACH thumb.
- `disabled:` (boolean) - default false - Renders the control inert; the hidden inputs still submit the server value.
- `inverted:` (boolean) - default false - Flips the value direction along the axis; composes with RTL (both = ltr math).
- `label:` () - Per-thumb accessible names -> aria-label; range REQUIRES two. Alternatively labelled_by (external wiring). Enforced.
- `labelled_by:` (string) - aria-labelledby for the thumb(s) - the Field-wrapped single slider derives its name from the field label this way.
- `max:` (float) - default 100.0 - The track's upper bound; must exceed min:.
- `min:` (float) - default 0.0 - The track's lower bound.
- `min_steps_between_thumbs:` (integer) - default 0 - Range-mode minimum gap in STEPS: high - low >= n*step; thumbs can never cross.
- `name:` (string) - required - Form name; single thumb -> name; range -> name + "[]" per input (the Rails array-param convention).
- `orientation:` (symbol) - one of horizontal|vertical, default "horizontal" - The track axis.
- `step:` (float) - default 1.0 - Snap increment; decimal steps supported (precision-aware rounding lives in the controller's math core).
- `value:` () - Single-thumb value. ArgumentError if given with values:.
- `value_text:` () - aria-valuetext formatter: a proc (v -> "$200") or an i18n key with %{value}; optional - falls back to the bare number.
- `values:` () - Range mode: [low, high] -> two thumbs, sorted. ArgumentError if given with value:, unsorted, or length != 2.
- PART `slider` - Root - the controller, the geometry vars, and pointer capture ride here | states: data-orientation=horizontal|vertical (always - the axis); data-disabled (disabled: is set (the control is inert; the hidden inputs still submit)); data-dragging (a pointer drag is in flight (the controller sets it for the gesture; never rendered server-side)) | vars: --slider-start (the filled range's start edge as a percentage - server-rendered (no first-paint jump), rewritten by the controller on every move); --slider-end (the filled range's end edge as a percentage (the single-thumb value rides here))
- PART `slider-track` - The full-length rail the range paints over | states: data-orientation=horizontal|vertical (always - mirrors the root)
- PART `slider-range` - The filled span between --slider-start and --slider-end | states: data-orientation=horizontal|vertical (always - mirrors the root)
- PART `slider-anchor` - Absolutely positioned thumb wrapper (one per thumb, with its hidden input alongside) seated on the geometry vars | states: data-orientation=horizontal|vertical (always - mirrors the root)
- PART `slider-thumb` - The role=slider handle - its own Tab stop, carrying the aria-value* surface (bounds neighbor-clamped in range mode) | states: data-orientation=horizontal|vertical (always - mirrors the root); data-disabled (disabled: is set (tabindex drops to -1)); data-dragging (this thumb is the one being dragged (the controller pairs it with the root's))
- WIRING root: `poetry--core--slider` registers; values min, max, step, value, min_steps_between_thumbs, orientation, inverted; actions pointerdown on pointerdown
- WIRING track: `poetry--core--slider` targets track
- WIRING range: `poetry--core--slider` targets range
- WIRING thumb: `poetry--core--slider` actions keydown on keydown; targets thumb
- WIRING input: `poetry--core--slider` targets input
- RULE: Use poetry_slider / form.slider - never hand-roll a draggable div.
- RULE: Every thumb MUST have a distinct accessible name (label: - array of two for ranges). ArgumentError otherwise.
- RULE: Give value_text: whenever the number alone is meaningless ('$200', '80%') - SR users hear aria-valuetext.
- RULE: Range mode: values must be sorted [low, high]; use min_steps_between_thumbs to keep a meaningful gap.
- RULE: Do not use Slider for precise known-number entry (use Input type=number) or in no-JS-required forms (native input type=range).
- RULE: Debounce on poetry:slider:commit, never on :change (change fires every drag frame).
- RULE: Never transition the thumb/range position with CSS - geometry must track the pointer.
