Skip to content
Sign in
Image studioRealtime canvasMenu

Realtime canvasPro

Draw on the left and watch the model answer on the right as you draw: frames sent on change at a capped rate, images swapped without flicker, end to end latency with the last 24 frames, connection states, pause and save frame.

ProDraw on the left and the right answers as you draw, with end to end latency. The model is simulated in the browser as a clay render over a fake network.

Installation

$ pnpm dlx shadcn@latest add @chatcn-pro/realtime-canvas

Usage

tsx
import { RealtimeCanvas } from "@/components/ui/chatcn/pro/realtime-canvas"

<RealtimeCanvas
  status={client.status}
  output={latest}
  onFrame={async (frame) => {
    const image = await client.send(await frame.toBlob(), frame.prompt, frame.strength)
    setLatest({ frameId: frame.id, src: image.url })
  }}
  onRetry={client.reconnect}
/>

Bring any realtime client. The canvas sends a frame whenever the sketch, prompt or strength changes, at most maxFps times a second (the first change at once, the last always), and shows whatever you hand back on output. Tag each output with the frameId it answers: the latency readout is measured end to end from that, older answers than the one on screen are ignored, and decoding happens off screen so frames swap without flicker. The demo's model is simulated in the browser.

Examples

States

ProConnecting, a slow connection in amber, paused on the last frame, a dropped connection with Reconnect and disabled.

Props

PropTypeNotes
status"connecting" | "live" | "reconnecting" | "error"From your client. Default live
error, onRetrystring, () => voidSay how to fix it; Reconnect calls onRetry
onFrame({ id, canvas, prompt, strength, toDataURL, toBlob }) => voidThe sketch at frameWidth, ink on white
output{ frameId, src?, image? }A URL, or an image, bitmap or canvas already decoded
latencyMsnumberUse your client's own measure instead
maxFps, frameWidthnumberDefault 12 and 512 px
prompt, defaultPrompt, onPromptChangestringChanges send a frame
strength, defaultStrength, onStrengthChangenumberHow closely to follow the sketch, 0 to 1. Default 0.7
paused, defaultPaused, onPausedChangebooleanStops sending; the last image stays
onSaveFrame(blob: Blob) => voidShows Save frame
slowAfterMsnumberLatency above it reads amber. Default 400
aspectRatio, sketchProps, disabledBoth panes' shape, the sketch pad's props, lock

Keyboard

KeyAction
Sketch pad keysB, X, R, C, F, 1 to 9, [, ], undo and redo
TabPrompt, Follow sketch, Pause and Save frame

Accessibility

  • The output is an image named by the prompt. Connection changes are announced politely; frames and latency are not, so a screen reader is never flooded.
  • Status pairs a dot with a word (Live, Paused, Off, Connecting, Disconnected); a slow connection turns the latency amber and its bars stand out, never color alone.
  • Follow sketch is a slider that announces a percentage.

Motion

  • Frames swap in one paint with no fade: a fade would make the image lag the sketch. Only the first frame fades in, 200 ms.
  • Updating shows only when an answer is more than 600 ms late. Connecting shows after 300 ms and stays at least 400 ms.