Skip to content

Signature Pad

Draw a signature with a pointer and capture it as SVG paths / a data URL. Strokes are dynamic, so you provide a <template> for a path; stimulus-zag renders one per committed stroke plus the one under the pointer, so ink appears as you draw. Author the template as a plain <path> — it is rebuilt in the SVG namespace for you (markup inside a <template> parses as HTML, and an HTML <path> paints nothing).

html
<div data-controller="zag-signature-pad" data-part="root" class="w-full max-w-md space-y-2">
  <div
    data-part="control"
    class="border-input bg-popover relative h-40 touch-none rounded-lg border"
  >
    <svg data-part="segment" class="text-foreground h-full w-full"></svg>
    <div
      data-part="guide"
      class="border-input pointer-events-none absolute inset-x-4 bottom-8 border-b border-dashed"
    ></div>
  </div>
  <button
    data-part="clear-trigger"
    class="border-input hover:bg-accent rounded-lg border px-3 py-1.5 text-sm"
  >
    Clear
  </button>
  <input data-part="hidden-input" class="sr-only" />
  <template data-zag-signature-pad-target="pathTemplate">
    <path
      data-part="segment-path"
      fill="none"
      stroke="currentColor"
      stroke-width="2.5"
      stroke-linecap="round"
      stroke-linejoin="round"
    >
    </path
  ></template>
</div>

Parts

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

Values

AttributeTypeDefaultDescription
data-zag-signature-pad-paths-valueArray[]Initial stroke paths (JSON).
data-zag-signature-pad-name-valueString""name for form submission.
data-zag-signature-pad-disabled-valueBooleanfalseDisable drawing.
data-zag-signature-pad-read-only-valueBooleanfalseRead-only.
data-zag-signature-pad-required-valueBooleanfalseMark required.

Events

Emits zag-signature-pad:draw-enddetail is { paths }. The hidden input is populated with the signature as a PNG data URL on each stroke.

Programmatic control

isEmpty (getter), paths (getter), clear(), toDataUrl(type?) (returns a Promise).