Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/web/src/components/ComposerPromptEditorTiptap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,7 @@ function ComposerPromptEditorTiptapInner(props: ComposerPromptEditorProps) {
<ComposerContextRecordsContext value={contextRecords}>
<ComposerCitationCommentContext value={citationCommentActions}>
<div
data-chat-composer-transition-prompt="true"
className={cn(
"relative flow-root [font-family:var(--font-composer,var(--font-sans))] [font-size:var(--font-size-prompt,0.875rem)] [@media(max-width:39.999rem)_and_(pointer:coarse)]:[font-size:max(var(--font-size-prompt,1rem),16px)]",
containerClassName,
Expand Down
37 changes: 22 additions & 15 deletions apps/web/src/components/chat/ChatComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,13 @@ const COMPOSER_RESTING_TRANSITION_CLEANUP_BUFFER_MS = 50;
const COMPOSER_RESTING_TRANSITION_EASING = "cubic-bezier(0.32, 0.72, 0, 1)";
const COMPOSER_RESTING_CONTROLS_ARRIVAL_DRIFT_PX = 4;

function composerPromptLineCenter(prompt: HTMLElement): number {
const rect = prompt.getBoundingClientRect();
const lineSource = prompt.querySelector<HTMLElement>('[data-testid="composer-editor"]') ?? prompt;
const lineHeight = Number.parseFloat(getComputedStyle(lineSource).lineHeight);
return rect.top + (Number.isFinite(lineHeight) ? lineHeight / 2 : rect.height / 2);
}

function useComposerRestingTransition(
isCollapsed: boolean,
isResting: boolean,
Expand Down Expand Up @@ -469,15 +476,12 @@ function useComposerRestingTransition(
Array.from(element.querySelectorAll<HTMLElement>(selector)).find(
(candidate) => candidate.getClientRects().length > 0,
) ?? null;
const prompt = visibleTransitionElement(
'[data-testid="composer-editor"], [data-chat-composer-transition-prompt="true"]',
);
const prompt = visibleTransitionElement('[data-chat-composer-transition-prompt="true"]');
const action = visibleTransitionElement('[data-chat-composer-transition-actions="true"]');
const footer = element.querySelector<HTMLElement>('[data-chat-composer-footer="true"]');
const interruptedAnimation = animationRef.current;
const interruptedPromptTop = interruptedAnimation
? (prompt?.getBoundingClientRect().top ?? null)
: null;
const interruptedPromptTop =
interruptedAnimation && prompt ? composerPromptLineCenter(prompt) : null;
const interruptedActionTop = interruptedAnimation
? (action?.getBoundingClientRect().top ?? null)
: null;
Expand Down Expand Up @@ -520,7 +524,7 @@ function useComposerRestingTransition(
onOverlayHeightChange(overlayHeight);
}
const nextPromptRect = prompt?.getBoundingClientRect() ?? null;
const nextPromptTop = nextPromptRect?.top ?? null;
const nextPromptTop = prompt ? composerPromptLineCenter(prompt) : null;
const nextActionTop = action?.getBoundingClientRect().top ?? null;
const previousHeight = interruptedHeight ?? previousHeightRef.current;
const targetChanged =
Expand Down Expand Up @@ -602,9 +606,10 @@ function useComposerRestingTransition(
const animateContentPosition = (
content: HTMLElement | null,
previousTop: number | null,
measureTop: (content: HTMLElement) => number,
) => {
if (!content || previousTop === null) return;
const offset = previousTop - content.getBoundingClientRect().top;
const offset = Math.round(previousTop - measureTop(content));
if (Math.abs(offset) < 0.5) return;
contentAnimations.push(
content.animate(
Expand All @@ -616,8 +621,12 @@ function useComposerRestingTransition(
),
);
};
animateContentPosition(prompt, previousPromptTop);
animateContentPosition(action, previousActionTop);
animateContentPosition(prompt, previousPromptTop, composerPromptLineCenter);
animateContentPosition(
action,
previousActionTop,
(content) => content.getBoundingClientRect().top,
);
contentAnimationsRef.current = contentAnimations;

if (stateChanged) {
Expand Down Expand Up @@ -798,16 +807,14 @@ function useComposerRestingTransition(
Array.from(element.querySelectorAll<HTMLElement>(selector)).find(
(candidate) => candidate.getClientRects().length > 0,
) ?? null;
const promptRect = visibleTransitionElement(
'[data-testid="composer-editor"], [data-chat-composer-transition-prompt="true"]',
)?.getBoundingClientRect();
const prompt = visibleTransitionElement('[data-chat-composer-transition-prompt="true"]');
const actionTop = visibleTransitionElement(
'[data-chat-composer-transition-actions="true"]',
)?.getBoundingClientRect().top;
previousHeightRef.current = elementRect.height;
previousContentOffsetsRef.current = {
promptFromTop: promptRect === undefined ? null : promptRect.top - elementRect.top,
promptHeight: promptRect?.height ?? null,
promptFromTop: prompt ? composerPromptLineCenter(prompt) - elementRect.top : null,
promptHeight: prompt?.getBoundingClientRect().height ?? null,
actionFromBottom: actionTop === undefined ? null : elementRect.bottom - actionTop,
};
});
Expand Down
Loading