Corex. Slider
(Corex v0.2.2)
View Source
Linear slider for Phoenix LiveView forms. Behavior follows Zag.js Slider
(the same machine powers range slider).
Use slider/1 with one value for a single thumb, or a list for multiple thumbs.
Anatomy
Basic
<.slider class="slider">
<:label>Volume</:label>
</.slider>Range
<.slider class="slider" value={[20, 80]}>
<:label>Price</:label>
</.slider>With marks
<.slider class="slider" markers marker_values={[0, 25, 50, 75, 100]}>
<:label>Volume</:label>
</.slider>API
Requires a stable id on <.slider>.
| Function | Action | Returns |
|---|---|---|
set_value/2 | Set value (client) | %Phoenix.LiveView.JS{} |
set_value/3 | Set value (server) | socket |
set_thumb_value/3 | Set one thumb (client) | %Phoenix.LiveView.JS{} |
set_thumb_value/4 | Set one thumb (server) | socket |
increment/1 | Increment first thumb (client) | %Phoenix.LiveView.JS{} |
increment/2 | Increment (client with index, or server) | %Phoenix.LiveView.JS{} or socket |
increment/3 | Increment thumb (server) | socket |
decrement/1 | Decrement first thumb (client) | %Phoenix.LiveView.JS{} |
decrement/2 | Decrement (client with index, or server) | %Phoenix.LiveView.JS{} or socket |
decrement/3 | Decrement thumb (server) | socket |
value/1 | Read value (client) | %Phoenix.LiveView.JS{} |
value/2 | Read value (client, opts) | %Phoenix.LiveView.JS{} |
value/3 | Read value (server) | socket |
For value, use respond_to: :server | :client | :both. LiveView receives slider_value_response; the DOM receives slider-value.
Events
Pick an event name and pass it to on_* on <.slider>.
Server events
| Event | When | Payload |
|---|---|---|
on_value_change="slider_changed" | Value changes while dragging | %{"id" => id, "value" => list} |
on_value_change_end="slider_changed_end" | User releases a thumb | %{"id" => id, "value" => list} |
on_value_change
<.slider
class="slider"
on_value_change="slider_changed"
markers marker_values={[0, 25, 50, 75, 100]}
>
<:label>Volume</:label>
</.slider>def handle_event("slider_changed", %{"value" => value}, socket) do
{:noreply, assign(socket, :value, value)}
endClient events
| Event | When | event.detail |
|---|---|---|
on_value_change_client="slider-changed" | Value changes while dragging | id, value |
on_value_change_end_client="slider-changed-end" | User releases a thumb | id, value |
Style
Use data attributes to target elements:
[data-scope="slider"][data-part="root"] {}
[data-scope="slider"][data-part="control"] {}
[data-scope="slider"][data-part="track"] {}
[data-scope="slider"][data-part="range"] {}
[data-scope="slider"][data-part="thumb"] {}
[data-scope="slider"][data-part="value-text"] {}
[data-scope="slider"][data-part="marker-group"] {}
[data-scope="slider"][data-part="marker"] {}If you wish to use the default Corex styling, you can use the class slider on the component.
This requires the corex_design dependency and mix corex.design.build; import the component css file.
@import "../corex/corex.css";Stack modifiers on the host (class on <.slider>). Combine axes, for example slider ui-accent ui-size-lg or slider ui-info.
Axes: Semantic (ui-accent, ui-brand, ui-alert, ui-info, ui-success), Size (ui-size-sm … ui-size-xl), Radius (ui-rounded-*). No variant axis. See the modifier guide.
Semantic modifiers set palette variables on the track fill and thumb handle. Selection paint always fills; there is no variant axis.
Semantic
Palette variables for range fill and thumb ink.
| Modifier | Classes |
|---|---|
| Default | slider |
| Accent | slider ui-accent |
| Brand | slider ui-brand |
| Alert | slider ui-alert |
| Info | slider ui-info |
| Success | slider ui-success |
Size
| Modifier | Classes |
|---|---|
| SM | slider ui-size-sm |
| MD | slider ui-size-md |
| LG | slider ui-size-lg |
| XL | slider ui-size-xl |
Patterns
Async and skeleton
Use assign_async/3 with <.async_result> and show slider_skeleton/1 while loading.
<.async_result :let={slider} assign={@slider}>
<:loading>
<.slider_skeleton class="slider" />
</:loading>
<:failed>Could not load.</:failed>
<.slider id="async-slider" class="slider" value={slider.value} />
</.async_result>Form
When using with Phoenix forms, set the form id in to_form/2 (for example to_form(changeset, as: :name, id: "my-form")) and use <.form for={@form}>.
A single thumb submits one number. Two or more thumbs submit name[] list params.
For cross-cutting invalid styling and error presentation, see the Forms guide. With field={@form[:…]}, pass auto_invalid for alert borders from visible errors, or invalid={true} to force the alert state.
def slider_form_page(conn, _params) do
form =
%MyApp.Form.SliderForm{}
|> MyApp.Form.SliderForm.changeset(%{})
|> Phoenix.Component.to_form(as: :slider_form, id: "slider-form")
render(conn, :slider_form_page, form: form)
end<.form :let={f} for={@form} action={@action} method="post">
<.slider field={f[:volume]} class="slider" markers marker_values={[0, 25, 50, 75, 100]}>
<:label>Volume</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.slider>
<button type="submit">Submit</button>
</.form>
Summary
Components
Renders a loading skeleton for the slider. No hook; static data-part markup for styling.
API
Decrement the first thumb from a control (phx-click).
Decrement from handle_event. Optional thumb index (default 0).
Increment the first thumb from a control (phx-click).
Increment from handle_event. Optional thumb index (default 0).
Set one thumb from a control (phx-click).
Set one thumb from handle_event.
Set the slider value from a control (phx-click). value is a number or a list of numbers.
Set the slider value from handle_event. Accepts a number, a list, or a numeric string.
Read the current value from phx-click. Optional respond_to: :server (default), :client, or :both.
Read the value from handle_event. Same respond_to behavior as value/2.
Components
Attributes
id(:string) - The id of the slider. Defaults tonil.field(Phoenix.HTML.FormField) - A form field struct retrieved from the form, for example: @form[:volume]. Automatically sets id, name, value, and errors from the form field. Defaults tonil.name(:string) - Name for form submission. Multi-thumb sliders append []. Defaults tonil.form(:string) - Form id to associate the control with. Defaults tonil.invalid(:boolean) - Whether the control has validation errors. Defaults tonil.auto_invalid(:boolean) - When true withfield, set invalid from visible changeset errors (default false). Defaults tofalse.disabled(:boolean) - Whether the control is disabled. Defaults tofalse.read_only(:boolean) - Whether the slider is read-only. Defaults tofalse.required(:boolean) - Whether the control is required. Defaults tofalse.value(:any) - Initial value. A number is one thumb; a list of numbers is a range (or N thumbs). Defaults to0.min(:float) - Minimum value. Defaults to0.0.max(:float) - Maximum value. Defaults to100.0.step(:float) - Step value. Defaults to1.0.large_step(:float) - Step when Shift or PageUp/PageDown is used. Defaults tonil.dir(:string) - Direction. Defaults tonil. Must be one ofnil,"ltr", or"rtl".orientation(:string) - Defaults to"horizontal". Must be one of"horizontal", or"vertical".origin(:string) - Where the range fill starts for a single thumb. Defaults to"start". Must be one of"start","center", or"end".thumb_alignment(:string) - Thumb alignment relative to the track. Defaults tonil. Must be one ofnil,"contain", or"center".min_steps_between_thumbs(:integer) - Minimum steps between thumbs for a range slider. Defaults tonil.thumb_collision_behavior(:string) - How thumbs behave when they collide. Defaults tonil. Must be one ofnil,"none","push", or"swap".compound(:boolean) - Enable compound mode. Use with :let={ctx} and sub-components to fully control structure. Defaults tofalse.on_value_change(:string) - Server event when value changes during drag. Defaults tonil.on_value_change_client(:string) - Client event when value changes during drag. Defaults tonil.on_value_change_end(:string) - Server event when the user releases a thumb. Defaults tonil.on_value_change_end_client(:string) - Client event when the user releases a thumb. Defaults tonil.markers(:boolean) - Show tick marks on the track. Use marker_values to customize positions. Defaults tofalse.marker_values(:list) - Tick positions when markers is true (defaults to quarter steps between min and max). Defaults tonil.errors(:list) - List of error messages to display. Defaults to[].- Global attributes are accepted.
Slots
inner_blocklabel- Accepts attributes:class(:string)
value_text- Accepts attributes:class(:string)
error- Accepts attributes:class(:string)
Renders a loading skeleton for the slider. No hook; static data-part markup for styling.
Attributes
- Global attributes are accepted.
Compounds
Attributes
ctx(:map) (required)- Global attributes are accepted.
Slots
inner_block
Attributes
ctx(:map) (required)- Global attributes are accepted.
Slots
inner_block(required)
Attributes
ctx(:map) (required)value(:float) (required)disabled(:boolean) - Defaults tofalse.- Global attributes are accepted.
Attributes
ctx(:map) (required)- Global attributes are accepted.
Slots
inner_block
Attributes
ctx(:map) (required)- Global attributes are accepted.
Attributes
ctx(:map) (required) - The context map yielded by the parent slider via :let={ctx}.- Global attributes are accepted.
Slots
inner_block(required)
Attributes
ctx(:map) (required)index(:integer) (required)- Global attributes are accepted.
Slots
inner_block
Attributes
ctx(:map) (required)- Global attributes are accepted.
Slots
inner_block
Attributes
ctx(:map) (required)- Global attributes are accepted.
Slots
inner_block(required)
Attributes
ctx(:map) (required)- Global attributes are accepted.
Slots
value_text- Accepts attributes:class(:string)
API
@spec decrement(String.t()) :: Phoenix.LiveView.JS.t()
Decrement the first thumb from a control (phx-click).
<.action phx-click={Corex.Slider.decrement("my-slider")}>-</.action>
@spec decrement(String.t(), integer()) :: Phoenix.LiveView.JS.t()
@spec decrement(Phoenix.LiveView.Socket.t(), String.t()) :: Phoenix.LiveView.Socket.t()
Decrement from handle_event. Optional thumb index (default 0).
def handle_event("dec", _, socket) do
{:noreply, Corex.Slider.decrement(socket, "my-slider")}
end
@spec increment(String.t()) :: Phoenix.LiveView.JS.t()
Increment the first thumb from a control (phx-click).
<.action phx-click={Corex.Slider.increment("my-slider")}>+</.action>
@spec increment(String.t(), integer()) :: Phoenix.LiveView.JS.t()
@spec increment(Phoenix.LiveView.Socket.t(), String.t()) :: Phoenix.LiveView.Socket.t()
Increment from handle_event. Optional thumb index (default 0).
def handle_event("inc", _, socket) do
{:noreply, Corex.Slider.increment(socket, "my-slider")}
end
@spec set_thumb_value(String.t(), integer(), number()) :: Phoenix.LiveView.JS.t()
Set one thumb from a control (phx-click).
<.action phx-click={Corex.Slider.set_thumb_value("my-slider", 0, 25)}>Min 25</.action>
@spec set_thumb_value(Phoenix.LiveView.Socket.t(), String.t(), integer(), term()) :: Phoenix.LiveView.Socket.t()
Set one thumb from handle_event.
def handle_event("set_min", _, socket) do
{:noreply, Corex.Slider.set_thumb_value(socket, "my-slider", 0, 25)}
end
@spec set_value(String.t(), number() | [number()] | String.t()) :: Phoenix.LiveView.JS.t()
Set the slider value from a control (phx-click). value is a number or a list of numbers.
<.action phx-click={Corex.Slider.set_value("my-slider", 50)}>50</.action>
<.slider id="my-slider" class="slider" value={0} name="volume" />document.getElementById("my-slider")?.dispatchEvent(
new CustomEvent("corex:slider:set-value", {
bubbles: false,
detail: { value: [50] },
})
);
@spec set_value(Phoenix.LiveView.Socket.t(), String.t(), term()) :: Phoenix.LiveView.Socket.t()
Set the slider value from handle_event. Accepts a number, a list, or a numeric string.
def handle_event("set_volume", %{"value" => value}, socket) do
{:noreply, Corex.Slider.set_value(socket, "my-slider", value)}
end
@spec value( String.t(), keyword() ) :: Phoenix.LiveView.JS.t()
Read the current value from phx-click. Optional respond_to: :server (default), :client, or :both.
<.action phx-click={Corex.Slider.value("my-slider", respond_to: :both)}>Read</.action>
<.slider id="my-slider" class="slider" value={45} name="volume" />document.getElementById("my-slider")?.dispatchEvent(
new CustomEvent("corex:slider:value", {
bubbles: false,
detail: { respond_to: "both" },
})
);
@spec value(Phoenix.LiveView.Socket.t(), String.t(), keyword()) :: Phoenix.LiveView.Socket.t()
Read the value from handle_event. Same respond_to behavior as value/2.
def handle_event("read_volume", _, socket) do
{:noreply, Corex.Slider.value(socket, "my-slider", respond_to: :server)}
end
Functions
@spec decrement(Phoenix.LiveView.Socket.t(), String.t(), integer()) :: Phoenix.LiveView.Socket.t()
@spec increment(Phoenix.LiveView.Socket.t(), String.t(), integer()) :: Phoenix.LiveView.Socket.t()