Corex.SignaturePad (Corex v0.1.0-alpha.31)

View Source

Phoenix implementation of Zag.js Signature Pad.

Examples

Basic Usage

<.signature_pad id="my-signature-pad" class="signature-pad">
  <:label>Sign here</:label>
  <:clear_trigger>
    <.heroicon name="hero-x-mark" />
  </:clear_trigger>
</.signature_pad>

With Callback

<.signature_pad
  id="my-signature-pad"
  on_draw_end="signature_drawn"
  class="signature-pad">
  <:label>Sign here</:label>
  <:clear_trigger>
    <.heroicon name="hero-x-mark" />
  </:clear_trigger>
</.signature_pad>
def handle_event("signature_drawn", %{"paths" => paths}, socket) do
  {:noreply, put_flash(socket, :info, "Signature drawn with #{length(paths)} paths")}
end

Custom Drawing Options

<.signature_pad
  id="my-signature-pad"
  drawing_fill="blue"
  drawing_size={3}
  drawing_simulate_pressure
  class="signature-pad">
  <:label>Sign here</:label>
  <:clear_trigger>
    <.heroicon name="hero-x-mark" />
  </:clear_trigger>
</.signature_pad>

Phoenix Form Integration

When using with Phoenix forms, you must add an id to the form using the Corex.Form.get_form_id/1 function.

Controller

Build the form from an Ecto changeset:

def form_page(conn, _params) do
  form =
    %MyApp.Form.SignatureForm{}
    |> MyApp.Form.SignatureForm.changeset(%{})
    |> Phoenix.Component.to_form(as: :signature_form, id: "signature-form")
  render(conn, :form_page, form: form)
end
<.form :let={f} for={@form} id={Corex.Form.get_form_id(@form)} action={@action} method="post">
  <.signature_pad field={f[:signature]} class="signature-pad">
    <:label>Sign here</:label>
    <:clear_trigger>
      <.heroicon name="hero-x-mark" />
    </:clear_trigger>
    <:error :let={msg}>
      <.heroicon name="hero-exclamation-circle" class="icon" />
      {msg}
    </:error>
  </.signature_pad>
  <button type="submit">Submit</button>
</.form>

Live View

When using in a Live view you must add controlled mode. Prefer building the form from an Ecto changeset (see "With Ecto changeset" below).

With Ecto changeset

First create your schema and changeset:

defmodule MyApp.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset

  schema "users" do
    field :name, :string
    field :signature, :text
    timestamps(type: :utc_datetime)
  end

  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :signature])
    |> validate_required([:name, :signature])
  end
end
defmodule MyAppWeb.UserLive do
  use MyAppWeb, :live_view
  alias MyApp.Accounts.User

  def mount(_params, _session, socket) do
    {:ok, assign(socket, :form, to_form(User.changeset(%User{}, %{})))}
  end

  def handle_event("validate", %{"user" => user_params}, socket) do
    changeset = User.changeset(%User{}, user_params)
    {:noreply, assign(socket, form: to_form(changeset, action: :validate))}
  end

  def render(assigns) do
    ~H"""
    <.form for={@form} id={get_form_id(@form)} phx-change="validate">
      <.signature_pad
        field={@form[:signature]}
        id="my-signature-pad"
        class="signature-pad"
      >
        <:label>Sign here</:label>
        <:clear_trigger>
          <.heroicon name="hero-x-mark" />
        </:clear_trigger>
        <:error :let={msg}>
          <.heroicon name="hero-exclamation-circle" class="icon" />
          {msg}
        </:error>
      </.signature_pad>
    </.form>
    """
  end
end

API Control

In order to use the API, you must use an id on the component

Client-side

<button phx-click={Corex.SignaturePad.clear("my-signature-pad")}>
  Clear Signature
</button>

Server-side

def handle_event("clear_signature", _, socket) do
  {:noreply, Corex.SignaturePad.clear(socket, "my-signature-pad")}
end

Styling

Use data attributes to target elements:

[data-scope="signature-pad"][data-part="root"] {}
[data-scope="signature-pad"][data-part="label"] {}
[data-scope="signature-pad"][data-part="control"] {}
[data-scope="signature-pad"][data-part="segment"] {}
[data-scope="signature-pad"][data-part="guide"] {}
[data-scope="signature-pad"][data-part="clear-trigger"] {}
[data-scope="signature-pad"][data-part="hidden-input"] {}

If you wish to use the default Corex styling, you can use the class signature-pad on the component. This requires to install Mix.Tasks.Corex.Design first and import the component css file.

@import "../corex/main.css";
@import "../corex/tokens/themes/neo/light.css";
@import "../corex/components/signature-pad.css";

You can then use modifiers

<.signature_pad class="signature-pad signature-pad--accent signature-pad--lg">

Learn more about modifiers and Corex Design

Summary

Components

Renders a signature pad component.

API

Clears the signature pad from client-side. Returns a Phoenix.LiveView.JS command.

Clears the signature pad from server-side. Pushes a LiveView event.

Components

signature_pad(assigns)

Renders a signature pad component.

Attributes

  • id (:string) - The id of the signature pad, useful for API to identify the signature pad.
  • drawing_fill (:string) - The fill color for drawing strokes. Defaults to "black".
  • drawing_size (:integer) - The size/thickness of drawing strokes. Defaults to 2.
  • drawing_simulate_pressure (:boolean) - Whether to simulate pressure for drawing strokes. Defaults to false.
  • drawing_smoothing (:float) - Smoothing factor for drawing strokes (0–1, perfect-freehand option). Defaults to 0.9.
  • drawing_easing (:string) - Easing function for drawing strokes (perfect-freehand option). Defaults to nil.
  • drawing_thinning (:float) - Thinning factor for drawing strokes (perfect-freehand option). Defaults to nil.
  • drawing_streamline (:float) - Streamline factor for drawing strokes (perfect-freehand option). Defaults to 0.1.
  • dir (:string) - The direction of the signature pad. When nil, derived from document (html lang + config :rtl_locales). Defaults to nil. Must be one of nil, "ltr", or "rtl".
  • on_draw_end (:string) - The server event name when drawing ends. Defaults to nil.
  • on_draw_end_client (:string) - The client event name when drawing ends. Defaults to nil.
  • controlled (:boolean) - Whether the signature pad is controlled. Defaults to false.
  • paths (:any) - The initial paths or the controlled paths of the signature pad. Can be a list or a JSON string. Defaults to nil.
  • name (:string) - The name of the signature pad input for form submission.
  • errors (:list) - List of error messages to display. Defaults to [].
  • field (Phoenix.HTML.FormField) - A form field struct retrieved from the form, for example: @form[:signature]. Automatically sets id, name, value, and errors from the form field.
  • Global attributes are accepted.

Slots

  • label - Accepts attributes:
    • class (:string)
  • clear_trigger - Accepts attributes:
    • class (:string)
    • aria_label (:string) - Accessibility label for the clear button. Defaults to 'Clear signature' if not provided.
  • error - Accepts attributes:
    • class (:string)

API

clear(signature_pad_id)

Clears the signature pad from client-side. Returns a Phoenix.LiveView.JS command.

Examples

<button phx-click={Corex.SignaturePad.clear("my-signature-pad")}>
  Clear
</button>

clear(socket, signature_pad_id)

Clears the signature pad from server-side. Pushes a LiveView event.

Examples

def handle_event("clear_signature", _params, socket) do
  {:noreply, Corex.SignaturePad.clear(socket, "my-signature-pad")}
end