mirror of
https://github.com/ohwgiles/laminar.git
synced 2026-09-23 04:20:41 +00:00
Add sticky auto-scroll for build output
Implements #220 - if the page is scrolled to the very bottom while a build log is streaming, the scroll position "sticks" there and follows new output as it is rendered, like tail -f. Any upward scroll disengages this behaviour, and scrolling back to the bottom re-engages it, so no toggle button is needed. The sticky state is tracked with wheel/scroll event listeners rather than sampled from window.scrollY at render time, because scrolling is handled outside the main thread: while the main thread is busy rendering a large log chunk, window.scrollY may still report the old (bottom) position, which would wrongly yank the page back down and swallow the user's upward scroll. AI-assisted implementation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -669,6 +669,23 @@ const Run = templateId => {
|
||||
latestNum: null,
|
||||
logComplete: false,
|
||||
};
|
||||
// if the page is scrolled to the bottom, the scroll position "sticks"
|
||||
// there and follows new log output as it is rendered, like tail -f.
|
||||
// Any upward scroll disengages this, scrolling back to the bottom
|
||||
// re-engages it. This must be tracked with event listeners rather than
|
||||
// sampled when rendering, because scrolling is handled outside the main
|
||||
// thread: while the main thread is busy rendering a large log chunk,
|
||||
// window.scrollY may still report the old (bottom) position, which
|
||||
// would wrongly yank the page back down and swallow the user's scroll.
|
||||
let stickToBottom = true;
|
||||
window.addEventListener('wheel', evt => {
|
||||
if (evt.deltaY < 0)
|
||||
stickToBottom = false;
|
||||
});
|
||||
window.addEventListener('scroll', () => {
|
||||
stickToBottom = window.innerHeight + window.scrollY >=
|
||||
document.documentElement.scrollHeight - 1;
|
||||
});
|
||||
const logFetcher = (vm, name, num) => {
|
||||
const abort = new AbortController();
|
||||
fetch('log/'+name+'/'+num, {signal:abort.signal}).then(res => {
|
||||
@@ -705,6 +722,9 @@ const Run = templateId => {
|
||||
state.logComplete = true;
|
||||
}
|
||||
|
||||
if (stickToBottom)
|
||||
window.scrollTo(0, document.documentElement.scrollHeight);
|
||||
|
||||
lastUiUpdate = Date.now();
|
||||
tid = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user