Skip to content

Commit 727515a

Browse files
committed
Fix #5236: Resolve ChatView layout shifting and inconsistent spacing
- Standardize AutoApproveMenu positioning with flex-shrink-0 class for both task and no-task states - Replace custom scroll-to-bottom button styling with standard VSCodeButton component - Add consistent spacing with fixed padding in action button areas - Eliminate layout shifts caused by different CSS classes between states
1 parent 3a8ba27 commit 727515a

File tree

1 file changed

+79
-74
lines changed

1 file changed

+79
-74
lines changed

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 79 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
14471447
// but becomes scrollable when the viewport is too small
14481448
*/}
14491449
{!task && (
1450-
<div className="mb-[-2px] flex-initial min-h-0">
1450+
<div className="flex-shrink-0">
14511451
<AutoApproveMenu />
14521452
</div>
14531453
)}
@@ -1474,86 +1474,91 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
14741474
initialTopMostItemIndex={groupedMessages.length - 1}
14751475
/>
14761476
</div>
1477-
<AutoApproveMenu />
1478-
{showScrollToBottom ? (
1479-
<div className="flex px-[15px] pt-[10px]">
1477+
{/* Fixed positioning for AutoApproveMenu to prevent layout shifts */}
1478+
<div className="flex-shrink-0">
1479+
<AutoApproveMenu />
1480+
</div>
1481+
1482+
{/* Consistent spacing and styling for action buttons area */}
1483+
<div className="flex px-[15px] pt-[10px] pb-[5px] flex-shrink-0">
1484+
{showScrollToBottom ? (
14801485
<StandardTooltip content={t("chat:scrollToBottom")}>
1481-
<div
1482-
className="bg-[color-mix(in_srgb,_var(--vscode-toolbar-hoverBackground)_55%,_transparent)] rounded-[3px] overflow-hidden cursor-pointer flex justify-center items-center flex-1 h-[25px] hover:bg-[color-mix(in_srgb,_var(--vscode-toolbar-hoverBackground)_90%,_transparent)] active:bg-[color-mix(in_srgb,_var(--vscode-toolbar-hoverBackground)_70%,_transparent)]"
1486+
<VSCodeButton
1487+
appearance="secondary"
1488+
className="flex-1 h-[25px] flex justify-center items-center"
14831489
onClick={() => {
14841490
scrollToBottomSmooth()
14851491
disableAutoScrollRef.current = false
14861492
}}>
1487-
<span className="codicon codicon-chevron-down text-[18px]"></span>
1488-
</div>
1493+
<span className="codicon codicon-chevron-down text-[16px]"></span>
1494+
</VSCodeButton>
14891495
</StandardTooltip>
1490-
</div>
1491-
) : (
1492-
<div
1493-
className={`flex ${
1494-
primaryButtonText || secondaryButtonText || isStreaming ? "px-[15px] pt-[10px]" : "p-0"
1495-
} ${
1496-
primaryButtonText || secondaryButtonText || isStreaming
1497-
? enableButtons || (isStreaming && !didClickCancel)
1498-
? "opacity-100"
1499-
: "opacity-50"
1500-
: "opacity-0"
1501-
}`}>
1502-
{primaryButtonText && !isStreaming && (
1503-
<StandardTooltip
1504-
content={
1505-
primaryButtonText === t("chat:retry.title")
1506-
? t("chat:retry.tooltip")
1507-
: primaryButtonText === t("chat:save.title")
1508-
? t("chat:save.tooltip")
1509-
: primaryButtonText === t("chat:approve.title")
1510-
? t("chat:approve.tooltip")
1511-
: primaryButtonText === t("chat:runCommand.title")
1512-
? t("chat:runCommand.tooltip")
1513-
: primaryButtonText === t("chat:startNewTask.title")
1514-
? t("chat:startNewTask.tooltip")
1515-
: primaryButtonText === t("chat:resumeTask.title")
1516-
? t("chat:resumeTask.tooltip")
1517-
: primaryButtonText === t("chat:proceedAnyways.title")
1518-
? t("chat:proceedAnyways.tooltip")
1496+
) : (
1497+
<div
1498+
className={`flex w-full ${
1499+
primaryButtonText || secondaryButtonText || isStreaming
1500+
? enableButtons || (isStreaming && !didClickCancel)
1501+
? "opacity-100"
1502+
: "opacity-50"
1503+
: "opacity-0 pointer-events-none"
1504+
}`}>
1505+
{primaryButtonText && !isStreaming && (
1506+
<StandardTooltip
1507+
content={
1508+
primaryButtonText === t("chat:retry.title")
1509+
? t("chat:retry.tooltip")
1510+
: primaryButtonText === t("chat:save.title")
1511+
? t("chat:save.tooltip")
1512+
: primaryButtonText === t("chat:approve.title")
1513+
? t("chat:approve.tooltip")
1514+
: primaryButtonText === t("chat:runCommand.title")
1515+
? t("chat:runCommand.tooltip")
1516+
: primaryButtonText === t("chat:startNewTask.title")
1517+
? t("chat:startNewTask.tooltip")
1518+
: primaryButtonText === t("chat:resumeTask.title")
1519+
? t("chat:resumeTask.tooltip")
15191520
: primaryButtonText ===
1520-
t("chat:proceedWhileRunning.title")
1521-
? t("chat:proceedWhileRunning.tooltip")
1522-
: undefined
1523-
}>
1524-
<VSCodeButton
1525-
appearance="primary"
1526-
disabled={!enableButtons}
1527-
className={secondaryButtonText ? "flex-1 mr-[6px]" : "flex-[2] mr-0"}
1528-
onClick={() => handlePrimaryButtonClick(inputValue, selectedImages)}>
1529-
{primaryButtonText}
1530-
</VSCodeButton>
1531-
</StandardTooltip>
1532-
)}
1533-
{(secondaryButtonText || isStreaming) && (
1534-
<StandardTooltip
1535-
content={
1536-
isStreaming
1537-
? t("chat:cancel.tooltip")
1538-
: secondaryButtonText === t("chat:startNewTask.title")
1539-
? t("chat:startNewTask.tooltip")
1540-
: secondaryButtonText === t("chat:reject.title")
1541-
? t("chat:reject.tooltip")
1542-
: secondaryButtonText === t("chat:terminate.title")
1543-
? t("chat:terminate.tooltip")
1544-
: undefined
1545-
}>
1546-
<VSCodeButton
1547-
appearance="secondary"
1548-
disabled={!enableButtons && !(isStreaming && !didClickCancel)}
1549-
className={isStreaming ? "flex-[2] ml-0" : "flex-1 ml-[6px]"}
1550-
onClick={() => handleSecondaryButtonClick(inputValue, selectedImages)}>
1551-
{isStreaming ? t("chat:cancel.title") : secondaryButtonText}
1552-
</VSCodeButton>
1553-
</StandardTooltip>
1554-
)}
1555-
</div>
1556-
)}
1521+
t("chat:proceedAnyways.title")
1522+
? t("chat:proceedAnyways.tooltip")
1523+
: primaryButtonText ===
1524+
t("chat:proceedWhileRunning.title")
1525+
? t("chat:proceedWhileRunning.tooltip")
1526+
: undefined
1527+
}>
1528+
<VSCodeButton
1529+
appearance="primary"
1530+
disabled={!enableButtons}
1531+
className={secondaryButtonText ? "flex-1 mr-[6px]" : "flex-[2] mr-0"}
1532+
onClick={() => handlePrimaryButtonClick(inputValue, selectedImages)}>
1533+
{primaryButtonText}
1534+
</VSCodeButton>
1535+
</StandardTooltip>
1536+
)}
1537+
{(secondaryButtonText || isStreaming) && (
1538+
<StandardTooltip
1539+
content={
1540+
isStreaming
1541+
? t("chat:cancel.tooltip")
1542+
: secondaryButtonText === t("chat:startNewTask.title")
1543+
? t("chat:startNewTask.tooltip")
1544+
: secondaryButtonText === t("chat:reject.title")
1545+
? t("chat:reject.tooltip")
1546+
: secondaryButtonText === t("chat:terminate.title")
1547+
? t("chat:terminate.tooltip")
1548+
: undefined
1549+
}>
1550+
<VSCodeButton
1551+
appearance="secondary"
1552+
disabled={!enableButtons && !(isStreaming && !didClickCancel)}
1553+
className={isStreaming ? "flex-[2] ml-0" : "flex-1 ml-[6px]"}
1554+
onClick={() => handleSecondaryButtonClick(inputValue, selectedImages)}>
1555+
{isStreaming ? t("chat:cancel.title") : secondaryButtonText}
1556+
</VSCodeButton>
1557+
</StandardTooltip>
1558+
)}
1559+
</div>
1560+
)}
1561+
</div>
15571562
</>
15581563
)}
15591564

0 commit comments

Comments
 (0)