Skip to content
weftGitHub

SignaturePad

Sign by drawing or by typing a name.

SourcePackage @weft-js/warp

Preview

tsx
import { state } from '@weft-js/core'import { SignaturePad, Stack, Text } from '@weft-js/warp'import type { SignatureValue } from '@weft-js/warp'export function Basic() {  const signature = state<SignatureValue | null>(null)  return (    <Stack gap="related">      <SignaturePad label="Signature" value={signature} />      <Text subtle>{signature.value ? `Signed: ${signature.value.method}` : 'Not signed yet'}</Text>    </Stack>  )}

Installation

npm install @weft-js/warp

Usage

tsx
import { SignaturePad } from '@weft-js/warp'

Type to sign

Always on offer, for people who can't draw.

tsx
import { SignaturePad } from '@weft-js/warp'export function Typed() {  return (    <SignaturePad label="Signature" defaultValue={{ method: 'typed', text: 'Mara Lindqvist', svg: '' }} />  )}

States

A signature pad can be empty, show a hint, or show an error.

tsx
import { Grid, SignaturePad, Stack, Text } from '@weft-js/warp'export function States() {  return (    <Grid cols={3} gap="group">      <Cell name="Empty"><SignaturePad label="Signature" /></Cell>      <Cell name="Hint"><SignaturePad label="Signature" hint="Sign as Mara Lindqvist, Owner." /></Cell>      <Cell name="Invalid"><SignaturePad label="Signature" error="Sign before you continue." /></Cell>    </Grid>  )}const Cell = (p: { name: string; children?: unknown }) => (  <Stack gap="tight">    <Text role="caption" subtle>{p.name}</Text>    {p.children}  </Stack>)

Sign an agreement

Press the button without signing.

tsx
import { state } from '@weft-js/core'import { Button, SignaturePad, Stack, Text } from '@weft-js/warp'import type { SignatureValue } from '@weft-js/warp'export function FormDataAgreement() {  const signature = state<SignatureValue | null>(null)  const tried = state(false)  const done = state(false)  const submit = (e: Event) => {    e.preventDefault()    tried.value = true    if (signature.value) done.value = true  }  return (    <Stack as="form" gap="group" onSubmit={submit}>      <Stack gap="hair">        <Text role="heading">Data processing agreement</Text>        <Text subtle>weft GmbH will process logs only to run your deploys.</Text>      </Stack>      <SignaturePad label="Signature" value={signature} error={tried.value && !signature.value ? 'Sign before you continue.' : undefined} />      <Button type="submit" full>{done.value ? 'Signed' : 'Sign agreement'}</Button>    </Stack>  )}

Accessibility

  • Typing a name is always available, so keyboard and switch users can sign.
  • The status under the pad is announced.

API Reference

PropTypeDefaultDescription
labelstring—The visible name, and what screen readers announce.
hintunknown—A short line of help under the field.
errorunknown—Replaces the hint and marks the field invalid.
iconIconRef—Leading icon: it sweeps with the border.
prefixunknown—Text or an element inside the field before the value, such as $.
suffixunknown—Text or an element inside the field after the value, such as kg.
variant"floating" | "classic"—floating (default, or the app's warp({ fields })) · classic: the label above.
appearance"line"—line: only a bottom line under the value, no box or fill. The boxed field otherwise.
size"sm" | "md" | "lg"'md'Control size. md by default.
clearablebooleanfalseA clear button (shown once there is a value).
counternumber—Maximum length, shown as a counter.
idstring—The element id. One is made for you if you leave it out.
disabledbooleanfalseCan't be focused or changed.
readonlybooleanfalseShows the value and lets it be selected and copied, but not changed.
valueSignatureValue | State<SignatureValue | null> | null—The signature with its strokes or text and an SVG, or a State to bind.
defaultValueSignatureValue | null—The starting value, when the component owns the state.
EventTypeDefaultDescription
onInput((e: InputEvent & { currentTarget: HTMLInputElement & HTMLTextAreaElemen…—Called on each keystroke.
onValueChange((v: SignatureValue | null, reason: ChangeReason) => void)—Hears the new signature and why it changed.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="signature"] [data-part="pad"]

pademptybaselinetyped

RelatedInputCanvas