fix: chat auto-scroll is fragile in chromium environments#820
fix: chat auto-scroll is fragile in chromium environments#820danjrwalsh wants to merge 3 commits intostoatchat:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request addresses a Chromium-specific bug where chat auto-scroll functionality breaks frequently during regular usage. The issue affects both browser and Electron desktop environments. The fix adds a scroll event listener and ResizeObserver to maintain scroll position at the bottom when new messages arrive, working around apparent CSS rendering issues in Chromium's handling of column-reverse flex layouts.
Changes:
- Adds scroll tracking via event listener to detect when user is at the bottom
- Implements ResizeObserver to snap scroll position back to bottom when content resizes
- Introduces state management for scroll position tracking and suppression during manual DOM updates
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Dan Walsh <dan@danwalsh.ca>
45a0ae1 to
e3ddb1a
Compare
I have tested it both on Chrome and in the dev client and had it happen there as well, feels a lot more consistent but still had issues with it loosing scroll, you should try interact with messages, replies and check profiles it's very random but still happens happens that it looses scroll |
I did try a bunch of regular actions like that yesterday when using it over a period of a couple hours but I guess I just got lucky. Chances are it's just the threshold though, it's only set to 1px currently, increasing it would likely catch those remaining scenarios you ran into. I'll play around with the threshold after work and see if I can find a sweet spot. |
Signed-off-by: Dan Walsh <dan@danwalsh.ca>
|
@mihaicm93 I didn't have much time today but tried going a slightly different approach that I think will be more reliable + provide a better UX. Instead of having a static threshold, it's now checking if the last message was visible (including partially) by comparing bounding rects and if so, keeping the auto-scrolling engaged. So now auto-scroll should continue working unless you explicitly move the most recent message completely out of bounds (I also added a mutation observer so it only takes into account explicit user scrolls). Give it a test on your side when you have a moment and let me know what you think. It's a more "aggressive" way of handling it, but covers more edge cases. If you think it's a bit too aggressive and doesn't release auto-scroll early enough, I can revert back to the static threshold approach and simply increase the threshold (30-50px felt best in my testing, but that could be subjective). |
Potential fix for #660 and #700
In Chromium environments (including Electron, so this affects the desktop apps too), I've found the existing auto-scroll to be quite fragile, breaking fairly often (multiple times an hour) from regular usage. Every time it happens, it requires switching chat channels or pressing
Esca couple times to get it functioning again. It's a minor nuisance, but it does get frustrating. I was unable to reproduce the issue on Firefox, which is why I'm assuming this is a Chromium specific issue.To get around what appears to be a CSS issue on Chromium, I've added a scroll event listener and ResizeObserver that will keep the chat history snapped to the bottom when applicable.
I've been running this locally side-by-side the current prod for the last couple hours and I've yet to experience auto scroll break on me once, whereas prod has lost auto scroll 4 times.
Live example of the two instances side-by-side (in Brave browser), mimicking actions (left prod, right local). You can see prod lost auto scroll (scrolling back down does not re-engage the scrolling).

Current threshold is set to 1 pixel, but can be adjusted as needed.
NOTE: While I have tested this in a browser environment, I have not tested this inside a local Electron instance.
Feedback is welcome, this is my first contribution to both Stoat and a Solid.js project in general (more of a Vue/Nuxt guy).