Slider
Single or dual thumb, marks, vertical, and a value that shows inline or in a tooltip. The form posts plain numbers.
Single thumb
A native range input with the track, fill and thumb painted by the library, so it looks the same on every browser and OS. label names it for screen readers and prints above the track; show_value="inline" puts the live readout in that same row, with value_prefix and value_suffix formatting it.
<div class="w-full max-w-sm space-y-8">
<.slider name="volume" label="Volume" value={60} value_suffix="%" show_value="inline" />
<.slider name="quality" label="Quality" value={3} min={1} max={5} />
</div>
Dual thumb
min_field and max_field make it a range: two thumbs, two form values, one fill spanning between them. Each thumb posts its own name, so a price filter is a plain form change event with no JavaScript of your own. Reversed or out-of-bounds values are clamped and ordered server-side, so the fill can never paint backwards.
<div class="w-full max-w-sm">
<.slider
min_field={to_form(%{"min" => "250"}, as: :price)[:min]}
max_field={to_form(%{"max" => "750"}, as: :price)[:max]}
min={0}
max={1000}
step={50}
label="Price"
value_prefix="$"
show_value="inline"
/>
</div>
Marks and tooltip
marks are labelled stops under the track. An empty label renders a tick only, so you can mark every step and label the ones that carry meaning; ticks the fill has swallowed flip to the on-primary treatment. show_value="tooltip" floats the value in a bubble over the thumb while you drag or tab to it, rather than taking up a row.
<div class="w-full max-w-sm">
<.slider
name="year"
label="Model year"
value={2010}
min={1990}
max={2030}
step={5}
show_value="tooltip"
marks={[
%{value: 1990, label: "1990"},
%{value: 2000, label: ""},
%{value: 2010, label: "2010"},
%{value: 2020, label: ""},
%{value: 2030, label: "2030"}
]}
/>
</div>
Sizes and states
size runs sm, md, lg - track thickness and thumb diameter move together, so the proportions hold. disabled dims the whole control and takes the native inputs out of the tab order.
<div class="w-full max-w-sm space-y-6">
<.slider name="s" label="Small" value={30} size="sm" />
<.slider name="m" label="Medium" value={50} size="md" />
<.slider name="l" label="Large" value={70} size="lg" />
<.slider name="d" label="Disabled" value={40} disabled />
</div>
Vertical
orientation="vertical" stands the track up and fills from the bottom. It is the same native input turned with writing-mode, so the keyboard map and the screen reader announcement are unchanged - useful for a mixer strip or a level control that sits beside content rather than under it.
<div class="flex items-end gap-10">
<.slider name="bass" label="Bass" value={70} orientation="vertical" show_value="tooltip" />
<.slider name="mid" label="Mid" value={45} orientation="vertical" show_value="tooltip" />
<.slider
name="treble"
label="Treble"
value={55}
orientation="vertical"
show_value="tooltip"
/>
</div>
Properties
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
CSS class for the outer wrapper |
disabled
|
boolean |
false
|
disables every input and dims the control |
field
|
any |
nil
|
a Phoenix.HTML.FormField for single-thumb use; sets name, id and value |
id
|
string |
nil
|
wrapper id; the inputs derive theirs from it |
label
|
string |
nil
|
visible label above the track, and the base for each input's accessible name (dual thumbs become "<label> minimum" and "<label> maximum"); defaults to the humanised field name |
marks
|
list |
[]
|
labelled stops rendered under the track, e.g. [%{value: 0, label: "Min"}, %{value: 50, label: ""}]; an empty label renders a tick only |
max
|
any |
100
|
upper bound |
max_field
|
any |
nil
|
FormField for the upper value; dual-thumb mode when set with min_field |
max_name
|
string |
nil
|
upper input name in dual mode when not using max_field; defaults to "#{name}_max" |
min
|
any |
0
|
lower bound |
min_field
|
any |
nil
|
FormField for the lower value; dual-thumb mode when set with max_field |
min_name
|
string |
nil
|
lower input name in dual mode when not using min_field; defaults to "#{name}_min" |
name
|
string |
nil
|
input name when not using field |
orientation
|
string |
"horizontal"
|
vertical stands the track up, filling from the bottom
one of: "horizontal", "vertical"
|
rest
|
global |
any other HTML attributes, applied to the wrapper | |
show_value
|
string |
"none"
|
tooltip shows the value in a bubble above the thumb while dragging or focus-visible; inline renders it in the label row beside the track
one of: "tooltip", "inline", "none"
|
size
|
string |
"md"
|
track thickness and thumb diameter
one of: "sm", "md", "lg"
|
step
|
any |
1
|
step increment; values snap to it natively |
value
|
any |
nil
|
current value (single-thumb) |
value_prefix
|
string |
""
|
prepended to displayed values, e.g. "$" |
value_suffix
|
string |
""
|
appended to displayed values, e.g. "%" |
values
|
list |
nil
|
[min, max] current values (dual-thumb, when not using min_field/max_field) |