From ddf360f36da922271ea6816a1eee1b3ffbad59ec Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Mon, 9 Mar 2026 15:09:04 -0700 Subject: [PATCH 1/3] Defer proposed plan rendering until expand in ChatView - Keep long plan cards collapsed with lightweight preview text by default - Render full plan markdown only after explicit expand to reduce thread open slowness - Add tests for preview/strip helpers and browser coverage for expand behavior --- apps/web/src/components/ChatView.browser.tsx | 92 ++ apps/web/src/components/ChatView.tsx | 1032 +++++++++--------- apps/web/src/components/PlanSidebar.tsx | 4 +- apps/web/src/proposedPlan.test.ts | 34 + apps/web/src/proposedPlan.ts | 59 + 5 files changed, 725 insertions(+), 496 deletions(-) diff --git a/apps/web/src/components/ChatView.browser.tsx b/apps/web/src/components/ChatView.browser.tsx index e2fd573fe8..0f0250e48f 100644 --- a/apps/web/src/components/ChatView.browser.tsx +++ b/apps/web/src/components/ChatView.browser.tsx @@ -256,6 +256,61 @@ function createDraftOnlySnapshot(): OrchestrationReadModel { }; } +function createSnapshotWithLongProposedPlan(): OrchestrationReadModel { + const snapshot = createSnapshotForTargetUser({ + targetMessageId: "msg-user-plan-target" as MessageId, + targetText: "plan thread", + }); + const planMarkdown = [ + "# Ship plan mode follow-up", + "", + "- Step 1: capture the thread-open trace", + "- Step 2: identify the main-thread bottleneck", + "- Step 3: keep collapsed cards cheap", + "- Step 4: render the full markdown only on demand", + "- Step 5: preserve export and save actions", + "- Step 6: add regression coverage", + "- Step 7: verify route transitions stay responsive", + "- Step 8: confirm no server-side work changed", + "- Step 9: confirm short plans still render normally", + "- Step 10: confirm long plans stay collapsed by default", + "- Step 11: confirm preview text is still useful", + "- Step 12: confirm plan follow-up flow still works", + "- Step 13: confirm timeline virtualization still behaves", + "- Step 14: confirm theme styling still looks correct", + "- Step 15: confirm save dialog behavior is unchanged", + "- Step 16: confirm download behavior is unchanged", + "- Step 17: confirm code fences do not parse until expand", + "- Step 18: confirm preview truncation ends cleanly", + "- Step 19: confirm markdown links still open in editor after expand", + "- Step 20: confirm deep hidden detail only appears after expand", + "", + "```ts", + "export const hiddenPlanImplementationDetail = 'deep hidden detail only after expand';", + "```", + ].join("\n"); + + return { + ...snapshot, + threads: snapshot.threads.map((thread) => + thread.id === THREAD_ID + ? Object.assign({}, thread, { + proposedPlans: [ + { + id: "plan-browser-test", + turnId: null, + planMarkdown, + createdAt: isoAt(1_000), + updatedAt: isoAt(1_001), + }, + ], + updatedAt: isoAt(1_001), + }) + : thread, + ), + }; +} + function resolveWsRpc(tag: string): unknown { if (tag === ORCHESTRATION_WS_METHODS.getSnapshot) { return fixture.snapshot; @@ -867,4 +922,41 @@ describe("ChatView timeline estimator parity (full app)", () => { await mounted.cleanup(); } }); + + it("keeps long proposed plans lightweight until the user expands them", async () => { + const mounted = await mountChatView({ + viewport: DEFAULT_VIEWPORT, + snapshot: createSnapshotWithLongProposedPlan(), + }); + + try { + await waitForElement( + () => + Array.from(document.querySelectorAll("button")).find( + (button) => button.textContent?.trim() === "Expand plan", + ) as HTMLButtonElement | null, + "Unable to find Expand plan button.", + ); + + expect(document.body.textContent).not.toContain("deep hidden detail only after expand"); + + const expandButton = await waitForElement( + () => + Array.from(document.querySelectorAll("button")).find( + (button) => button.textContent?.trim() === "Expand plan", + ) as HTMLButtonElement | null, + "Unable to find Expand plan button.", + ); + expandButton.click(); + + await vi.waitFor( + () => { + expect(document.body.textContent).toContain("deep hidden detail only after expand"); + }, + { timeout: 8_000, interval: 16 }, + ); + } finally { + await mounted.cleanup(); + } + }); }); diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 5fb47b1a9a..73c9ee94a0 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -31,6 +31,7 @@ import { } from "@t3tools/shared/model"; import { memo, + startTransition, useCallback, useEffect, useLayoutEffect, @@ -89,6 +90,7 @@ import { } from "../pendingUserInput"; import { useStore } from "../store"; import { + buildCollapsedProposedPlanPreviewMarkdown, buildPlanImplementationThreadTitle, buildPlanImplementationPrompt, buildProposedPlanMarkdownFilename, @@ -96,6 +98,7 @@ import { normalizePlanMarkdownForExport, proposedPlanTitle, resolvePlanFollowUpSubmission, + stripDisplayedPlanMarkdown, } from "../proposedPlan"; import { truncateTitle } from "../truncateTitle"; import { @@ -201,11 +204,7 @@ import { Toggle } from "./ui/toggle"; import { SidebarTrigger } from "./ui/sidebar"; import { newCommandId, newMessageId, newThreadId } from "~/lib/utils"; import { readNativeApi } from "~/nativeApi"; -import { - getAppModelOptions, - resolveAppModelSelection, - useAppSettings, -} from "../appSettings"; +import { getAppModelOptions, resolveAppModelSelection, useAppSettings } from "../appSettings"; import { type ComposerImageAttachment, type DraftThreadEnvMode, @@ -292,8 +291,6 @@ function workToneClass(tone: "thinking" | "tool" | "info" | "error"): string { return "text-muted-foreground/40"; } - - interface ExpandedImageItem { src: string; name: string; @@ -1963,8 +1960,6 @@ export default function ChatView({ threadId }: ChatViewProps) { planSidebarDismissedForTurnRef.current = null; }, [activeThread?.id]); - - useEffect(() => { if (!composerMenuOpen) { setComposerHighlightedItemId(null); @@ -2688,9 +2683,7 @@ export default function ChatView({ threadId }: ChatViewProps) { ...(selectedModelOptionsForDispatch ? { modelOptions: selectedModelOptionsForDispatch } : {}), - ...(providerOptionsForDispatch - ? { providerOptions: providerOptionsForDispatch } - : {}), + ...(providerOptionsForDispatch ? { providerOptions: providerOptionsForDispatch } : {}), provider: selectedProvider, assistantDeliveryMode: settings.enableAssistantStreaming ? "streaming" : "buffered", runtimeMode, @@ -2968,9 +2961,7 @@ export default function ChatView({ threadId }: ChatViewProps) { ...(selectedModelOptionsForDispatch ? { modelOptions: selectedModelOptionsForDispatch } : {}), - ...(providerOptionsForDispatch - ? { providerOptions: providerOptionsForDispatch } - : {}), + ...(providerOptionsForDispatch ? { providerOptions: providerOptionsForDispatch } : {}), assistantDeliveryMode: settings.enableAssistantStreaming ? "streaming" : "buffered", runtimeMode, interactionMode: nextInteractionMode, @@ -3079,9 +3070,7 @@ export default function ChatView({ threadId }: ChatViewProps) { ...(selectedModelOptionsForDispatch ? { modelOptions: selectedModelOptionsForDispatch } : {}), - ...(providerOptionsForDispatch - ? { providerOptions: providerOptionsForDispatch } - : {}), + ...(providerOptionsForDispatch ? { providerOptions: providerOptionsForDispatch } : {}), assistantDeliveryMode: settings.enableAssistantStreaming ? "streaming" : "buffered", runtimeMode, interactionMode: "default", @@ -3503,513 +3492,537 @@ export default function ChatView({ threadId }: ChatViewProps) {
{/* Chat column */}
- - {/* Messages */} -
- 0} - isWorking={isWorking} - activeTurnInProgress={isWorking || !latestTurnSettled} - activeTurnStartedAt={activeWorkStartedAt} - scrollContainer={messagesScrollElement} - timelineEntries={timelineEntries} - completionDividerBeforeEntryId={completionDividerBeforeEntryId} - completionSummary={completionSummary} - turnDiffSummaryByAssistantMessageId={turnDiffSummaryByAssistantMessageId} - nowIso={nowIso} - expandedWorkGroups={expandedWorkGroups} - onToggleWorkGroup={onToggleWorkGroup} - onOpenTurnDiff={onOpenTurnDiff} - revertTurnCountByUserMessageId={revertTurnCountByUserMessageId} - onRevertUserMessage={onRevertUserMessage} - isRevertingCheckpoint={isRevertingCheckpoint} - onImageExpand={onExpandTimelineImage} - markdownCwd={gitCwd ?? undefined} - resolvedTheme={resolvedTheme} - workspaceRoot={activeProject?.cwd ?? undefined} - /> -
- - {/* Input bar */} -
-
+ {/* Messages */}
- {activePendingApproval ? ( -
- -
- ) : pendingUserInputs.length > 0 ? ( -
- -
- ) : showPlanFollowUpPrompt && activeProposedPlan ? ( -
- -
- ) : null} + 0} + isWorking={isWorking} + activeTurnInProgress={isWorking || !latestTurnSettled} + activeTurnStartedAt={activeWorkStartedAt} + scrollContainer={messagesScrollElement} + timelineEntries={timelineEntries} + completionDividerBeforeEntryId={completionDividerBeforeEntryId} + completionSummary={completionSummary} + turnDiffSummaryByAssistantMessageId={turnDiffSummaryByAssistantMessageId} + nowIso={nowIso} + expandedWorkGroups={expandedWorkGroups} + onToggleWorkGroup={onToggleWorkGroup} + onOpenTurnDiff={onOpenTurnDiff} + revertTurnCountByUserMessageId={revertTurnCountByUserMessageId} + onRevertUserMessage={onRevertUserMessage} + isRevertingCheckpoint={isRevertingCheckpoint} + onImageExpand={onExpandTimelineImage} + markdownCwd={gitCwd ?? undefined} + resolvedTheme={resolvedTheme} + workspaceRoot={activeProject?.cwd ?? undefined} + /> +
- {/* Textarea area */} -
+ - {composerMenuOpen && !isComposerApprovalState && ( -
- -
- )} - - {!isComposerApprovalState && pendingUserInputs.length === 0 && composerImages.length > 0 && ( -
- {composerImages.map((image) => ( -
- {image.previewUrl ? ( - - ) : ( -
- {image.name} -
- )} - {nonPersistedComposerImageIdSet.has(image.id) && ( - - - - - } - /> - - Draft attachment could not be saved locally and may be lost on - navigation. - - - )} - -
- ))} -
- )} - -
- - {/* Bottom toolbar */} - {activePendingApproval ? ( -
- -
- ) : (
+ {activePendingApproval ? ( +
+ +
+ ) : pendingUserInputs.length > 0 ? ( +
+ +
+ ) : showPlanFollowUpPrompt && activeProposedPlan ? ( +
+ +
+ ) : null} + + {/* Textarea area */}
- {/* Provider/model picker */} - + +
+ )} + + {!isComposerApprovalState && + pendingUserInputs.length === 0 && + composerImages.length > 0 && ( +
+ {composerImages.map((image) => ( +
+ {image.previewUrl ? ( + + ) : ( +
+ {image.name} +
+ )} + {nonPersistedComposerImageIdSet.has(image.id) && ( + + + + + } + /> + + Draft attachment could not be saved locally and may be lost on + navigation. + + + )} + +
+ ))} +
+ )} + +
- {isComposerFooterCompact ? ( - + - ) : ( - <> - {selectedProvider === "codex" && selectedEffort != null ? ( - <> - - - - ) : null} +
+ ) : ( +
+
+ {/* Provider/model picker */} + - + {isComposerFooterCompact ? ( + + ) : ( + <> + {selectedProvider === "codex" && selectedEffort != null ? ( + <> + + + + ) : null} - + - + - + - {(activePlan || activeProposedPlan || planSidebarOpen) ? ( - <> - - - ) : null} - - )} -
- {/* Right side: send / stop button */} -
- {isPreparingWorktree ? ( - Preparing worktree... - ) : null} - {activePendingProgress ? ( -
- {activePendingProgress.questionIndex > 0 ? ( - - ) : null} - + {activePlan || activeProposedPlan || planSidebarOpen ? ( + <> + + + + ) : null} + + )}
- ) : phase === "running" ? ( - - ) : pendingUserInputs.length === 0 ? ( - showPlanFollowUpPrompt ? ( - prompt.trim().length > 0 ? ( - - ) : ( -
+ {isPreparingWorktree ? ( + + Preparing worktree... + + ) : null} + {activePendingProgress ? ( +
+ {activePendingProgress.questionIndex > 0 ? ( + + ) : null} - - - } - > - - - - void onImplementPlanInNewThread()} - > - Implement in new thread - - -
- ) - ) : ( - + ) : pendingUserInputs.length === 0 ? ( + showPlanFollowUpPrompt ? ( + prompt.trim().length > 0 ? ( + + ) : ( +
+ + + + } + > + + + + void onImplementPlanInNewThread()} + > + Implement in new thread + + + +
+ ) ) : ( - - )} - - ) - ) : null} -
+ {isConnecting || isSendBusy ? ( + + ) : ( + + )} + + ) + ) : null} +
+
+ )}
- )} +
- - - - {isGitRepo && ( - - )} - {/* end chat column */} + {isGitRepo && ( + + )} + + {/* end chat column */} {/* Plan sidebar */} {planSidebarOpen ? ( @@ -4028,7 +4041,8 @@ export default function ChatView({ threadId }: ChatViewProps) { }} /> ) : null} - {/* end horizontal flex container */} + + {/* end horizontal flex container */} {(() => { if (!terminalState.terminalOpen || !activeProject) { @@ -4465,10 +4479,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard( const handler = (event: globalThis.KeyboardEvent) => { if (event.metaKey || event.ctrlKey || event.altKey) return; const target = event.target; - if ( - target instanceof HTMLInputElement || - target instanceof HTMLTextAreaElement - ) { + if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { return; } // If the user has started typing a custom answer in the contenteditable @@ -4542,12 +4553,12 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard(
{option.label} {option.description && option.description !== option.label ? ( - {option.description} + + {option.description} + ) : null}
- {isSelected ? ( - - ) : null} + {isSelected ? : null} ); })} @@ -4754,13 +4765,34 @@ const ProposedPlanCard = memo(function ProposedPlanCard({ const [isSaveDialogOpen, setIsSaveDialogOpen] = useState(false); const [savePath, setSavePath] = useState(""); const [isSavingToWorkspace, setIsSavingToWorkspace] = useState(false); + const [renderCollapsedMarkdown, setRenderCollapsedMarkdown] = useState(false); const savePathInputId = useId(); const title = proposedPlanTitle(planMarkdown) ?? "Proposed plan"; const lineCount = planMarkdown.split("\n").length; const canCollapse = planMarkdown.length > 900 || lineCount > 20; + const displayedPlanMarkdown = stripDisplayedPlanMarkdown(planMarkdown); + const collapsedPreview = canCollapse + ? buildCollapsedProposedPlanPreviewMarkdown(planMarkdown, { maxLines: 10 }) + : null; const downloadFilename = buildProposedPlanMarkdownFilename(planMarkdown); const saveContents = normalizePlanMarkdownForExport(planMarkdown); + useEffect(() => { + if (!canCollapse || expanded) { + setRenderCollapsedMarkdown(false); + return; + } + setRenderCollapsedMarkdown(false); + const frame = window.requestAnimationFrame(() => { + startTransition(() => { + setRenderCollapsedMarkdown(true); + }); + }); + return () => { + window.cancelAnimationFrame(frame); + }; + }, [canCollapse, expanded, collapsedPreview]); + const handleDownload = () => { downloadPlanAsTextFile(downloadFilename, saveContents); }; @@ -4847,7 +4879,17 @@ const ProposedPlanCard = memo(function ProposedPlanCard({
- + {canCollapse && !expanded ? ( + renderCollapsedMarkdown ? ( + + ) : ( +
+                {collapsedPreview}
+              
+ ) + ) : ( + + )} {canCollapse && !expanded ? (
) : null} @@ -5601,7 +5643,7 @@ const ProviderModelPicker = memo(function ProviderModelPicker(props: { } setIsMenuOpen(open); }} - > + >max-w-42 } diff --git a/apps/web/src/components/PlanSidebar.tsx b/apps/web/src/components/PlanSidebar.tsx index 5ab2f5e32c..b2a9744f07 100644 --- a/apps/web/src/components/PlanSidebar.tsx +++ b/apps/web/src/components/PlanSidebar.tsx @@ -20,6 +20,7 @@ import { buildProposedPlanMarkdownFilename, normalizePlanMarkdownForExport, downloadPlanAsTextFile, + stripDisplayedPlanMarkdown, } from "../proposedPlan"; import { Menu, MenuItem, MenuPopup, MenuTrigger } from "./ui/menu"; import { readNativeApi } from "~/nativeApi"; @@ -67,6 +68,7 @@ const PlanSidebar = memo(function PlanSidebar({ const [copied, setCopied] = useState(false); const planMarkdown = activeProposedPlan?.planMarkdown ?? null; + const displayedPlanMarkdown = planMarkdown ? stripDisplayedPlanMarkdown(planMarkdown) : null; const planTitle = planMarkdown ? proposedPlanTitle(planMarkdown) : null; const handleCopyPlan = useCallback(() => { @@ -237,7 +239,7 @@ const PlanSidebar = memo(function PlanSidebar({ {proposedPlanExpanded ? (
diff --git a/apps/web/src/proposedPlan.test.ts b/apps/web/src/proposedPlan.test.ts index b8431bdbcc..e5e917bd4c 100644 --- a/apps/web/src/proposedPlan.test.ts +++ b/apps/web/src/proposedPlan.test.ts @@ -1,11 +1,13 @@ import { describe, expect, it } from "vitest"; import { + buildCollapsedProposedPlanPreviewMarkdown, buildPlanImplementationThreadTitle, buildPlanImplementationPrompt, buildProposedPlanMarkdownFilename, proposedPlanTitle, resolvePlanFollowUpSubmission, + stripDisplayedPlanMarkdown, } from "./proposedPlan"; describe("proposedPlanTitle", () => { @@ -26,6 +28,38 @@ describe("buildPlanImplementationPrompt", () => { }); }); +describe("buildCollapsedProposedPlanPreviewMarkdown", () => { + it("drops the redundant title heading and preserves the following markdown lines", () => { + expect( + buildCollapsedProposedPlanPreviewMarkdown("# Integrate RPC\n\n## Summary\n\n- step 1\n- step 2", { + maxLines: 4, + }), + ).toBe("- step 1\n- step 2"); + }); + + it("appends an overflow marker when the preview truncates remaining content", () => { + expect( + buildCollapsedProposedPlanPreviewMarkdown("# Integrate RPC\n\n- step 1\n- step 2\n- step 3", { + maxLines: 2, + }), + ).toBe("- step 1\n- step 2\n\n..."); + }); +}); + +describe("stripDisplayedPlanMarkdown", () => { + it("drops the leading title heading from displayed plan markdown", () => { + expect(stripDisplayedPlanMarkdown("# Integrate RPC\n\n## Summary\n\n- step 1\n")).toBe( + "- step 1", + ); + }); + + it("preserves non-summary headings after dropping the title heading", () => { + expect(stripDisplayedPlanMarkdown("# Integrate RPC\n\n## Scope\n\n- step 1\n")).toBe( + "## Scope\n\n- step 1", + ); + }); +}); + describe("resolvePlanFollowUpSubmission", () => { it("switches to default mode when implementing the ready plan without extra text", () => { expect( diff --git a/apps/web/src/proposedPlan.ts b/apps/web/src/proposedPlan.ts index 3bd4f62e60..8a5f18b6f0 100644 --- a/apps/web/src/proposedPlan.ts +++ b/apps/web/src/proposedPlan.ts @@ -3,6 +3,65 @@ export function proposedPlanTitle(planMarkdown: string): string | null { return heading && heading.length > 0 ? heading : null; } +export function stripDisplayedPlanMarkdown(planMarkdown: string): string { + const lines = planMarkdown.trimEnd().split(/\r?\n/); + const sourceLines = + lines[0] && /^\s{0,3}#{1,6}\s+/.test(lines[0]) ? lines.slice(1) : [...lines]; + while (sourceLines[0]?.trim().length === 0) { + sourceLines.shift(); + } + const firstHeadingMatch = sourceLines[0]?.match(/^\s{0,3}#{1,6}\s+(.+)$/); + if (firstHeadingMatch?.[1]?.trim().toLowerCase() === "summary") { + sourceLines.shift(); + while (sourceLines[0]?.trim().length === 0) { + sourceLines.shift(); + } + } + return sourceLines.join("\n"); +} + +export function buildCollapsedProposedPlanPreviewMarkdown( + planMarkdown: string, + options?: { + maxLines?: number; + }, +): string { + const maxLines = options?.maxLines ?? 8; + const lines = stripDisplayedPlanMarkdown(planMarkdown) + .trimEnd() + .split(/\r?\n/) + .map((line) => line.trimEnd()); + const previewLines: string[] = []; + let visibleLineCount = 0; + let hasMoreContent = false; + + for (const line of lines) { + const isVisibleLine = line.trim().length > 0; + if (isVisibleLine && visibleLineCount >= maxLines) { + hasMoreContent = true; + break; + } + previewLines.push(line); + if (isVisibleLine) { + visibleLineCount += 1; + } + } + + while (previewLines.length > 0 && previewLines.at(-1)?.trim().length === 0) { + previewLines.pop(); + } + + if (previewLines.length === 0) { + return proposedPlanTitle(planMarkdown) ?? "Plan preview unavailable."; + } + + if (hasMoreContent) { + previewLines.push("", "..."); + } + + return previewLines.join("\n"); +} + function sanitizePlanFileSegment(input: string): string { const sanitized = input .toLowerCase() From a776454b1c62bdf97ea983777e3b1cba91bcb4c3 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Mon, 9 Mar 2026 15:12:42 -0700 Subject: [PATCH 2/3] Render collapsed plan preview directly as markdown - remove deferred collapsed preview state in `ProposedPlanCard` - always render collapsed preview with `ChatMarkdown` for simpler, consistent display --- apps/web/src/components/ChatView.tsx | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 73c9ee94a0..8bb8f7c70e 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -31,7 +31,6 @@ import { } from "@t3tools/shared/model"; import { memo, - startTransition, useCallback, useEffect, useLayoutEffect, @@ -4765,7 +4764,6 @@ const ProposedPlanCard = memo(function ProposedPlanCard({ const [isSaveDialogOpen, setIsSaveDialogOpen] = useState(false); const [savePath, setSavePath] = useState(""); const [isSavingToWorkspace, setIsSavingToWorkspace] = useState(false); - const [renderCollapsedMarkdown, setRenderCollapsedMarkdown] = useState(false); const savePathInputId = useId(); const title = proposedPlanTitle(planMarkdown) ?? "Proposed plan"; const lineCount = planMarkdown.split("\n").length; @@ -4777,22 +4775,6 @@ const ProposedPlanCard = memo(function ProposedPlanCard({ const downloadFilename = buildProposedPlanMarkdownFilename(planMarkdown); const saveContents = normalizePlanMarkdownForExport(planMarkdown); - useEffect(() => { - if (!canCollapse || expanded) { - setRenderCollapsedMarkdown(false); - return; - } - setRenderCollapsedMarkdown(false); - const frame = window.requestAnimationFrame(() => { - startTransition(() => { - setRenderCollapsedMarkdown(true); - }); - }); - return () => { - window.cancelAnimationFrame(frame); - }; - }, [canCollapse, expanded, collapsedPreview]); - const handleDownload = () => { downloadPlanAsTextFile(downloadFilename, saveContents); }; @@ -4880,13 +4862,7 @@ const ProposedPlanCard = memo(function ProposedPlanCard({
{canCollapse && !expanded ? ( - renderCollapsedMarkdown ? ( - - ) : ( -
-                {collapsedPreview}
-              
- ) + ) : ( )} From 039ce6ed142788f9a255c633b09600aa21472884 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Mon, 9 Mar 2026 15:16:16 -0700 Subject: [PATCH 3/3] fmt --- apps/web/src/components/ChatView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 8bb8f7c70e..2eaeb64f07 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -5619,7 +5619,7 @@ const ProviderModelPicker = memo(function ProviderModelPicker(props: { } setIsMenuOpen(open); }} - >max-w-42 + > } @@ -5636,7 +5636,7 @@ const ProviderModelPicker = memo(function ProviderModelPicker(props: {