Signature pad

Smooth ink that thins with speed, with undo, replay, and PNG or SVG export.

pnpm dlx shadcn@latest add @uiarc/signature-pad
Live · keyboard ready

Lease agreement

1420 Alder Street, unit 3B · 12 months from Oct 1, 2026

Save as

Press Control or Command Z to undo, add Shift to redo, and Delete to clear.

  • Contracts, delivery confirmations, and consent forms that need a drawn signature.
  • Initials or quick sketches where pen pressure and natural stroke width matter.
  • Flows that need a clean, cropped PNG or SVG of the signature.
  • Use input for a typed name when a legal drawn signature is not required.
  • Use file-upload when the user already has a scanned signature image.
  • Use hold-to-confirm for a simple deliberate confirmation without a signature artifact.

Installation

Add Signature pad with the shadcn CLI, or copy the source by hand.

pnpm dlx shadcn@latest add @uiarc/signature-pad

Adds the component and its local dependencies, and installs motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:

example.tsx
import { useState } from "react";import { SignaturePad, signatureToSvg } from "@/registry/components/signature-pad/signature-pad";import type { InkStroke } from "@/registry/components/signature-pad/signature-pad"; export function SignContract() {  const [strokes, setStrokes] = useState<InkStroke[]>([]);   return (    <form onSubmit={event => { event.preventDefault(); submit(signatureToSvg(strokes)); }}>      <SignaturePad signer="Ada Lovelace" fileName="ada-signature" onChange={setStrokes} />      <button type="submit" disabled={!strokes.length}>Sign</button>    </form>  );}

API reference

3 parts. The first is the root.

SignaturePad

A signature field with pressure-sensitive ink, undo and redo, a wipe to clear, replay, and PNG or SVG export.

PropTypeDefaultDescription
signerstring–Printed under the baseline, such as the signer's name.
hintstring"Sign here"Resting hint on the baseline before the first stroke.
defaultColor"black" | "blue" | "violet""black"Starting ink color.
defaultWidth"fine" | "medium" | "bold""medium"Starting nib width.
onChange(strokes: InkStroke[]) => void–Receives the strokes after every change, including undo, redo, and clear.
fileNamestring"signature"File name for exports, without extension.
labelstring"Signature pad"Accessible name of the drawing surface.
classNamestring–Extra class on the root.

signatureToSvg

Returns a standalone SVG string of the strokes, cropped to the ink with print ink colors. Empty string for no strokes.

PropTypeDefaultDescription
strokesRequiredInkStroke[]–Strokes as received from onChange.

signatureToPng

Resolves to a transparent PNG Blob cropped to the ink. Rejects when there are no strokes.

PropTypeDefaultDescription
strokesRequiredInkStroke[]–Strokes as received from onChange.
scalenumber3Multiple of the 600 by 260 pad resolution.
Mod+Z
Undoes the last change while the pad is focused.
Shift+Mod+ZorMod+Y
Redoes.
DeleteorBackspace
Clears the signature with the wipe; undo brings it back.
Escape
Stops a replay in progress.
Arrow keys
Move between ink colors or nib widths inside each radio group.
  • The pad is focusable with role="img", aria-roledescription="signature pad", and a label that states the stroke count.
  • Keyboard shortcuts are described through aria-describedby on a visually hidden paragraph.
  • Ink color and width are radio groups with roving tabindex; toolbar icon buttons carry aria-label and title.
  • A polite status region announces strokes added, undo, redo, clear, replay, and export results.
  • Clear sweeps a squeegee edge across the pad while a clip-path wipe removes the ink over 0.56s.
  • Replay redraws each stroke in its original rhythm with a nib dot, capping gaps between strokes and fitting the whole replay into about 3.2s.
  • The hint fades up from a soft blur; the selected color and width highlight glides with a shared layout spring.
  • Reduced motion skips the wipe and blur and uses short opacity fades.
  • The pad keeps a 600 / 260 aspect ratio at every width, and strokes scale with it.
  • touch-action: none on the pad keeps finger strokes from scrolling the page; coalesced pointer events capture fast strokes on touch and pen.
  • The toolbar wraps on narrow widths; hover styles apply only on hover-capable fine pointers.
  • The live stroke writes its SVG path directly to the DOM on each pointer move, without a React render.
  • History keeps the last 60 states; replay runs a rAF loop that re-renders the visible strokes each frame, so very long signatures cost more to replay.
  • PNG export draws to an offscreen canvas at 3x by default.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use for capturing a handwritten signature or initials. Store the InkStroke[] from onChange, or convert it with signatureToSvg or signatureToPng on submit.
  • Strokes are stored in a 600 by 260 coordinate space (PAD_WIDTH, PAD_HEIGHT), so they scale with the pad and can be replayed later.
  • getStrokeOutline, outlineToPath, and strokePath are also exported if you need the raw outline math.
  • The pad is uncontrolled; to reset it, remount it with a new key.

The full library index for assistants is at /llms.txt.