Perf/UI performance (#473)

* perf(ui): defer off-screen Artist grid paint + rAF overlay scrollbar

Apply content-visibility to artist tiles in .album-grid-wrap (aligned with
album cards). Coalesce OverlayScrollArea thumb updates to one requestAnimationFrame per scroll burst.

* perf(css): content-visibility on horizontal artist rails

Apply the same off-screen deferral as album cards to `.album-grid .artist-card`
(ArtistRow, Favorites, etc.).
This commit is contained in:
cucadmuh
2026-05-06 10:45:13 +03:00
committed by GitHub
parent de3c0d9da1
commit 5abe18d5b8
2 changed files with 29 additions and 1 deletions
+18 -1
View File
@@ -60,6 +60,8 @@ export default function OverlayScrollArea({
const perfFlags = usePerfProbeFlags();
const wrapRef = useRef<HTMLDivElement | null>(null);
const viewportRef = useRef<HTMLDivElement | null>(null);
/** Coalesce burst scroll events to one thumb update per animation frame. */
const scrollRecomputeRafRef = useRef(0);
const [meta, setMeta] = useState({ thumbH: 0, thumbT: 0, visible: false });
const recompute = useCallback(() => {
@@ -71,6 +73,21 @@ export default function OverlayScrollArea({
setMeta(computeOverlayScrollbarThumbMeta(vp, trackH));
}, []);
const scheduleScrollRecompute = useCallback(() => {
if (scrollRecomputeRafRef.current !== 0) return;
scrollRecomputeRafRef.current = requestAnimationFrame(() => {
scrollRecomputeRafRef.current = 0;
recompute();
});
}, [recompute]);
useEffect(() => () => {
if (scrollRecomputeRafRef.current !== 0) {
cancelAnimationFrame(scrollRecomputeRafRef.current);
scrollRecomputeRafRef.current = 0;
}
}, []);
const measureKey = JSON.stringify(measureDeps ?? []);
useLayoutEffect(() => {
@@ -138,7 +155,7 @@ export default function OverlayScrollArea({
id={viewportId}
ref={setViewportNode}
className={viewportClass}
onScroll={perfFlags.disableOverlayScrollbars ? undefined : recompute}
onScroll={perfFlags.disableOverlayScrollbars ? undefined : scheduleScrollRecompute}
onWheel={viewportOnWheel}
onTouchMove={viewportOnTouchMove}
>
+11
View File
@@ -401,6 +401,12 @@
contain-intrinsic-size: 0 220px;
}
/* Same wrap as Albums grid; defer layout/paint for off-screen artist tiles (helps scroll on WebKit/Linux). */
.album-grid-wrap > .artist-card {
content-visibility: auto;
contain-intrinsic-size: 0 220px;
}
@media (min-width: 1024px) {
.album-grid-wrap {
@@ -420,6 +426,11 @@
contain-intrinsic-size: 0 240px;
}
.album-grid .artist-card {
content-visibility: auto;
contain-intrinsic-size: 0 240px;
}
.album-card-more {
flex: 0 0 clamp(140px, 15vw, 180px);
display: flex;