Corex UI
Pagination
Select

# Signature Pad

A pure HTML and vanilla JS implementation of Zag JS Signature Pad

The signature pad component allows users to draw handwritten signatures using touch or pointer devices. The signature can be saved as an image or cleared.


# Anatomy

The Signature Pad component consists of the following data parts:

root, label, hidden-input, control, segment, clear-trigger, guide

<div
              id="signature-anatomy"
              class="signature-pad signature-pad-js"
              data-on-draw-end="save-signature"
            >
              <div data-part="root">
                <label data-part="label">Signature Pad</label>
                <input data-part="hidden-input" />
                <div data-part="control">
                  <svg data-part="segment"></svg>
                  <button data-part="clear-trigger">
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke-width="1.5"
                      stroke="currentColor"
                    >
                      <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
                      />
                    </svg>
                  </button>
                  <div data-part="guide"></div>
                </div>
                <div data-part="preview"></div>
              </div>
            </div>
            
document
              .getElementById("signature-anatomy")
              ?.addEventListener("save-signature", async (event) => {
                const details = (event as CustomEvent).detail;
                console.log(details);
                const dataUrl = await details.getDataUrl("image/png");
                const preview = document.querySelector<HTMLElement>(
                  '[data-part="preview"]',
                );
                console.log(preview);
                console.log(dataUrl);
                if (!preview || !dataUrl) return;
                preview.innerHTML = `
                  <img src="${dataUrl}" alt="Signature preview" />
                  <button class="button button--sm button--accent" id="download-signature">Save Signature</button>
                `;
                const downloadBtn = document.getElementById("download-signature");
                downloadBtn?.addEventListener("click", () => {
                  const link = document.createElement("a");
                  link.href = dataUrl;
                  link.download = "signature.png";
                  link.click();
                });
                console.log("Signature preview populated with save button.");
              });
            

# Data attributes

Each signature pad can be set with different settings with the following data-attribute.

<div
              class="signature-pad signature-pad-js"
              data-fill="red"
              data-simulate-pressure="true"
              data-size="6"
            >
              <div data-part="root">
                <label data-part="label">Signature Pad</label>
                <input data-part="hidden-input" />
                <div data-part="control">
                  <svg data-part="segment"></svg>
                  <button data-part="clear-trigger">
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke-width="1.5"
                      stroke="currentColor"
                    >
                      <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
                      />
                    </svg>
                  </button>
                  <div data-part="guide"></div>
                </div>
              </div>
            </div>
            

id
Type: string
Description: Unique id of the signature pad. Default generated if none is provided.

data-dir
Type: string
Description: The orientation of the signature pad. Can be ltr or rtl.

data-name
Type: string
Description: The name of the signature pad useful for form submission.

data-disabled
Type: boolean
Description: Whether the signature pad is disabled.

data-required
Type: boolean
Description: Whether the signature pad is required.

data-read-only
Type: boolean
Description: Whether the signature pad is read-only.

data-default-paths
Type: string[]
Description: Default signature paths (uncontrolled).

data-paths
Type: string[]
Description: Controlled signature paths.

data-fill
Type: string
Description: Stroke color of the signature.

data-size
Type: number
Description: Stroke size of the signature.

data-simulate-pressure
Type: boolean
Description: Whether to simulate pressure in stroke drawing.


# Event Callbacks

Each signature pad component can receive callbacks that can be used to respond to user interaction with custom behavior.

You must add a custom id for the signature pad and a event listener for your event name

document
              .getElementById("my-signature-pad")
              ?.addEventListener("my-signature-pad-event", (event) => {
                console.log("Received event:", (event as CustomEvent).detail);
              });
            
<div
              id="my-signature-pad"
              class="signature-pad signature-pad-js"
              data-on-draw-end="my-signature-pad-event"
            >
              <div data-part="root">
                <label data-part="label">Signature Pad</label>
                <input data-part="hidden-input" />
                <div data-part="control">
                  <svg data-part="segment"></svg>
                  <button data-part="clear-trigger">
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke-width="1.5"
                      stroke="currentColor"
                    >
                      <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
                      />
                    </svg>
                  </button>
                  <div data-part="guide"></div>
                </div>
                <div data-part="preview"></div>
              </div>
            </div>
            

Open your browser's console to see the events received when the siganture pad draw ends

data-on-draw
Type: string
Description: Event name triggered while drawing on the signature pad.

data-on-draw-end
Type: string
Description: Event name triggered when drawing ends.


# Form usage

Signature pad can be used inside a form

You must set the id of the form and the name of the Signature pad

data-name="signature"

<form
              id="my-form"
              class="flex max-w-(--container-mini) flex-col items-center gap-(--spacing-ui-gap)"
            >
              <div class="signature-pad signature-pad-js" data-name="signature">
                <div data-part="root">
                  <label data-part="label">Signature Pad</label>
                  <input data-part="hidden-input" />
                  <div data-part="control">
                    <svg data-part="segment"></svg>
                    <button data-part="clear-trigger">
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        fill="none"
                        viewBox="0 0 24 24"
                        stroke-width="1.5"
                        stroke="currentColor"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
                        />
                      </svg>
                    </button>
                    <div data-part="guide"></div>
                  </div>
                </div>
              </div>
              <button class="button button--accent" type="submit">Submit</button>
              <div id="result"></div>
            </form>
            

You can use the results from the form as you wish

const signaturePadForm = document.getElementById(
              "my-form",
            ) as HTMLFormElement | null;
            const signatureResult = document.getElementById(
              "result",
            ) as HTMLDivElement | null;
            
            if (signaturePadForm && signatureResult) {
              signaturePadForm.addEventListener("submit", (e: Event) => {
                e.preventDefault();
                const formData = new FormData(signaturePadForm);
                console.log(formData.getAll("signature"));
                const signature = (formData.get("signature") as string) || "none";
                signatureResult.innerHTML = `Submitted: signature: <span class="overflow-scroll scrollbar scrollbar--sm max-h-(--container-mini) block max-w-(--container-mini) break-all">${signature}</span>`;
              });
            }
            

# Installation

First, complete the Corex UI initial installation guide for your platform, bundler, or framework.

  1. Import the component
import "@corex-ui/static/components/signature-pad";
            

This will automatically initialize all elements with class="signature-pad-js" and add the necessary interaction behavior.

  1. Add styling

The component is unstyled by default for maximum customization flexibility.

To apply the default Corex UI design system styles, import the stylesheet:

@import "@corex-ui/design/components/signature-pad.css";
            

These styles will be applied to all elements with the signature-pad class.