Slider
An input for selecting a value or range along a track.
Installation
Included in poetry-ui — available as
poetry_slider
the moment you've installed Poetry,
with no per-component step. To own the source and edit it, copy it into your app:
bin/rails g poetry:add slider
Default
<%= poetry_slider(name: "progress", value: 50, label: "Progress", class: "w-80") %>
Controlled
<%# The live readout rides poetry:slider:change (detail.value is the
full thumb array) - a docs-only harness mirrors it into the span;
in an app the same event drives whatever needs the value. %>
<div class="mx-auto grid w-full max-w-xs gap-3" data-controller="demo-slider-value"
data-action="poetry:slider:change->demo-slider-value#update">
<div class="flex items-center justify-between gap-2">
<span class="text-sm font-medium">Temperature</span>
<span class="text-sm text-muted-foreground" data-demo-slider-value-target="output">0.3, 0.7</span>
</div>
<%= poetry_slider(name: "temperature", values: [0.3, 0.7], min: 0, max: 1, step: 0.1,
label: ["Low temperature", "High temperature"]) %>
</div>
Disabled
<%= poetry_slider(name: "volume", value: 40, disabled: true, label: "Volume", class: "w-80") %>
Multiple thumbs
<%# values: takes any ascending list - one accessible name per thumb;
each thumb clamps against its neighbors while dragging. %>
<%= poetry_slider(name: "stops", values: [10, 20, 70], min: 0, max: 100, step: 10,
label: ["First stop", "Second stop", "Third stop"],
class: "mx-auto w-full max-w-xs") %>
Range
<%= poetry_slider(name: "price_range", values: [200, 800], min: 0, max: 1000, step: 10,
label: ["Minimum price", "Maximum price"],
value_text: ->(value) { "$#{value}" }, class: "w-80") %>
Range with gap
<%= poetry_slider(name: "hours", values: [9, 17], min: 0, max: 24,
min_steps_between_thumbs: 4,
label: ["Start", "End"], class: "w-80") %>
Vertical
<%= poetry_slider(name: "volume", value: 65, orientation: :vertical, label: "Volume",
value_text: ->(value) { "#{value}%" }, class: "h-48") %>
API
Poetry::Ui::Slider::Component — options are
constructor keywords (the poetry_* helper forwards them);
slots are composed inside the block. Generated from the gem's source documentation.
| Option | Type | Details | Description |
|---|---|---|---|
| described_by: | String | Field hint/error wiring -> aria-describedby on EACH thumb. | |
| disabled: | Boolean | defaults to false |
Renders the control inert; the hidden inputs still submit the server value. |
| inverted: | Boolean | defaults to false |
Flips the value direction along the axis; composes with RTL (both = ltr math). |
| label: | Object | 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 | defaults to 100.0 |
The track's upper bound; must exceed min:. |
| min: | Float | defaults to 0.0 |
The track's lower bound. |
| min_steps_between_thumbs: | Integer | defaults to 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; defaults to :horizontal |
The track axis. |
| step: | Float | defaults to 1.0 |
Snap increment; decimal steps supported (precision-aware rounding lives in the controller's math core). |
| value: | Object | Single-thumb value. ArgumentError if given with values:. | |
| value_text: | Object | aria-valuetext formatter: a proc (v -> \"$200\") or an i18n key with %{value}; optional - falls back to the bare number. | |
| values: | Object | Range mode: [low, high] -> two thumbs, sorted. ArgumentError if given with value:, unsorted, or length != 2. |
Styling
Every part carries a stable data-slot attribute — target
[data-slot=…] from your own CSS to restyle it. State rides
data attributes on the parts below. This contract is verified against rendered DOM in CI.
| Part | Description |
|---|---|
| [data-slot=slider] | Root - the controller, the geometry vars, and pointer capture ride here |
| [data-slot=slider-track] | The full-length rail the range paints over |
| [data-slot=slider-range] | The filled span between --slider-start and --slider-end |
| [data-slot=slider-anchor] | Absolutely positioned thumb wrapper (one per thumb, with its hidden input alongside) seated on the geometry vars |
| [data-slot=slider-thumb] | The role=slider handle - its own Tab stop, carrying the aria-value* surface (bounds neighbor-clamped in range mode) |
State attributes
| Part | Attribute | Condition | Values |
|---|---|---|---|
| slider | data-orientation | always - the axis | horizontal · vertical |
| slider | data-disabled | disabled: is set (the control is inert; the hidden inputs still submit) | — |
| slider | data-dragging | a pointer drag is in flight (the controller sets it for the gesture; never rendered server-side) | — |
| slider-track | data-orientation | always - mirrors the root | horizontal · vertical |
| slider-range | data-orientation | always - mirrors the root | horizontal · vertical |
| slider-anchor | data-orientation | always - mirrors the root | horizontal · vertical |
| slider-thumb | data-orientation | always - mirrors the root | horizontal · vertical |
| slider-thumb | data-disabled | disabled: is set (tabindex drops to -1) | — |
| slider-thumb | data-dragging | this thumb is the one being dragged (the controller pairs it with the root's) | — |
CSS variables
| Part | Variable | Description |
|---|---|---|
| slider | --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 | --slider-end | the filled range's end edge as a percentage (the single-thumb value rides here) |
Wiring
The Stimulus surface each element carries — declared in the component, verified against rendered DOM in CI. Bare actions fire on the element's default event.
| Element | Controller | Wiring |
|---|---|---|
| root | poetry--core--slider | registers · value min · value max · value step · value value · value min_steps_between_thumbs · value orientation · value inverted · pointerdown on pointerdown |
| track | poetry--core--slider | target track |
| range | poetry--core--slider | target range |
| thumb | poetry--core--slider | keydown on keydown · target thumb |
| input | poetry--core--slider | target input |