Center current chapter in drawer on open
Chapter drawer now opens with the active row pre-scrolled to the center of the list instead of always starting at chapter #1. useLayoutEffect measures via getBoundingClientRect so the scroll lands before paint — no visible jump. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
43a2a6d3f8
commit
cad59143a3
@ -86,6 +86,8 @@ export function PageReader({
|
|||||||
const pageElRef = useRef<Map<string, HTMLDivElement>>(new Map());
|
const pageElRef = useRef<Map<string, HTMLDivElement>>(new Map());
|
||||||
const observerRef = useRef<IntersectionObserver | null>(null);
|
const observerRef = useRef<IntersectionObserver | null>(null);
|
||||||
const hiddenByScrollRef = useRef(false);
|
const hiddenByScrollRef = useRef(false);
|
||||||
|
const drawerScrollRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const drawerActiveRef = useRef<HTMLAnchorElement | null>(null);
|
||||||
// Pages currently inside the observer's viewport margin. The scroll tick
|
// Pages currently inside the observer's viewport margin. The scroll tick
|
||||||
// walks this small set instead of every loaded page.
|
// walks this small set instead of every loaded page.
|
||||||
const intersectingPagesRef = useRef<Map<string, IntersectingPage>>(new Map());
|
const intersectingPagesRef = useRef<Map<string, IntersectingPage>>(new Map());
|
||||||
@ -322,6 +324,21 @@ export function PageReader({
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (!showDrawer) return;
|
||||||
|
const scroll = drawerScrollRef.current;
|
||||||
|
const active = drawerActiveRef.current;
|
||||||
|
if (!scroll || !active) return;
|
||||||
|
const scrollRect = scroll.getBoundingClientRect();
|
||||||
|
const activeRect = active.getBoundingClientRect();
|
||||||
|
const delta =
|
||||||
|
activeRect.top -
|
||||||
|
scrollRect.top -
|
||||||
|
scroll.clientHeight / 2 +
|
||||||
|
active.clientHeight / 2;
|
||||||
|
scroll.scrollTop = Math.max(0, scroll.scrollTop + delta);
|
||||||
|
}, [showDrawer]);
|
||||||
|
|
||||||
const currentChapter =
|
const currentChapter =
|
||||||
chapters.find((c) => c.number === currentChapterNum) ??
|
chapters.find((c) => c.number === currentChapterNum) ??
|
||||||
chapters.find((c) => c.number === startChapterNumber);
|
chapters.find((c) => c.number === startChapterNumber);
|
||||||
@ -474,12 +491,16 @@ export function PageReader({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-y-auto max-h-[calc(75vh-4rem)] pb-safe">
|
<div
|
||||||
|
ref={drawerScrollRef}
|
||||||
|
className="overflow-y-auto max-h-[calc(75vh-4rem)] pb-safe"
|
||||||
|
>
|
||||||
{chapters.map((ch) => {
|
{chapters.map((ch) => {
|
||||||
const isActive = ch.number === currentChapterNum;
|
const isActive = ch.number === currentChapterNum;
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
key={ch.number}
|
key={ch.number}
|
||||||
|
ref={isActive ? drawerActiveRef : undefined}
|
||||||
href={`/manga/${mangaSlug}/${ch.number}`}
|
href={`/manga/${mangaSlug}/${ch.number}`}
|
||||||
scroll={false}
|
scroll={false}
|
||||||
className={`flex items-center gap-3 px-5 py-3 text-sm transition-colors ${
|
className={`flex items-center gap-3 px-5 py-3 text-sm transition-colors ${
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user