A Material Design slider (pp_slider/1) — a native <input type="range">, in the spirit of MUI's Slider.
<.pp_slider name="volume" value={60} label="Volume" />Colored/sized via a small set of literal, mutually-exclusive CSS
utilities in priv/static/phoenix_paper.css (pp-slider/
pp-slider-small/pp-slider-vertical/pp-slider-vertical-small, plus
pp-slider-primary/etc. and pp-slider-track-none/
pp-slider-track-inverted) rather than accent-color alone — see that
file's own comment for why accent-color can't give the unfilled part
of the track a controlled color once you also want control over its
thickness/rounding. The filled segment is a linear-gradient positioned
by a --pp-slider-percent CSS custom property, set inline for the first
paint and kept in sync on drag by a tiny vanilla oninput snippet — the
same "small inline script, no hook, no bundler" approach
PhoenixPaper.Ripple/PhoenixPaper.NumberField's steppers already use.
Sizes
size="small" shrinks the track/thumb, matching MUI's own size prop.
Track
track="none" hides the filled segment entirely (still shows the
neutral track + a colored thumb) — MUI's track={false}. track="inverted"
fills from the thumb to max instead of from min to the thumb — MUI's
track="inverted". Both are ignored for range sliders (see below), which
always show the colored segment between the two thumbs.
Marks
marks={true} ticks every step; marks={[10, 50, 90]} ticks specific
values; marks={[{0, "0°C"}, {100, "100°C"}]} ticks specific values
with labels drawn below the track. Ticks render via the native
<datalist>/list= pairing (real HTML, not a custom widget) — Chrome
and Firefox both draw tick marks and snap the thumb near them for free.
Label positioning assumes orientation="horizontal"; it isn't
implemented for vertical sliders.
Range sliders
Pass a {low, high} tuple as value for a two-thumb range slider —
MUI's array value. Submits as "#{name}_min"/"#{name}_max" (two
separate native inputs; there's no native two-handle range input, and
splitting the name avoids the query-string array-parsing ambiguity a
shared name would need to resolve). Built the well-known way two
overlapping native range inputs fake a range slider: each input's own
track is made fully transparent (pointer-events: none on the input,
re-enabled only on its own thumb via [&::-webkit-slider-thumb]:pointer-events-auto/
[&::-moz-range-thumb]:pointer-events-auto, so clicking near either thumb
reaches it and nothing else), and the colored segment between the two
thumbs is a separate absolutely-positioned <div> kept in sync by the
same kind of inline oninput snippet. Known, inherent limitation of this
technique (shared by essentially every native-input-based range slider):
a low thumb dragged past the high thumb's value (or vice versa) is
clamped by the inline script on input, not prevented at the OS/browser
drag-gesture level, so there's a narrow window where the two can briefly
overlap before the clamp corrects it. marks/orientation="vertical"
aren't supported in range mode.
Orientation
orientation="vertical" uses writing-mode: vertical-lr (Chromium/WebKit)
plus the still-supported non-standard -moz-orient: vertical
(Firefox) — the current cross-browser way to get a vertical native range
input; there's no vendor-neutral standard property for this yet.
Not implemented
MUI's valueLabelDisplay (a tooltip that tracks the thumb's exact pixel
position while dragging) and non-linear scale functions both need real
per-frame JS computing pixel offsets or transforming displayed numbers —
more than a "small inline snippet" can reasonably do without becoming a
bespoke JS hook, which this library avoids. The always-visible
label/current-value header serves the same purpose as
valueLabelDisplay="on" without needing to track the thumb's position at
all.
Summary
Functions
Attributes
id(:any) - Defaults tonil.name(:any) - Defaults tonil.value(:any) - a number, or a {low, high} tuple for a range slider. Defaults tonil.min(:any) - Defaults to0.max(:any) - Defaults to100.step(:any) - Defaults to1.color(:string) - Defaults to"primary". Must be one of"primary","secondary","tertiary", or"error".size(:string) - Defaults to"medium". Must be one of"medium", or"small".orientation(:string) - Defaults to"horizontal". Must be one of"horizontal", or"vertical".track(:string) - none hides the filled segment; inverted fills from the thumb to max — ignored for range sliders. Defaults to"normal". Must be one of"normal","none", or"inverted".marks(:any) - true (tick every step), a list of values, or a list of {value, label} tuples. Defaults tofalse.label(:string) - Defaults tonil.field(Phoenix.HTML.FormField) - Defaults tonil.disabled(:boolean) - Defaults tofalse.paperize(:boolean) - Defaults totrue.class(:any) - Defaults tonil.- Global attributes are accepted. Supports all globals plus:
["form", "autofocus", "phx-change"].