fix(chat): limit draft transition animation
This commit is contained in:
@@ -566,6 +566,8 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({
|
||||
// Session UI state
|
||||
const currentSessionId = useSessionUIStore((s) => s.currentSessionId);
|
||||
const currentSessionDirectory = useSessionUIStore((s) => s.currentSessionDirectory);
|
||||
const materializedDraftSessionId = useSessionUIStore((s) => s.materializedDraftSessionId);
|
||||
const clearMaterializedDraftSession = useSessionUIStore((s) => s.clearMaterializedDraftSession);
|
||||
const openNewSessionDraft = useSessionUIStore((s) => s.openNewSessionDraft);
|
||||
const setCurrentSession = useSessionUIStore((s) => s.setCurrentSession);
|
||||
const newSessionDraft = useSessionUIStore((s) => s.newSessionDraft);
|
||||
@@ -1107,8 +1109,11 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({
|
||||
const previousDraftOpenRef = React.useRef(draftOpen);
|
||||
const previousDraftLayoutVisibleRef = React.useRef(draftOpen);
|
||||
const [draftExitAnimating, setDraftExitAnimating] = React.useState(false);
|
||||
const shouldAnimateDraftTransition = Boolean(
|
||||
currentSessionId && materializedDraftSessionId === currentSessionId,
|
||||
);
|
||||
const draftPresentationExiting = draftExitAnimating
|
||||
|| (previousDraftOpenRef.current && !draftOpen && Boolean(currentSessionId));
|
||||
|| (previousDraftOpenRef.current && !draftOpen && shouldAnimateDraftTransition);
|
||||
const draftLayoutVisible = draftOpen || draftPresentationExiting;
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
@@ -1116,12 +1121,12 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({
|
||||
setDraftExitAnimating(false);
|
||||
return;
|
||||
}
|
||||
if (!previousDraftOpenRef.current || !currentSessionId) return;
|
||||
if (!previousDraftOpenRef.current || !shouldAnimateDraftTransition) return;
|
||||
|
||||
setDraftExitAnimating(true);
|
||||
const timeoutId = window.setTimeout(() => setDraftExitAnimating(false), DRAFT_EXIT_DURATION_MS);
|
||||
return () => window.clearTimeout(timeoutId);
|
||||
}, [currentSessionId, draftOpen]);
|
||||
}, [draftOpen, shouldAnimateDraftTransition]);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
previousDraftOpenRef.current = draftOpen;
|
||||
@@ -1139,7 +1144,8 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({
|
||||
&& Boolean(currentSessionId);
|
||||
const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
|
||||
|
||||
if (leftDraftLayout && previousRect && !reduceMotion && !useCompactDraftLayout && !isDesktopExpandedInput) {
|
||||
const shouldMoveComposer = leftDraftLayout && shouldAnimateDraftTransition;
|
||||
if (shouldMoveComposer && previousRect && !reduceMotion && !useCompactDraftLayout && !isDesktopExpandedInput) {
|
||||
const deltaX = previousRect.left - currentRect.left;
|
||||
const deltaY = previousRect.top - currentRect.top;
|
||||
composerSlot.animate(
|
||||
@@ -1150,10 +1156,19 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({
|
||||
{ duration: COMPOSER_MOVE_DURATION_MS, easing: 'cubic-bezier(0.22, 1, 0.36, 1)' },
|
||||
);
|
||||
}
|
||||
|
||||
previousComposerRectRef.current = currentRect;
|
||||
previousDraftLayoutVisibleRef.current = draftLayoutVisible;
|
||||
}, [currentSessionId, draftLayoutVisible, isDesktopExpandedInput, useCompactDraftLayout]);
|
||||
if (leftDraftLayout && currentSessionId) {
|
||||
clearMaterializedDraftSession(currentSessionId);
|
||||
}
|
||||
}, [
|
||||
clearMaterializedDraftSession,
|
||||
currentSessionId,
|
||||
draftLayoutVisible,
|
||||
isDesktopExpandedInput,
|
||||
shouldAnimateDraftTransition,
|
||||
useCompactDraftLayout,
|
||||
]);
|
||||
|
||||
if (!currentSessionId && !draftOpen) {
|
||||
// The auto-open effect runs on the next tick. Use a neutral background
|
||||
|
||||
@@ -11,7 +11,9 @@ belongs to one of them.
|
||||
becomes its first session. Draft-only UI first fades for 120ms while the editor
|
||||
stays in place. The parent then moves the editor to its final session position
|
||||
with a 180ms transform-only FLIP animation. Reduced-motion mode skips these
|
||||
transitions. Do not restore separate draft and session composer branches:
|
||||
transitions. `session-ui-store.ts` marks sessions materialized from a submitted
|
||||
draft, so selecting an existing session while a draft is open switches without
|
||||
animation. Do not restore separate draft and session composer branches:
|
||||
remounting the editor loses focus and interrupts the transition. Keep the
|
||||
existing mobile fixed-position rules unchanged.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user