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>.

FunctionActionReturns
set_value/2Set value (client)%Phoenix.LiveView.JS{}
set_value/3Set value (server)socket
set_thumb_value/3Set one thumb (client)%Phoenix.LiveView.JS{}
set_thumb_value/4Set one thumb (server)socket
increment/1Increment first thumb (client)%Phoenix.LiveView.JS{}
increment/2Increment (client with index, or server)%Phoenix.LiveView.JS{} or socket
increment/3Increment thumb (server)socket
decrement/1Decrement first thumb (client)%Phoenix.LiveView.JS{}
decrement/2Decrement (client with index, or server)%Phoenix.LiveView.JS{} or socket
decrement/3Decrement thumb (server)socket
value/1Read value (client)%Phoenix.LiveView.JS{}
value/2Read value (client, opts)%Phoenix.LiveView.JS{}
value/3Read 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

EventWhenPayload
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)}
end

Client events

EventWhenevent.detail
on_value_change_client="slider-changed"Value changes while draggingid, value
on_value_change_end_client="slider-changed-end"User releases a thumbid, 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-smui-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.

ModifierClasses
Defaultslider
Accentslider ui-accent
Brandslider ui-brand
Alertslider ui-alert
Infoslider ui-info
Successslider ui-success

Size

ModifierClasses
SMslider ui-size-sm
MDslider ui-size-md
LGslider ui-size-lg
XLslider 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

slider(assigns)

Attributes

  • id (:string) - The id of the slider. Defaults to nil.
  • 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 to nil.
  • name (:string) - Name for form submission. Multi-thumb sliders append []. Defaults to nil.
  • form (:string) - Form id to associate the control with. Defaults to nil.
  • invalid (:boolean) - Whether the control has validation errors. Defaults to nil.
  • auto_invalid (:boolean) - When true with field, set invalid from visible changeset errors (default false). Defaults to false.
  • disabled (:boolean) - Whether the control is disabled. Defaults to false.
  • read_only (:boolean) - Whether the slider is read-only. Defaults to false.
  • required (:boolean) - Whether the control is required. Defaults to false.
  • value (:any) - Initial value. A number is one thumb; a list of numbers is a range (or N thumbs). Defaults to 0.
  • min (:float) - Minimum value. Defaults to 0.0.
  • max (:float) - Maximum value. Defaults to 100.0.
  • step (:float) - Step value. Defaults to 1.0.
  • large_step (:float) - Step when Shift or PageUp/PageDown is used. Defaults to nil.
  • dir (:string) - Direction. Defaults to nil. Must be one of nil, "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 to nil. Must be one of nil, "contain", or "center".
  • min_steps_between_thumbs (:integer) - Minimum steps between thumbs for a range slider. Defaults to nil.
  • thumb_collision_behavior (:string) - How thumbs behave when they collide. Defaults to nil. Must be one of nil, "none", "push", or "swap".
  • compound (:boolean) - Enable compound mode. Use with :let={ctx} and sub-components to fully control structure. Defaults to false.
  • on_value_change (:string) - Server event when value changes during drag. Defaults to nil.
  • on_value_change_client (:string) - Client event when value changes during drag. Defaults to nil.
  • on_value_change_end (:string) - Server event when the user releases a thumb. Defaults to nil.
  • on_value_change_end_client (:string) - Client event when the user releases a thumb. Defaults to nil.
  • markers (:boolean) - Show tick marks on the track. Use marker_values to customize positions. Defaults to false.
  • marker_values (:list) - Tick positions when markers is true (defaults to quarter steps between min and max). Defaults to nil.
  • errors (:list) - List of error messages to display. Defaults to [].
  • Global attributes are accepted.

Slots

  • inner_block
  • label - Accepts attributes:
    • class (:string)
  • value_text - Accepts attributes:
    • class (:string)
  • error - Accepts attributes:
    • class (:string)

slider_skeleton(assigns)

Renders a loading skeleton for the slider. No hook; static data-part markup for styling.

Attributes

  • Global attributes are accepted.

Compounds

slider_control(assigns)

Attributes

  • ctx (:map) (required)
  • Global attributes are accepted.

Slots

  • inner_block

slider_hidden_input(assigns)

Attributes

  • ctx (:map) (required)
  • index (:integer) - Defaults to 0.
  • Global attributes are accepted.

slider_label(assigns)

Attributes

  • ctx (:map) (required)
  • Global attributes are accepted.

Slots

  • inner_block (required)

slider_marker(assigns)

Attributes

  • ctx (:map) (required)
  • value (:float) (required)
  • disabled (:boolean) - Defaults to false.
  • Global attributes are accepted.

slider_marker_group(assigns)

Attributes

  • ctx (:map) (required)
  • Global attributes are accepted.

Slots

  • inner_block

slider_range(assigns)

Attributes

  • ctx (:map) (required)
  • Global attributes are accepted.

slider_root(assigns)

Attributes

  • ctx (:map) (required) - The context map yielded by the parent slider via :let={ctx}.
  • Global attributes are accepted.

Slots

  • inner_block (required)

slider_thumb(assigns)

Attributes

  • ctx (:map) (required)
  • index (:integer) (required)
  • Global attributes are accepted.

Slots

  • inner_block

slider_track(assigns)

Attributes

  • ctx (:map) (required)
  • Global attributes are accepted.

Slots

  • inner_block

slider_value(assigns)

Attributes

  • ctx (:map) (required)
  • Global attributes are accepted.

Slots

  • inner_block (required)

slider_value_text(assigns)

Attributes

  • ctx (:map) (required)
  • Global attributes are accepted.

Slots

  • value_text - Accepts attributes:
    • class (:string)

API

decrement(slider_id)

@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>

decrement(slider_id, index)

Decrement from handle_event. Optional thumb index (default 0).

def handle_event("dec", _, socket) do
  {:noreply, Corex.Slider.decrement(socket, "my-slider")}
end

increment(slider_id)

@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>

increment(slider_id, index)

Increment from handle_event. Optional thumb index (default 0).

def handle_event("inc", _, socket) do
  {:noreply, Corex.Slider.increment(socket, "my-slider")}
end

set_thumb_value(slider_id, index, value)

@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>

set_thumb_value(socket, slider_id, index, value)

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

set_value(slider_id, value)

@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] },
  })
);

set_value(socket, slider_id, value)

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

value(slider_id, opts)

@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" },
  })
);

value(socket, slider_id, opts \\ [])

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

decrement(socket, slider_id, index)

increment(socket, slider_id, index)