Skip to content

fix(chat): keep auto-scroll pinned while streaming - #174

Merged
actus7 merged 1 commit into
mainfrom
fix/chat-autoscroll-stick
Jul 30, 2026
Merged

fix(chat): keep auto-scroll pinned while streaming#174
actus7 merged 1 commit into
mainfrom
fix/chat-autoscroll-stick

Conversation

@actus7

@actus7 actus7 commented Jul 30, 2026

Copy link
Copy Markdown
Owner

@

Contexto

Sequência de tentativas anteriores no scroll do chat (#171, #172, #173) atacou o thumb do Radix ScrollArea. O #173 removeu o Radix da área de mensagens e passou a usar scroll nativo — isso resolve a classe de bug do thumb desenhado em JS.

Este PR corrige um segundo bug, independente, que sobrevive à troca por scroll nativo: o auto-scroll desligava sozinho durante o streaming.

Causa raiz

O handler de scroll decidia "usuário rolou para cima" só pela distância até o fundo:

const distFromBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
userScrolledUpRef.current = distFromBottom > 100;

Essa distância aumenta em dois casos distintos:

  1. o usuário rola para cima — deve descolar do fundo;
  2. o conteúdo cresce durante o streaming — não deve descolar.

O código tratava os dois igual. Qualquer render que adicionasse mais de 100px de uma vez (bloco de código destacado, tabela, KaTeX) marcava "rolou para cima" e o chat parava de acompanhar no meio da resposta. Pior: a escrita programática viewport.scrollTop = viewport.scrollHeight dispara scroll, realimentando o próprio handler — daí os saltos.

Correção

Só uma redução real de scrollTop descola. Crescimento de conteúdo não mexe em scrollTop, então não descola mais. Chegar ao fundo recola, então o estado se auto-corrige e não trava em nenhum dos dois lados.

A decisão virou função pura (resolveStickToBottom) em lib/chat-utils.ts, testável sem DOM.

Test plan

  • pnpm test — 333 passam, 1 skip
  • 5 testes novos para resolveStickToBottom, incluindo o caso de regressão (conteúdo cresce 400px, scrollTop parado → continua colado)
  • pnpm typecheck limpo
  • pnpm lint — 0 erros (1 warning pré-existente em last-ndc.ts, não relacionado)
  • Manual: enviar prompt longo com bloco de código e confirmar que o chat acompanha até o fim
  • Manual: rolar para cima durante o streaming e confirmar que ele para de acompanhar
  • Manual: rolar de volta ao fim e confirmar que volta a acompanhar

Nota sobre produção

O #173 (scroll nativo) entrou no main às 13:01. Se o teste em produção foi feito antes desse deploy subir, o que se via ainda era o thumb do Radix. Vale revalidar prod já com o #173 + este PR antes de concluir que o sintoma persiste.

🤖 Generated with Claude Code
@

fix(chat): keep auto-scroll pinned while streaming

O handler de `scroll` decidia se o usuário havia rolado para cima apenas
pela distância até o fundo. Durante o streaming o conteúdo cresce sem que
o usuário toque na barra, e essa mesma distância aumenta — então qualquer
render que adicionasse mais de 100px (bloco de código, tabela, KaTeX)
marcava "usuário rolou para cima" e o auto-scroll desligava no meio da
resposta. A escrita programática de `scrollTop` também realimentava o
próprio handler, produzindo saltos.

Passa a distinguir os dois casos: só uma redução real de `scrollTop`
descola do fundo; crescimento de conteúdo não. Voltar ao fundo recola,
então o estado se auto-corrige. A decisão vira uma função pura em
lib/chat-utils para poder ser testada.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@
Copilot AI review requested due to automatic review settings July 30, 2026 16:18
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
modelhub Ready Ready Preview Jul 30, 2026 4:19pm

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added frontend Frontend changes backend Backend changes tests Test changes labels Jul 30, 2026
@actus7
actus7 merged commit f6909f3 into main Jul 30, 2026
12 checks passed
@actus7
actus7 deleted the fix/chat-autoscroll-stick branch July 30, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Backend changes frontend Frontend changes tests Test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants