Skip to content

Commit 939ad6a

Browse files
committed
fix: use useLayoutEffect for initial scroll to fix Chromatic snapshots
The scroll-to-bottom when workspace loads was using useEffect with requestAnimationFrame, which runs asynchronously after browser paint. Chromatic could capture the snapshot before scroll completed. Switch to useLayoutEffect which runs synchronously after DOM mutations but before paint, ensuring scroll happens before Chromatic captures. This also removes the need for the RAF wrapper since useLayoutEffect already guarantees DOM is ready.
1 parent 1fb531e commit 939ad6a

File tree

1 file changed

+5
-6
lines changed

1 file changed

+5
-6
lines changed

src/browser/components/AIView.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useCallback, useEffect, useRef } from "react";
1+
import React, { useState, useCallback, useEffect, useLayoutEffect, useRef } from "react";
22
import { cn } from "@/common/lib/utils";
33
import { MessageRenderer } from "./Messages/MessageRenderer";
44
import { InterruptedBarrier } from "./Messages/ChatBarrier/InterruptedBarrier";
@@ -262,12 +262,11 @@ const AIViewInner: React.FC<AIViewProps> = ({
262262
]);
263263

264264
// Scroll to bottom when workspace loads or changes
265-
useEffect(() => {
265+
// useLayoutEffect ensures scroll happens synchronously after DOM mutations
266+
// but before browser paint - critical for Chromatic snapshot consistency
267+
useLayoutEffect(() => {
266268
if (workspaceState && !workspaceState.loading && workspaceState.messages.length > 0) {
267-
// Give React time to render messages before scrolling
268-
requestAnimationFrame(() => {
269-
jumpToBottom();
270-
});
269+
jumpToBottom();
271270
}
272271
// eslint-disable-next-line react-hooks/exhaustive-deps
273272
}, [workspaceId, workspaceState?.loading]);

0 commit comments

Comments
 (0)