Fix plan composer layout by preventing flex overflow in chat/sidebar#706
Fix plan composer layout by preventing flex overflow in chat/sidebar#706juliusmarminge merged 7 commits intomainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Duplicated reasoning label map across two components
- Extracted the duplicated
reasoningLabelByOptionmap andgetDefaultReasoningEffort("codex")call into file-level constantsREASONING_LABEL_BY_OPTIONandDEFAULT_CODEX_REASONING_EFFORT, shared by bothCompactComposerControlsMenuandCodexTraitsPicker.
- Extracted the duplicated
Or push these changes by commenting:
@cursor push 23b302207c
Preview (23b302207c)
diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx
--- a/apps/web/src/components/ChatView.tsx
+++ b/apps/web/src/components/ChatView.tsx
@@ -5723,6 +5723,15 @@
);
});
+const REASONING_LABEL_BY_OPTION: Record<CodexReasoningEffort, string> = {
+ low: "Low",
+ medium: "Medium",
+ high: "High",
+ xhigh: "Extra High",
+};
+
+const DEFAULT_CODEX_REASONING_EFFORT = getDefaultReasoningEffort("codex");
+
const CompactComposerControlsMenu = memo(function CompactComposerControlsMenu(props: {
activePlan: boolean;
interactionMode: ProviderInteractionMode;
@@ -5738,14 +5747,6 @@
onTogglePlanSidebar: () => void;
onToggleRuntimeMode: () => void;
}) {
- const defaultReasoningEffort = getDefaultReasoningEffort("codex");
- const reasoningLabelByOption: Record<CodexReasoningEffort, string> = {
- low: "Low",
- medium: "Medium",
- high: "High",
- xhigh: "Extra High",
- };
-
return (
<Menu>
<MenuTrigger
@@ -5776,8 +5777,8 @@
>
{props.reasoningOptions.map((effort) => (
<MenuRadioItem key={effort} value={effort}>
- {reasoningLabelByOption[effort]}
- {effort === defaultReasoningEffort ? " (default)" : ""}
+ {REASONING_LABEL_BY_OPTION[effort]}
+ {effort === DEFAULT_CODEX_REASONING_EFFORT ? " (default)" : ""}
</MenuRadioItem>
))}
</MenuRadioGroup>
@@ -5847,15 +5848,8 @@
onFastModeChange: (enabled: boolean) => void;
}) {
const [isMenuOpen, setIsMenuOpen] = useState(false);
- const defaultReasoningEffort = getDefaultReasoningEffort("codex");
- const reasoningLabelByOption: Record<CodexReasoningEffort, string> = {
- low: "Low",
- medium: "Medium",
- high: "High",
- xhigh: "Extra High",
- };
const triggerLabel = [
- reasoningLabelByOption[props.effort],
+ REASONING_LABEL_BY_OPTION[props.effort],
...(props.fastModeEnabled ? ["Fast"] : []),
]
.filter(Boolean)
@@ -5894,8 +5888,8 @@
>
{props.options.map((effort) => (
<MenuRadioItem key={effort} value={effort}>
- {reasoningLabelByOption[effort]}
- {effort === defaultReasoningEffort ? " (default)" : ""}
+ {REASONING_LABEL_BY_OPTION[effort]}
+ {effort === DEFAULT_CODEX_REASONING_EFFORT ? " (default)" : ""}
</MenuRadioItem>
))}
</MenuRadioGroup>There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Inconsistent width measurement between initial and observer callbacks
- Changed the ResizeObserver callback to use composerForm.clientWidth instead of entry.contentRect.width, making both measurement points consistent.
Or push these changes by commenting:
@cursor push 580eb4b5a8
Preview (580eb4b5a8)
diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx
--- a/apps/web/src/components/ChatView.tsx
+++ b/apps/web/src/components/ChatView.tsx
@@ -1928,7 +1928,7 @@
const [entry] = entries;
if (!entry) return;
- const nextCompact = shouldUseCompactComposerFooter(entry.contentRect.width, {
+ const nextCompact = shouldUseCompactComposerFooter(composerForm.clientWidth, {
hasWideActions: composerFooterHasWideActions,
});
setIsComposerFooterCompact((previous) => (previous === nextCompact ? previous : nextCompact));- add `min-w-0` to chat/flex containers to prevent composer/sidebar overflow - move `BranchToolbar` into the chat column so layout stays aligned with plan sidebar - extract sidebar inset base classes to shared logic and add a regression test for `min-w-0`
- add shared footer layout breakpoint helper with tests - switch chat composer footer to compact menu when width is constrained - preserve plan sidebar toggle behavior while consolidating footer actions
- Replace `SIDEBAR_INSET_BASE_CLASSNAME` with an inline class string in `sidebar.tsx` - Delete the now-unused `sidebar.logic.ts` helper and its focused unit test
Co-authored-by: codex <[email protected]>
b4d1a69 to
c714e8d
Compare
- Measure composer width from the form element in initial and resize paths - Avoid relying on ResizeObserver contentRect width for compact footer layout decisions
- Add composer footer/action data attributes for targeted width measurement - Enforce a minimum composer width before allowing inline diff sidebar
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Inline arrow function defeats memo on compact menu
- Extracted the inline arrow function into a stable
toggleRuntimeModeuseCallback, consistent with howtoggleInteractionModeandtogglePlanSidebarare handled, so the memo onCompactComposerControlsMenucan properly skip re-renders.
- Extracted the inline arrow function into a stable
Or push these changes by commenting:
@cursor push 457d6c4f14
Preview (457d6c4f14)
diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx
--- a/apps/web/src/components/ChatView.tsx
+++ b/apps/web/src/components/ChatView.tsx
@@ -1675,6 +1675,11 @@
const toggleInteractionMode = useCallback(() => {
handleInteractionModeChange(interactionMode === "plan" ? "default" : "plan");
}, [handleInteractionModeChange, interactionMode]);
+ const toggleRuntimeMode = useCallback(() => {
+ void handleRuntimeModeChange(
+ runtimeMode === "full-access" ? "approval-required" : "full-access",
+ );
+ }, [handleRuntimeModeChange, runtimeMode]);
const togglePlanSidebar = useCallback(() => {
setPlanSidebarOpen((open) => {
if (open) {
@@ -3745,11 +3750,7 @@
onCodexFastModeChange={onCodexFastModeChange}
onToggleInteractionMode={toggleInteractionMode}
onTogglePlanSidebar={togglePlanSidebar}
- onToggleRuntimeMode={() =>
- void handleRuntimeModeChange(
- runtimeMode === "full-access" ? "approval-required" : "full-access",
- )
- }
+ onToggleRuntimeMode={toggleRuntimeMode}
/>
) : (
<>Co-authored-by: Julius Marminge <[email protected]> Applied via @cursor push command

Before
After
CleanShot.2026-03-09.at.11.00.55.mp4
Summary
min-w-0to the main chat/sidebar flex container inChatViewso the plan sidebar and composer can shrink correctly without horizontal overflowBranchToolbarinto the chat column so it participates in the intended column layout with the composer/content areaSidebarInsetbase classes intosidebar.logic.tsand includemin-w-0in the shared base classnamemin-w-0for shrink behavior safetyTesting
apps/web/src/components/ui/sidebar.test.tsx: verifiesSIDEBAR_INSET_BASE_CLASSNAMEcontainsmin-w-0min-w-0andSidebarInsetbase class includesmin-w-0bun lint,bun typecheck,bun run test)Note
Fix flex overflow in chat composer and sidebar to prevent layout breakage
CompactComposerControlsMenucomponent.shouldUseCompactComposerFooterin composerFooterLayout.ts with aResizeObserverto recompute layout on width changes.min-w-0to the main content containers in ChatView.tsx and sidebar.tsx so flex children can shrink without forcing horizontal overflow.Macroscope summarized 5d6a99a.
Note
Low Risk
UI-only layout changes (flex sizing, resize observers, and sidebar resize constraints) that could cause minor regressions in responsiveness across breakpoints, but no security or data-handling impact.
Overview
Prevents chat layout overflow by adding
min-w-0to key flex containers (ChatViewmain row andSidebarInset) and movingBranchToolbarinto the chat column so it participates in the intended layout.Adds a responsive compact composer footer:
ChatViewnow measures composer width (withResizeObserver) and, below a breakpoint, collapses secondary controls into a newCompactComposerControlsMenuand constrains theProviderModelPickerlabel via a newcompactprop; breakpoints and logic are extracted toshouldUseCompactComposerFooterwith unit tests.Hardens inline diff sidebar resizing by rejecting sidebar widths that would force the composer below a computed minimum width, using new
data-chat-composer-*hooks to measure footer gaps and right-side action widths.Written by Cursor Bugbot for commit 9bbb600. This will update automatically on new commits. Configure here.