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:
@@ -424,8 +424,6 @@ describe("PlayerModal — the description", () => {
|
||||
});
|
||||
});
|
||||
|
||||
// C3: the queue's side arrows sit in a gutter of the card's row, not outside it, so no window cuts
|
||||
// them off (outside the card, a 1024 window cut them and a portrait tablet lost them).
|
||||
// The full-height strips beside the card were a second Previous / Next that cost the video 7rem of
|
||||
// width (owner): the panel's transport row and Shift+← / → step on their own.
|
||||
describe("PlayerModal — no side strips", () => {
|
||||
|
||||
@@ -671,8 +671,8 @@ export default function PlayerModal({
|
||||
// The card's width budget (its maxWidth, below): the video's, and the side panel's when wide.
|
||||
const fitWidth = `(100dvh - 3rem - ${below}px) * 16 / 9`;
|
||||
const panelWidth = panelShut ? PANEL_STRIP : SIDE_PANEL;
|
||||
// One Close, icon only, in the card's top-right corner: the wide panel's head (or its strip), the
|
||||
// stacked card's title row.
|
||||
// One Close, icon only: at the top right of the wide panel's head (or its strip), at the end of the
|
||||
// stacked card's title row under the video.
|
||||
const closeButton = (
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
|
||||
@@ -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