Skip to content

fix(web): make plan sidebar resizable like diff panel#2598

Open
jonathanperis wants to merge 1 commit intopingdotgg:mainfrom
jonathanperis:main
Open

fix(web): make plan sidebar resizable like diff panel#2598
jonathanperis wants to merge 1 commit intopingdotgg:mainfrom
jonathanperis:main

Conversation

@jonathanperis
Copy link
Copy Markdown

@jonathanperis jonathanperis commented May 8, 2026

What Changed

The plan sidebar panel was rendered as a plain `

` with a hardcoded `w-[340px]` width inside `ChatView`. It could not be resized by the user.

This PR adds drag-to-resize support, a max-width constraint, and localStorage width persistence — matching the behavior already present on the diff panel.

Changes across 5 files:

  • `rightPanelLayout.ts` — adds `PLAN_INLINE_*` constants, `COMPOSER_COMPACT_MIN_LEFT_CONTROLS_WIDTH_PX`, and `createComposerWidthValidator(cssVarName)` factory (shared by both panels)
  • `PlanSidebar.tsx` — removes hardcoded `w-[340px] shrink-0 border-l`; width/border controlled by the parent wrapper
  • `hooks/useResizeHandle.ts` — new hook encapsulating pointer capture, RAF-batched width updates, body style management, click suppression, localStorage persistence with viewport-aware restore validation, and three cleanup paths: (1) `isDisabled` effect for sheet-mode flip mid-drag, (2) `setWrapperRef(null)` for programmatic sidebar close mid-drag, (3) React unmount effect; uses `useMemo` for the width validator
  • `ChatView.tsx` — replaces ~90 lines of inline resize logic with `useResizeHandle({ cssVarName, storageKey, minWidth, isDisabled: shouldUsePlanSidebarSheet })`
  • `routes/_chat.$environmentId.$threadId.tsx` — removes duplicate `COMPOSER_COMPACT_MIN_LEFT_CONTROLS_WIDTH_PX` constant; replaces `shouldAcceptInlineSidebarWidth` inline body with `useMemo(() => createComposerWidthValidator("--sidebar-width"), [])`

Why a plain div instead of `SidebarProvider > Sidebar`?

The `Sidebar` component uses `position: fixed; right: 0; z-10` hardcoded in its JSX. When both the diff and plan panels are open simultaneously, two `fixed` elements at `right: 0` overlap. The plain flex div stays in normal document flow — it renders to the left of the diff panel's fixed container with no overlap.

Default width: `clamp(20rem, 30vw, 28rem)` (~340px). Minimum: 320px. The `shouldAcceptWidth` validator rejects resize attempts that would overflow the chat composer or drop it below its minimum usable width — same behaviour as the diff panel. Width persists under `localStorage` key `chat_plan_sidebar_width`. Sheet/mobile behaviour (≤1180px) is unchanged.

Why

The diff panel has had resize support since it was introduced. The plan sidebar did not, despite being the same visual pattern. Users working with large plans benefit from being able to widen the panel to read content without scrolling.

UI Changes

2026-04-19.15-37-07.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

[!NOTE]

Make plan sidebar resizable with a draggable left-edge handle

  • Adds a drag handle to the inline plan sidebar in ChatView.tsx, mirroring the existing diff panel resize behavior.
  • Implements a new useResizeHandle hook that controls panel width via a CSS custom property (--plan-sidebar-width), persists width to localStorage, enforces a minimum width, and cleans up mid-drag if the panel switches to sheet mode.
  • Adds sizing constants and a shared createComposerWidthValidator factory to rightPanelLayout.ts; the diff panel route now uses this shared validator instead of its own inline implementation.
  • PlanSidebar.tsx no longer applies its own fixed width or border — parent containers are responsible for sizing.
  • Behavioral Change: the plan sidebar no longer has a fixed width in inline mode; initial width comes from localStorage or the new default constant, and resizing is constrained to prevent composer overflow.

Macroscope summarized cd94682.


[!NOTE]
Medium Risk
Moderate UI risk: adds pointer-driven resizing, DOM measurement, and localStorage persistence in the core chat view, which could regress layout or leave global body styles stuck if edge cases are missed.

Overview
Makes the inline plan sidebar in ChatView draggable-resizable (defaulting to a CSS-var width and persisting to localStorage), including a left-edge resize handle and disabling the interaction when the mobile/sheet layout is active.

Extracts the resize interaction into a new useResizeHandle hook (pointer capture, RAF-batched updates, cleanup, click suppression) and centralizes the “don’t break the composer” width-acceptance logic via createComposerWidthValidator in rightPanelLayout, which the diff panel route now uses instead of its duplicated inline validator. PlanSidebar no longer hardcodes its own sidebar width/border, relying on the parent wrapper for sizing.

Reviewed by Cursor Bugbot for commit 71731f2. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 97e5533f-d19a-43f3-ab19-c63defd34396

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels May 8, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 8, 2026

Approvability

Verdict: Needs human review

This PR introduces a new user-facing capability (resizable plan sidebar) with ~190 lines of new hook code. While well-scoped and following existing patterns from the diff panel, the addition of new interactive behavior warrants human review.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant