Skip to content

vscode: replace top-of-window Quick Pick input for adding review comments from the markdown preview with an inline composer #1107

Description

@amrmelsayed

Problem

Adding a review comment from the Codev Markdown Preview (codev.openMarkdownPreview, shipped in v3.2.0) currently uses vscode.window.showInputBox for the comment body. The input box is rendered in VS Code's center-top Quick Pick chrome — physically far from the block the user clicked + on, which can be anywhere on the page.

The cognitive distance between the block being commented on (the visual anchor for the comment they're writing) and the input they're typing into (always at the top of the window) is the friction. The user has to mentally hold the block's content while typing into a context-less input box; longer comments lose the visual anchor entirely. It's the kind of v1-simplicity choice that's now the dominant slow step in the review flow.

Source

packages/vscode/src/markdown-preview/preview-provider.ts:92-113:

private async addComment(document: vscode.TextDocument, line: number): Promise<void> {
  const text = await vscode.window.showInputBox({
    prompt: 'Add review comment',
    placeHolder: 'Type your review comment, then Enter to submit',
  });
  // ... insert REVIEW marker at markerInsertionLine(line)
}

The webview already posts the line number with the addComment message, so the host knows exactly which block the comment is being added to. The geometry information needed to render the input near the block is fully available — the Quick Pick is just where the v1 implementation landed.

The source-editor Codev: Add Review Comment command (commands/review.ts) does NOT have this problem: it inserts the marker skeleton at the cursor and moves the cursor into the comment, so the user types the body directly in the editor near the block. The friction is preview-pane-specific.

Design options

Three viable approaches, in increasing order of implementation complexity:

Option A: Inline composer rendered by the webview (recommended)

The most physically aligned with the problem. When the user clicks +, the webview itself renders a small editable composer immediately below (or in place of) the + button — same DOM context as the block being commented on, zero physical distance. On submit, the webview posts the body back to the host via the existing onDidReceiveMessage channel, which then writes the marker exactly as it does today.

Pros:

  • Composer lives in the same visual context as the block — anchor is preserved while typing.
  • Reuses the existing webview ↔ host message protocol; no new VS Code API surface.
  • Composer can render with the same prose typography as the preview itself (matches MarkdownView styling shipped in v3.2.1).
  • Supports multi-line input naturally (a textarea, not a single-line input).

Cons:

  • The webview now owns text input state — escape / cancel handling, submit-on-Enter vs newline-on-Enter (with Cmd/Ctrl+Enter to submit), focus restoration on dismiss are all new responsibilities. Several of these are well-trodden patterns.
  • Needs a small DOM component (text area + Submit / Cancel buttons or just Enter / Esc affordances).

Option B: VS Code Comments API thread anchored at the source line

Use vscode.comments.createCommentController to open a native comment thread at the source line being commented on. VS Code renders the thread inline in the source editor, with a native input box at the source location. The preview's + button becomes a deep link into the editor's comment surface.

Pros:

Cons:

  • Forces a context switch from the preview back to the source editor (the input lives in the editor, not the preview).
  • Less compatible with "reading the preview while writing the comment" — the user is no longer looking at the rendered block while typing.

Option C: Floating popup overlay near the + button (lightweight visual fix)

The simplest delta from today: instead of showInputBox, render an absolute-positioned <dialog> or popup-style overlay in the webview anchored near the + button. Still a small input surface but co-located with the click target.

Pros:

  • Smallest implementation delta.
  • Keeps the preview as the focused surface.

Cons:

  • Still essentially the Quick Pick UX, just relocated. Doesn't fully solve "the input feels like a separate context."
  • Z-order / focus / dismissal need careful implementation to feel native.

Recommendation: Option A — inline composer in the webview. It's the only approach that preserves the visual anchor end-to-end (the block stays visible while typing), reuses the message protocol already in place, and composes cleanly with the prose-typography work already shipped in MarkdownView. Option B is the right move if this issue lands in the same cycle as #1055 (Comment system v2), since v2's native lifecycle features want the Comments API surface anyway — but Option B trades off the in-preview reading-while-writing flow that's the dominant comment-authoring posture.

Coordination with #1055

#1055 (Comment system v2) introduces a richer on-disk format with stable IDs, thread membership, and resolved state. If both issues land in the same cycle, the new input surface here should write comments in v2's format (not the current flat <!-- REVIEW(@author): body --> marker). The composer-on-submit path is the only on-disk-write site that needs to change to v2's format — the marker insertion in addComment is co-located with the input UI, so a v2 format change here lands naturally.

If #1055 lands first, this issue updates the composer to emit v2 markers. If this issue lands first, #1055 covers the migration of the existing emitter when v2 ships.

Out of scope

Protocol

PIR. UI / UX-shaped change with a meaningful design decision (which of the three options) that benefits from plan-gate validation before code, plus a running-preview dev-gate to confirm the composer feels right under real usage (cursor handling, escape behaviour, multi-line UX).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/vscodeArea: VS Code extension

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions