Edit region
Lets people paint over part of an image and say what should change there, for inpainting tools.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/edit-region.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/edit-region.json
Usage & API
Example
import { EditRegion } from "@/components/ai/edit-region"
<EditRegion
image={image}
strokes={[]}
onStrokesChange={() => {}}
brushSize={1}
onBrushSizeChange={() => {}}
prompt="…"
onPromptChange={() => {}}
onSubmit={() => {}}
/>Props EditRegion
| Prop | Type & description | Required |
|---|---|---|
image | ReactNode | Required |
edited | ReactNodeWhat the masked area becomes once the edit lands. | Optional |
strokes | Stroke[] | Required |
onStrokesChange | (strokes: Stroke[]) => void | Required |
brushSize | number | Required |
onBrushSizeChange | (size: number) => void | Required |
prompt | string | Required |
onPromptChange | (value: string) => void | Required |
onSubmit | (prompt: string, mask: Stroke[]) => void | Required |
status | "idle" | "editing" | "done" | Optional |
appliedStrokes | Stroke[]Strokes already applied in a finished edit. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
Brush and prompt is the only variant. The frame is 16:9. The canvas is an image role whose label changes from a paint instruction to a note that an area is marked, once any stroke exists. Drawing uses pointer capture, appends points as the pointer moves, and paints the new segment immediately, then commits the stroke list on pointer up. While status is editing, the canvas opacity goes to zero so the shimmer, masked to the strokes, is the only mark. The range input is labelled Brush size. Undo is an icon button. Clear is a text button with an eraser icon. The form submits on Enter inside the prompt. The corner chip is the only status sentence. There is no separate progress percent. The preview image is the shared landscape artwork, and the edited node is another palette revealed through the mask after the demo finishes.
Choosing a layout
Use it when the edit is local. Changing the sky, removing an object, or restyling one region all need a mask, and a full-frame prompt would be ambiguous. The tool pill sits on the picture so brush size, undo, and clear stay next to the stroke. The prompt stays under the frame so it does not cover the mask. Keep the underlying image at the same 16:9 crop as the canvas. Points are normalized to the mask width and height, then drawn back in CSS pixels, so a responsive card still lines up.
Use Before and after once the edit exists and the person wants to compare the whole frame, not paint again. Use Image results if the model returned several full images rather than a masked change. Image generation is only the wait. This component is also a poor fit for a rectangular crop tool: there is no marquee, only freehand strokes with a round cap. If the person should type a prompt with no mask, do not force a stroke. Submit will not enable until paint exists, which is the point of this layout and the wrong rule for a global edit.
What is actually submitted?
onSubmit receives the trimmed prompt only in the sense that the button requires a non-empty string, and it receives the current stroke array. Each stroke has a size and points in mask units. The parent turns that into a mask image or a model request. The soft PNG the component builds is for display during editing and for the applied reveal, not the payload.
What does each status change on screen?
Idle allows painting, undo, clear, and submit when the mask and prompt are ready. Editing blocks new strokes, disables undo and clear, disables submit, and plays the shimmer inside the mask. Done is only a label change: if you have cleared the working strokes, the pill says the edit was applied, and any appliedStrokes plus the edited node show through the mask. The field does not lock itself on done.