Skip to content
MediaImage edit regionMenu

Image edit region

Mark part of an image with a rectangle or a brush, then describe the change. The mask shows as monochrome hatching that reads on any image.

Drag a rectangle over the part to change, describe the edit, and the result generates below.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/image-edit-region.json

Usage

tsx
import { ImageEditRegion } from "@/components/ui/chatcn/image-edit-region"
import { chatcnMaskToDataUrl } from "@/hooks/use-chatcn-media-mask"

<ImageEditRegion
  src={image.src}
  alt={image.alt}
  width={image.width}
  height={image.height}
  submitting={editing}
  onSubmit={async ({ prompt, selection }) => {
    // Transparent where the user marked: the format OpenAI-style edit endpoints expect.
    const mask = chatcnMaskToDataUrl(selection, { width: image.width, height: image.height })
    await editImage({ image: image.src, mask, prompt })
  }}
/>

Selections are stored in fractions of the image, so they survive resizes and map onto the real pixels when you build the mask. Pass format: "luminance" to chatcnMaskToDataUrl for inpainting models that want a white region on black. The rectangle and the brush keep separate marks, so switching tools never throws one away.

Examples

Brush

Paint loose shapes with an adjustable brush. The ring under the pointer is the brush size, and every stroke is one undo step.

Paint a loose mask with an adjustable brush. Undo and redo step through strokes.

Props

PropTypeNotes
src, altstringThe image and what it shows
width, height, aspectRationumberSet the frame's shape
mode, defaultMode, onModeChange"rect" | "brush"The active tool
defaultSelection, onSelectionChangeChatcnMaskSelection{ kind: "rect", rect } or { kind: "brush", strokes }
defaultBrushSizenumberBrush diameter in px on screen. Default 32
value, defaultValue, onValueChangestringThe description
onSubmit({ prompt, selection }) => voidOnly fires with a mark and text
submittingbooleanLocks the tools and shows Editing region
disabledboolean
submitLabelstringDefault Edit region

useChatcnMediaMask is the state behind it, exported for your own editor: rectangle, strokes, live drags, undo, redo and clear.

Keyboard

KeyAction
Enter on the imageStart a centered selection when there is none
← → ↑ ↓Move the selection by 1%. Mirrored in RTL
Shift + arrowMove by 10%
Alt + arrowResize from the end edges
Delete, BackspaceClear the selection
⌘Z / Ctrl+ZUndo
⇧⌘Z / Ctrl+YRedo
Enter in the descriptionApply the edit. Shift+Enter adds a line

Accessibility

  • The image is a focusable group with a description of the controls. The rectangle is fully keyboard operable; the brush is a pointer tool with the rectangle as its keyboard alternative.
  • Keyboard moves announce the selection's size and position in a polite live region.
  • The tool switch is a toggle group, and every icon button has a label and a tooltip with its shortcut.
  • Enter never applies the edit while an IME composition is open.
  • Corner handles have a 24 px hit area with a mouse and 44 px with a finger.

Motion

  • None. Drawing, moving and resizing track the pointer one to one, and keyboard changes are instant.
  • A held arrow key is one undo step: the selection commits when the key comes up.