Skip to content

feat(chat): pause auto-scroll when user scrolls up, add acp.chat.autoScroll setting#54

Open
body-cmd wants to merge 1 commit into
formulahendry:mainfrom
body-cmd:fix/auto-scroll
Open

feat(chat): pause auto-scroll when user scrolls up, add acp.chat.autoScroll setting#54
body-cmd wants to merge 1 commit into
formulahendry:mainfrom
body-cmd:fix/auto-scroll

Conversation

@body-cmd

Copy link
Copy Markdown

Problem

The ACP Client chat panel forcefully auto-scrolls to the bottom on every
streaming update (agent_message_chunk, tool_call, tool_call_update,
agent_thought_chunk), making it impossible to scroll up and read earlier
content while a response is being generated. This is a well-known UX issue
also reported against Claude Code (#11092, #31496, #58767), VS Code Copilot
Chat (#312626), and others.

Solution

Implements the standard chat-UI auto-scroll pattern:

  • Auto-scroll follows new streaming content by default.
  • When the user manually scrolls up (>80px from bottom), auto-scroll
    pauses.
    The scroll listener tracks user intent — as long as the viewport
    is more than 80px from the bottom, scrollToBottom() is a no-op.
  • Scrolling back to the bottom or sending a new message resumes
    auto-scroll.
  • New VS Code setting acp.chat.autoScroll (default: true) lets users
    disable auto-scroll entirely.

Implementation

The scroll tracking is done in the webview inline JavaScript:

  • userScrolledUp flag tracks scroll position state
  • messagesEl.addEventListener('scroll') updates the flag on every scroll
    event, using the 80px threshold standard from Claude Code and Copilot Chat
  • autoScrollEnabled variable is set from the extension host via the
    state message, using vscode.workspace.getConfiguration()

Testing

  1. Set acp.chat.autoScroll to true (default)
  2. Start a long streaming response
  3. Scroll up while streaming — viewport stays in place
  4. Scroll back to bottom — auto-scroll resumes
  5. Send a new message — auto-scroll resumes even if scrolled up
  6. Set acp.chat.autoScroll to false — no auto-scroll ever occurs

…Scroll setting

Implements the standard chat-UI auto-scroll pattern used by Claude Code, VS
Code Copilot Chat, and other chat interfaces:

- Auto-scroll follows new streaming content by default.
- When the user manually scrolls up (>80px from bottom), auto-scroll pauses.
- Scrolling back to the bottom or sending a new message resumes auto-scroll.
- Add acp.chat.autoScroll setting (default: true) to disable auto-scroll entirely.

Fixes the issue where ACP Client chat forcefully scrolls to the bottom on
every streaming update, making it impossible to read earlier content while
a response is being generated.
Copilot AI review requested due to automatic review settings July 14, 2026 15:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the ACP Client chat webview UX by implementing a standard “pause auto-scroll when the user scrolls up” behavior during streaming responses, and introduces a new acp.chat.autoScroll setting to disable auto-scroll entirely.

Changes:

  • Add acp.chat.autoScroll contributed setting (default true) and send its value to the chat webview via the state message.
  • Update the chat webview’s inline JS to pause scrollToBottom() when the user scrolls up (using an ~80px-from-bottom threshold) and to resume when returning to bottom or sending a new message.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/ui/ChatWebviewProvider.ts Reads acp.chat.autoScroll, forwards it to the webview, and adds scroll-intent tracking to pause/resume auto-scroll.
package.json Contributes the new acp.chat.autoScroll configuration setting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1265 to +1276
function saveState() {
vscode.setState({ chatHistory, sessionState, hasActiveSession });
}

function restoreState() {
const saved = vscode.getState();
if (!saved) return;

chatHistory = saved.chatHistory || [];
sessionState = saved.sessionState || null;
hasActiveSession = saved.hasActiveSession || false;

Comment on lines +1982 to +1984
messagesEl.addEventListener('scroll', function () {
const atBottom = messagesEl.scrollHeight - messagesEl.scrollTop - messagesEl.clientHeight < 80;
if (!atBottom) {
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