| ... | @@ -5220,6 +5220,19 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -5220,6 +5220,19 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 5220 | useLayoutEffect(() => { | 5220 | useLayoutEffect(() => { |
| 5221 | onRestingChange(isComposerResting); | 5221 | onRestingChange(isComposerResting); |
| 5222 | }, [isComposerResting, onRestingChange]); | 5222 | }, [isComposerResting, onRestingChange]); |
| | 5223 | // The resting footer floats over the prompt row, so the row reserves its |
| | 5224 | // measured width. Wide actions like the compact-before-send chip vary too much for a fixed inset. |
| | 5225 | const [restingActionsElement, setRestingActionsElement] = useState<HTMLDivElement | null>(null); |
| | 5226 | const [restingActionsWidth, setRestingActionsWidth] = useState<number | null>(null); |
| | 5227 | useLayoutEffect(() => { |
| | 5228 | if (!isComposerResting || !restingActionsElement) return; |
| | 5229 | const measure = () => setRestingActionsWidth(restingActionsElement.offsetWidth); |
| | 5230 | measure(); |
| | 5231 | if (typeof ResizeObserver === "undefined") return; |
| | 5232 | const observer = new ResizeObserver(measure); |
| | 5233 | observer.observe(restingActionsElement); |
| | 5234 | return () => observer.disconnect(); |
| | 5235 | }, [isComposerResting, restingActionsElement]); |
| 5223 | const restingImagePreviewCounts = getRestingComposerImagePreviewCounts( | 5236 | const restingImagePreviewCounts = getRestingComposerImagePreviewCounts( |
| 5224 | standaloneComposerImages.length, | 5237 | standaloneComposerImages.length, |
| 5225 | ); | 5238 | ); |
| ... | @@ -7376,17 +7389,12 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -7376,17 +7389,12 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 7376 | )} | 7389 | )} |
| 7377 | | 7390 | |
| 7378 | <div | 7391 | <div |
| 7379 | className={cn( | 7392 | className={cn("relative", isComposerResting && "flex min-w-0 items-center gap-1")} |
| 7380 | "relative", | 7393 | style={ |
| 7381 | isComposerResting && "flex min-w-0 items-center gap-1", | 7394 | isComposerResting && restingActionsWidth !== null |
| 7382 | isComposerResting && | 7395 | ? { paddingRight: `calc(${restingActionsWidth}px + 1rem)` } |
| 7383 | ((settings.contextWindowMeterEnabled && activeContextWindow) || | 7396 | : undefined |
| 7384 | reserveContextWindowMeter | 7397 | } |
| 7385 | ? "pr-28" | | |
| 7386 | : showComposerAttachAction | | |
| 7387 | ? "pr-20" | | |
| 7388 | : "pr-12"), | | |
| 7389 | )} | | |
| 7390 | > | 7398 | > |
| 7391 | {previewFile ? ( | 7399 | {previewFile ? ( |
| 7392 | <Dialog | 7400 | <Dialog |
| ... | @@ -7565,6 +7573,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -7565,6 +7573,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 7565 | | 7573 | |
| 7566 | {/* Right side: send / stop button */} | 7574 | {/* Right side: send / stop button */} |
| 7567 | <div | 7575 | <div |
| | 7576 | ref={setRestingActionsElement} |
| 7568 | data-chat-composer-actions="right" | 7577 | data-chat-composer-actions="right" |
| 7569 | data-chat-composer-transition-actions="true" | 7578 | data-chat-composer-transition-actions="true" |
| 7570 | data-chat-composer-primary-actions-compact={ | 7579 | data-chat-composer-primary-actions-compact={ |