fix(player): a link that opens the cut text is scrolled back into view
Focus had scrolled the clamped box itself; opened, the link dropped by that much, out of a scrolling panel's sight. DESIGN states where Close sits in the stacked layout; a stale test comment goes.
This commit is contained in:
@@ -65,8 +65,13 @@ describe("ClampedText", () => {
|
||||
// Chrome: 45 px), so on screen the link sits inside the box: only the text's own top tells.
|
||||
clamp.scrollTop = 240;
|
||||
vi.spyOn(screen.getByText("cut"), "getBoundingClientRect").mockReturnValue(rect(130, 150));
|
||||
// Opened, the link drops back to its place in the text, as far as the box had scrolled: in a
|
||||
// scrolling panel that is out of sight, so it is brought back into view.
|
||||
const reveal = vi.fn();
|
||||
screen.getByText("cut").scrollIntoView = reveal;
|
||||
act(() => screen.getByText("cut").focus());
|
||||
expect(screen.getByText("Less").getAttribute("aria-expanded")).toBe("true");
|
||||
expect(reveal).toHaveBeenCalledWith({ block: "nearest" });
|
||||
} finally {
|
||||
tall.mockRestore();
|
||||
box.mockRestore();
|
||||
|
||||
@@ -49,12 +49,22 @@ export function ClampedText({
|
||||
}, [text, expanded]);
|
||||
// Measured from the text's top, not against the box on screen: focus scrolls the clamped box itself
|
||||
// to bring the link into view (overflow:hidden still scrolls), so on screen it looked "in sight".
|
||||
const revealing = useRef<Element | null>(null);
|
||||
const revealFocused = (e: FocusEvent<HTMLDivElement>) => {
|
||||
const box = e.currentTarget;
|
||||
if (expanded || e.target === box) return;
|
||||
const top = box.getBoundingClientRect().top - box.scrollTop;
|
||||
if (e.target.getBoundingClientRect().bottom - top > box.clientHeight + 1) setExpanded(true);
|
||||
if (e.target.getBoundingClientRect().bottom - top <= box.clientHeight + 1) return;
|
||||
revealing.current = e.target;
|
||||
setExpanded(true);
|
||||
};
|
||||
// That scroll was the box's own: opened, the link drops back to its place in the text, as far below
|
||||
// as the box had scrolled, and out of a scrolling panel's sight. Brought back into view.
|
||||
useLayoutEffect(() => {
|
||||
const el = revealing.current;
|
||||
revealing.current = null;
|
||||
if (expanded && el?.isConnected) el.scrollIntoView({ block: "nearest" });
|
||||
}, [expanded]);
|
||||
return (
|
||||
<div className={className}>
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user