Skip to content

feat(react): keep the pending-replacement preview beside the text it previews#212

Merged
ocavue merged 5 commits into
prosekit:masterfrom
maccman:ai-preview-ux
Jul 4, 2026
Merged

feat(react): keep the pending-replacement preview beside the text it previews#212
ocavue merged 5 commits into
prosekit:masterfrom
maccman:ai-preview-ux

Conversation

@maccman

@maccman maccman commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Problem

Two UX issues with the pending-replacement preview (the AI-transform popover):

  1. The popover detaches from long selections. It was anchored to the staged range's bounding box. A selection taller than the viewport leaves no room on either side of that box, so Floating UI's collision handling flung the popover to the top of the viewport — floating over unrelated UI and covering the selection mid-range:

    Before (tall selection) After
    Popover pinned at viewport top, over the page header Popover beside the last line of the selection
  2. "Accept" didn't say what it does. Whether accepting replaces the selection or inserts below it depends on the staged mode, which the button didn't surface.

Changes

  • Anchor the popover to the end caret of the staged range instead of its bounding box, so collision handling degrades gracefully.
  • When a stage starts, scroll the anchor line into view with enough clearance (PREVIEW_CLEARANCE) for the popover to stream below it — centering first, then nudging the nearest scrollable ancestor. Keyed on stage existence, so streamed text, range remaps, and retries never re-scroll.
  • Label the accept control by what accepting does: "Replace selection" or "Insert below", per the staged mode.
  • The website demo's actions slot now offers the opposite placement (like a real host would), instead of always "Insert below", which duplicated the CTA on append-mode runs.

Testing

  • pnpm vitest --run --project '@meowdown/react (chromium)' — 150 tests pass, including a new test asserting the mode-dependent accept label.
  • Verified in the website playground: small selections (popover below the selection end), selections taller than the viewport (scrolls to make room, popover beside the last line), append-mode runs ("Insert below" CTA), and the no-room-left degenerate case (popover flips to directly above the anchor line).
  • pnpm typecheck and pnpm lint pass.

🤖 Generated with Claude Code

…previews

The preview popover was anchored to the staged range's bounding box. A
selection taller than the viewport leaves no room on either side of that
box, so collision handling flung the popover to the top of the viewport,
detached from the text and overlapping the selection mid-range.

Anchor it to the end of the staged range instead, and scroll that line
into view with enough clearance below when a stage starts, so the
popover opens by the last line of the selection with room to stream.

Also label the accept control by what accepting does — "Replace
selection" or "Insert below" per the staged mode — instead of an
ambiguous "Accept", and let the website demo offer the opposite
placement like a real host.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

@maccman is attempting to deploy a commit to the ocavue's projects Team on Vercel.

A member of the Team first needs to authorize it.

@pkg-pr-new

pkg-pr-new Bot commented Jul 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/prosekit/meowdown/@meowdown/core@212
npm i https://pkg.pr.new/prosekit/meowdown/@meowdown/react@212

commit: 2294054

The mode-labeled accept button made the footer overflow the 24rem popup,
wrapping button labels mid-word. Widen the popover to 30rem, mark the
footer buttons nowrap, and let whole buttons wrap onto a second row when
a narrow viewport leaves no room.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@maccman

maccman commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up commit: the mode-labeled accept button made the footer overflow the 24rem popup and wrap labels mid-word. Widened the popover to 30rem, made footer buttons white-space: nowrap, and added flex-wrap so whole buttons flow to a second row in viewports too narrow for one line. Verified at 900px and 400px widths.

@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
meowdown Ready Ready Preview, Comment Jul 4, 2026 9:13am

@ocavue

ocavue commented Jul 2, 2026

Copy link
Copy Markdown
Member

@ocavue ocavue merged commit 4a13499 into prosekit:master Jul 4, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants