SignaturePad

A standalone signature capture component that supports drawing signatures with touch and mouse input.

Import

import { SignaturePad, type SignatureData } from '@mims/sdk-react';

Basic Usage

<SignaturePad
  onComplete={(data) => {
    console.log('Signature captured:', data);
  }}
/>

Props

PropTypeDefaultDescription
widthnumber400Width of the signature canvas in pixels.
heightnumber200Height of the signature canvas in pixels.
strokeColorstring"#000000"Color of the signature stroke.
strokeWidthnumber2Width of the signature stroke in pixels.
onSignatureChange(data: SignatureData | null) => voidCalled whenever the signature changes (including clear).
onComplete(data: SignatureData) => voidCalled when user clicks "Accept Signature" button.

SignatureData Type

The signature data returned by the component:

interface SignatureData {
  /** Base64 encoded PNG image of the signature */
  imageData: string;
  
  /** SVG path data for vector representation */
  pathData: string;
  
  /** Raw points for custom rendering (normalized 0-1) */
  points: Array<{ x: number; y: number }[]>;
}

Examples

Basic Signature Capture

function SignatureCapture() {
  const [signature, setSignature] = useState<SignatureData | null>(null);

  return (
    <div>
      <SignaturePad
        width={500}
        height={250}
        strokeColor="#1a1a1a"
        strokeWidth={3}
        onComplete={(data) => {
          setSignature(data);
          console.log('Signature accepted');
        }}
      />
      
      {signature && (
        <div className="mt-4">
          <h4>Captured Signature:</h4>
          <img src={signature.imageData} alt="Signature" />
        </div>
      )}
    </div>
  );
}

Signature in Form

1function ContractForm() {
2 const [formData, setFormData] = useState({
3 name: '',
4 email: '',
5 signature: null as SignatureData | null,
6 });
7
8 const handleSubmit = async (e: React.FormEvent) => {
9 e.preventDefault();
10
11 if (!formData.signature) {
12 alert('Please sign the document');
13 return;
14 }
15
16 // Submit form with signature
17 await fetch('/api/contracts', {
18 method: 'POST',
19 headers: { 'Content-Type': 'application/json' },
20 body: JSON.stringify({
21 ...formData,
22 signatureImage: formData.signature.imageData,
23 }),
24 });
25 };
26
27 return (
28 <form onSubmit={handleSubmit}>
29 <div className="space-y-4">
30 <input
31 type="text"
32 placeholder="Full Name"
33 value={formData.name}
34 onChange={(e) => setFormData({ ...formData, name: e.target.value })}
35 required
36 />
37
38 <input
39 type="email"
40 placeholder="Email"
41 value={formData.email}
42 onChange={(e) => setFormData({ ...formData, email: e.target.value })}
43 required
44 />
45
46 <div>
47 <label>Signature</label>
48 <SignaturePad
49 onComplete={(data) => {
50 setFormData({ ...formData, signature: data });
51 }}
52 />
53 </div>
54
55 <button type="submit">Submit Contract</button>
56 </div>
57 </form>
58 );
59}

Real-time Preview

function SignatureWithPreview() {
  const [preview, setPreview] = useState<string | null>(null);

  return (
    <div className="grid grid-cols-2 gap-8">
      <div>
        <h4>Draw Signature</h4>
        <SignaturePad
          onSignatureChange={(data) => {
            setPreview(data?.imageData ?? null);
          }}
          onComplete={(data) => {
            // Handle completion
            saveSignature(data);
          }}
        />
      </div>
      
      <div>
        <h4>Preview</h4>
        <div className="border rounded-lg p-4 bg-gray-50 h-[200px] flex items-center justify-center">
          {preview ? (
            <img 
              src={preview} 
              alt="Signature preview" 
              className="max-w-full max-h-full"
            />
          ) : (
            <span className="text-gray-400">
              Start drawing to see preview
            </span>
          )}
        </div>
      </div>
    </div>
  );
}

Custom Styling

<div className="signature-container">
  <SignaturePad
    width={450}
    height={180}
    strokeColor="#0066cc"
    strokeWidth={2.5}
    onComplete={handleComplete}
  />
</div>

/* CSS */
.signature-container {
  padding: 20px;
  background: linear-gradient(to bottom, #f8f9fa, #e9ecef);
  border-radius: 12px;
}

.signature-container .mims-signature-pad {
  border: 2px solid #dee2e6;
  border-radius: 8px;
  background: white;
}

Touch Support

The SignaturePad automatically supports touch devices. Users can sign using their finger on tablets and mobile phones.

Mobile Optimization

For best mobile experience, ensure the signature pad has enough size for comfortable signing. We recommend at least 300x150 pixels on mobile devices.

Clear and Reset

The component includes a built-in "Clear" button. When clicked:

  • The canvas is cleared
  • onSignatureChange is called with null
  • The "Accept Signature" button becomes disabled

Working with Image Data

Display Captured Signature

// The imageData is a data URL that can be used directly
<img src={signature.imageData} alt="Signature" />

// Or convert to Blob for upload
const blob = await fetch(signature.imageData).then(r => r.blob());
const file = new File([blob], 'signature.png', { type: 'image/png' });

// Upload to server
const formData = new FormData();
formData.append('signature', file);
await fetch('/api/upload', { method: 'POST', body: formData });

Server-side Processing

// On the server (Node.js example)
app.post('/api/signature', async (req, res) => {
  const { imageData } = req.body;
  
  // Remove data URL prefix
  const base64Data = imageData.replace(/^data:image\/png;base64,/, '');
  
  // Convert to buffer
  const buffer = Buffer.from(base64Data, 'base64');
  
  // Save to file or storage
  await fs.writeFile('signature.png', buffer);
  
  // Or process with image library
  const image = await sharp(buffer)
    .resize(200, 100)
    .toBuffer();
});

Accessibility

Accessibility Note

The signature pad is primarily designed for visual input. For users who cannot draw, consider providing alternative options like:
  • Typed signature option
  • Upload signature image
  • Checkbox agreement instead of signature

TypeScript Types

import type { SignatureData } from '@mims/sdk-react';

// Use in your components
const handleSignature = (data: SignatureData) => {
  // TypeScript knows the shape of data
  console.log(data.imageData);  // string
  console.log(data.pathData);   // string
  console.log(data.points);     // Array<{x: number, y: number}[]>
};