Compare commits

...
Author SHA1 Message Date
LukeParkerDev 4dcfc0c59c fix(ui): re-measure the scrollbar when its reactive inputs change
The removed effect was also what re-ran updateThumb when
verticalScrollAdjustment, the orientation or the thumb mount changed
(mobile-timeline-scroll e2e). Track those inputs explicitly with a
deferred effect so the resize observer still takes the first measurement.
2026-09-19 00:40:19 +10:00
LukeParkerDev 27111277e0 perf(ui): let the resize observer take the first scrollbar measurement
ScrollView measured the viewport synchronously in onMount and again in
an effect on the thumb mount, forcing a layout per ScrollView while the
page was still rendering (updateThumb was 24 ms of self time in the
desktop's startup renderer profile on the Home route). The resize
observer already reports every target once after layout, including a
thumb mount that appears later, so those measurements were redundant.

Thumb behaviour verified unchanged in the packaged desktop: appears when
the viewport shrinks, tracks scrollTop, disappears when it grows.
2026-09-18 23:38:41 +10:00
+11 -7
View File
@@ -1,4 +1,4 @@
import { createEffect, mergeProps, onCleanup, onMount, Show, splitProps, type ComponentProps } from "solid-js"
import { createEffect, mergeProps, on, onCleanup, onMount, Show, splitProps, type ComponentProps } from "solid-js"
import { Portal } from "solid-js/web"
import { createResizeObserver } from "@solid-primitives/resize-observer"
import { createStore } from "solid-js/store"
@@ -236,18 +236,22 @@ export function ScrollView(props: ScrollViewProps) {
local.viewportRef(viewportRef)
}
// The observer reports every target once when it starts observing (including a thumb mount that
// appears later), after layout. Measuring here as well would force a synchronous layout per
// ScrollView while the page is still rendering.
createResizeObserver(
() => [viewportRef, viewportRef.firstElementChild, thumbMount()].filter(Boolean) as HTMLElement[],
updateThumb,
)
updateThumb()
})
createEffect(() => {
thumbMount()
updateThumb()
})
// Inputs that change the thumb without resizing anything: re-measure on change, but leave the
// first measurement to the observer.
createEffect(
on([() => local.verticalScrollAdjustment, vertical, horizontal, thumbMount], () => updateThumb(), {
defer: true,
}),
)
createEffect(() => {
if (!horizontal() || !viewportRef) return