Conversation
Adds a toolbar Draw tool that lets you sketch freehand strokes and type text notes over the page, then copies a WYSIWYG screenshot to the clipboard (Enter to copy, Escape to cancel, Cmd/Ctrl+Z to undo). - Vendors perfect-freehand (consolidated, single file) for stroke output - Page-coordinate anchoring so drawings ride along with scroll/resize - Copy/Cancel menu + "Copied" toast share one AnchoredDropdownPanel - Other toolbar actions are locked while Draw owns the screen - e2e coverage in draw.spec.ts
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
|
bugbot run |
- Restore hidden toolbar/menu if the user exits draw mode mid-capture, and skip the screen-share prompt when no longer active after the capture delay - Ignore IME composition keydowns so confirming a composition doesn't trigger capture or corrupt an in-progress text note - Stop the getDisplayMedia stream on any capture failure (metadata/ready rejections previously leaked the stream)
|
bugbot run |
There was a problem hiding this comment.
3 issues found and verified against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
The toast computed its anchor once, so a post-capture reflow (e.g. the screen-share indicator bar collapsing) shifted the toolbar and stranded the toast at a stale position. Track the toolbar continuously for the toast's lifetime, mirroring the Copy/Cancel menu, and stop the tracker on fade-out and dispose.
- Unify committed strokes/texts into one ordered list so Cmd/Ctrl+Z undoes the genuinely-last action (and later items paint on top) regardless of type - Move all stream-touching setup inside the capture try/finally so a metadata/ready-state rejection can't leak the screen-capture stream - Add role="status" / aria-live="polite" to the "Copied" toast so screen readers announce it, matching CompletionView
|
bugbot run |
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
- Tag each draw session with an id and bail from an in-flight capture after any await if the session ended or was restarted, so a stale capture can no longer copy an abandoned shot or tear down a freshly-started session - Hide the Draw toolbar button and block the activation path (shortcut / api.annotate) when screen capture or clipboard-image write is unsupported, honoring the annotate plugin's existing enabled gate
|
bugbot run |
Reopening Draw before the toast's fade timer fired left it tracking and visible during the new session. Centralize toast teardown in one helper and call it from onOpen (and dispose), so a new session always starts clean.
- Use event.pressure directly instead of `|| fallback`, which treated a valid pressure of 0 (lightest pen touch) as missing; PointerEvent.pressure is always a number, so the fallback (and its constant) were unnecessary - Rename the draw e2e describe block to "Draw mode" (was "Draw (draw) mode" after the annotate->draw rename)
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
1 issue from previous review remains unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit bef1964. Configure here.
Replace the canvas-drawn note + hand-rolled blinking caret with a focused <input> (native caret, selection, IME, blur-to-commit) positioned over the canvas; flatten it onto the canvas on commit so the screenshot stays WYSIWYG, and re-open an input when a committed note is clicked. The input is frameless (plain accent text + native caret), dropping the canvas caret/box drawing, the blink interval, the manual IME guard while editing, and their constants.
|
bugbot run |
lastPointer held page coordinates captured at the last pointer event, so scrolling without moving the mouse and then typing dropped the note at the stale page position. Store the pointer in client (viewport) coords and add the current scroll only when placing the note.
|
bugbot run |
Strokes recorded PointerEvent.pressure but getStroke ran with the default simulatePressure: true, ignoring it. Tag each stroke by input type so pen strokes use their recorded pressure while mouse/touch (constant pressure) keep the velocity-based simulation.
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f2146da. Configure here.
- Re-editing a committed note no longer deletes it on Escape: the note is tracked by index, hidden behind its input, and updated in place on commit or left untouched on discard (was spliced out and lost) - Paint the canvas synchronously before the screen grab so the capture can't race the scheduled redraw - Ignore Cmd/Ctrl+Shift+Z so redo doesn't trigger another undo - Reposition an open note input on resize, not just scroll - Hoist the shared pencil path to DRAW_PENCIL_PATH_D (used by the icon + cursor)
edit/comment/copy plugins inline their action id literal; only draw used the DRAW_ACTION_ID constant. Inline "draw" for consistency (the constant stays for the toolbar/core call sites, same as the others).
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 59bc6cb. Configure here.

Summary
Adds a Draw tool to the toolbar that lets you sketch freehand strokes and type text notes anywhere on the page, then copies a WYSIWYG screenshot (drawings included) to the clipboard.
perfect-freehand(consolidated into a single file), pressure-aware, rendered on a fixed overlay canvas.Entercopies the screenshot,Escapediscards in-progress text then exits,Cmd/Ctrl+Zundoes the last action.AnchoredDropdownPanel(also adopted by the existing toolbar menu to kill duplication). Other toolbar actions are locked while Draw owns the screen.getDisplayMedia; the drawing canvas stays visible so the shot is WYSIWYG. User-cancel of the share prompt is treated as a normal action; clipboard failures are logged.Test plan
pnpm typecheck/pnpm lint/pnpm format/pnpm buildcleandraw.spec.ts+toolbar-actions.spec.tse2e pass (27/27)Note
Medium Risk
Draw relies on browser screen-share and clipboard APIs with a large new interaction surface in core keyboard/routing; capture/session handling is hardened but permission UX and cross-browser support remain sensitive.
Overview
Adds a Draw tool so users can sketch freehand strokes and type text notes on the page, then copy a WYSIWYG viewport screenshot (annotations included) to the clipboard via
getDisplayMediaandClipboardItem.Toolbar & API: New Draw button (hidden when screen capture or clipboard image write is unsupported),
DRAW_ACTION_ID,drawPluginwith D shortcut, andapi.draw()toggle. While drawing, copy/comment/style toolbar actions are disabled; Copy/Cancel menu and a tracked Copied toast use a new sharedAnchoredDropdownPanel(toolbar menu refactored onto it). Default toolbar action falls back if Draw was saved as default on an unsupported browser.Draw engine:
createDrawModeControllermounts a full-screen overlay/canvas with vendoredperfect-freehandstrokes, page-anchored geometry on scroll, inline text via a native<input>, undo, and session-safe capture that hides only react-grab chrome for the frame grab.Tests: New
draw.spec.tse2e coverage for toolbar, API, shortcuts, menu, strokes, cancel/escape, undo, and scroll anchoring.Reviewed by Cursor Bugbot for commit 59bc6cb. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Adds a Draw mode to
react-grabso you can sketch freehand and add text notes on the page, then copy a WYSIWYG screenshot with annotations to the clipboard. Draw only appears (andapi.draw()only runs) when screen capture and clipboard‑image write are supported; other tools and selection APIs are blocked while drawing.New Features
perfect-freehand), anchored to page coordinates on scroll/resize; text is edited in a native<input>and flattened on commit; click to re‑edit.api.draw()toggle drawing; exporteddrawPlugin. The default‑action picker filters disabled actions and falls back if Draw was saved as default on an unsupported browser; other toolbar actions are disabled while drawing.Bug Fixes
Written for commit 59bc6cb. Summary will update on new commits.