Signature Pad
A canvas you sign with a finger, stylus or mouse. Strokes are kept as points and redrawn, so undo, resize and export all work — and stylus pressure varies the line.
src/components/ui/signature-pad.tsxAbout
From the component's own source, where it was written.
A canvas you sign with a finger, a stylus or a mouse.
**Strokes are stored as points, and the canvas is redrawn from them.** The naive version draws straight to the canvas and keeps no model — which means undo is impossible, a resize wipes the drawing, and exporting at a different resolution is not an option. Keeping the points makes all three fall out.
**Pointer events, not mouse or touch.** One set of handlers covers a mouse, a finger and a pen, and pressure from a stylus varies the stroke width the way a real pen does. touch-action: none is essential: without it the first downward stroke scrolls the page instead of drawing.
**It is drawn at device pixel ratio.** A canvas sized in CSS pixels is visibly soft on any modern screen, and a signature is a thing people zoom into. The backing store is scaled up and the context scaled down to match.
A signature captured this way is a picture of a squiggle. It is fine as a record that someone signed; it is **not** a digital signature and proves nothing cryptographically. If you need non-repudiation, sign a hash of the document with a key, and keep this as the human-facing part.
Install
npx astralyx-ui add signature-pad
Usage
import { SignaturePad } from '@/components/ui/signature-pad'
<SignaturePad onSign={(blob) => upload(blob)} />Composer
Change the props and the source below follows.
<SignaturePad
penWidth={2}
onSign={(blob) => upload(blob)}
/>Examples
Sign, undo, clear
<SignaturePad onSign={(blob) => upload(blob)} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
SignaturePad
Extends Omit<ComponentProps<'div'>, 'onChange'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue | string | number | readonly string[] | — | — |
| value | Stroke[] | — | Points, not pixels. Drawing straight to the canvas with no model makes undo impossible and loses the drawing on resize. |
| onChange | (strokes: Stroke[]) => void | — | — |
| onSign | (blob: Blob, strokes: Stroke[]) => void | — | Flattened image on demand, via toBlob. |
| height | number | 180 | — |
| penColor | string | 'currentColor' | — |
| penWidth | number | 2 | Base stroke width. Stylus pressure scales it. |
| background | string | 'transparent' | Transparent by default, so it composites onto a document. |
| outputType | string | 'image/png' | — |
| clearLabel | string | 'Clear' | — |
| undoLabel | string | 'Undo' | — |
| saveLabel | string | 'Save' | — |
| actions | boolean | true | — |
| guideline | boolean | true | The line people sign above. |
| placeholder | string | 'Sign here' | — |
| label | string | 'Signature' | — |
| disabled | boolean | — | — |
Types
Point
A canvas you sign with a finger, a stylus or a mouse.
| Field | Type | Description |
|---|---|---|
| x | number | — |
| y | number | — |
| pressure | number | — |
| Type | Definition | Description |
|---|---|---|
Stroke | Point[] | — |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| pointer events | one set | Mouse, finger and pen through one path, with pressure from a stylus varying the width. touch-action: none is essential or the first stroke scrolls the page. |
| device pixel ratio | handled | The backing store is scaled up and the context scaled down; a canvas sized in CSS pixels is visibly soft, and a signature is a thing people zoom into. |
| not a digital signature | a picture | Fine as a record that someone signed; proves nothing cryptographically. For non-repudiation, sign a hash of the document with a key. |