PhoenixPaper.Slider (PhoenixPaper v0.1.0)

Copy Markdown View Source

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

pp_slider(assigns)

Attributes

  • id (:any) - Defaults to nil.
  • name (:any) - Defaults to nil.
  • value (:any) - a number, or a {low, high} tuple for a range slider. Defaults to nil.
  • min (:any) - Defaults to 0.
  • max (:any) - Defaults to 100.
  • step (:any) - Defaults to 1.
  • 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 to false.
  • label (:string) - Defaults to nil.
  • field (Phoenix.HTML.FormField) - Defaults to nil.
  • disabled (:boolean) - Defaults to false.
  • paperize (:boolean) - Defaults to true.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted. Supports all globals plus: ["form", "autofocus", "phx-change"].