Sketch

A finger-drawing surface with a pen, eight shapes, an eraser, colours, stroke width and undo, exported as SVG or PNG.

Open Source

Installation

Sketch ships with the library — install it once, then import:

import { Sketch } from "@delacour/react-native-ui/sketch";

Or copy the source into your project, to own and edit it:

bunx delacour@latest add sketch

Usage

app/index.tsx
import { Button } from "@/components/ui/button";
import { Sketch, type SketchHandle } from "@/components/ui/sketch";
import { useRef } from "react";
import { View } from "react-native";

export default function Example() {
  const sketch = useRef<SketchHandle>(null);

  return (
    <View className="flex-1 gap-3 p-4">
      <Sketch className="flex-1" ref={sketch} />
      <Button onPress={() => console.log(sketch.current?.toSVG({ background: null }))}>
        <Button.Label>Done</Button.Label>
      </Button>
    </View>
  );
}

Tools and shapes

shapes chooses which of the eight shapes the toolbar offers; a shape is drawn by dragging.

Shapes
<Sketch defaultTool="shape" defaultShape="arrow" shapes={["arrow", "rectangle", "ellipse"]} />

Colours

colors takes theme tokens and literals; each mark keeps the colour it was drawn in, whatever the theme does next.

Colours
Colours
<Sketch colors={["foreground", "primary", "#ec4899", "#14b8a6"]} defaultColor="#ec4899" />

Stroke width

size is the width in points, between minSize and maxSize. It applies to the next stroke only.

<Sketch defaultSize={8} minSize={2} maxSize={32} />

Eraser

The eraser hides only ink drawn before it — a later stroke over the same spot is untouched, and undo brings erased ink back.

Eraser

Undo and the handle

Sketch.Undo removes the last mark; the ref carries the same operations for buttons outside the sketch.

const sketch = useRef<SketchHandle>(null);

sketch.current?.undo();
sketch.current?.clear();
sketch.current?.isEmpty();

Exporting SVG

toSVG() returns a self-contained SVG on the theme's background — pass background: null for a transparent file; saving it is your app's job.

const svg = sketch.current?.toSVG({ background: null }) ?? "";

Exporting PNG

toPNG() renders the marks off screen at the screen's pixel ratio and returns base64, with the same background option and a scale for the pixels per point.

const png = sketch.current?.toPNG({ scale: 2 }) ?? "";
const uri = `data:image/png;base64,${png}`;

Your own toolbar

Pass children to choose and order the parts yourself.

<Sketch className="flex-1">
  <Sketch.Canvas />
  <Sketch.Toolbar>
    <Sketch.Tool tool="pen" />
    <Sketch.Tool tool="shape" shape="arrow" />
    <Sketch.Tool tool="eraser" />
    <Sketch.Swatches />
    <Sketch.Undo />
  </Sketch.Toolbar>
</Sketch>

Annotating an image

Sketch.Canvas children are painted under the marks; either export holds only the marks.

Annotate
<Sketch className="flex-1">
  <Sketch.Canvas>
    <Image className="absolute inset-0" resizeMode="contain" source={photo} />
  </Sketch.Canvas>
  <Sketch.Toolbar />
</Sketch>

Accessibility

The canvas reads as an image ("Drawing, 3 marks") with undo and clear actions.

Drawing by touch exploration is not supported. Where the drawing matters, offer screen-reader users another way to provide it.

API Reference

Anatomy

PartWhat it is
SketchOwns the marks, the tool, the shape, the colour and the width, and the handle
Sketch.CanvasThe drawing surface. Children are painted under the marks
Sketch.ToolbarThe tool tray — every tool when it has no children
Sketch.ToolOne tool: the pen, the eraser, or a shape
Sketch.SwatchesThe colour swatches, as a radio group
Sketch.SizeThe stroke-width slider
Sketch.UndoRemoves the last mark

Sketch

Prop

Type

Sketch.Tool

Prop

Type

Sketch.Swatches

Prop

Type

Sketch.Size

Prop

Type

SketchHandle

Prop

Type

SketchItem

Prop

Type

On this page