Skip to content

feat(web): remove sidebar and panel max-width limits#985

Merged
wbxl2000 merged 7 commits into
mainfrom
feat/web-unbounded-panel-width
Jun 23, 2026
Merged

feat(web): remove sidebar and panel max-width limits#985
wbxl2000 merged 7 commits into
mainfrom
feat/web-unbounded-panel-width

Conversation

@wbxl2000

@wbxl2000 wbxl2000 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No related issue — see the problem below.

Problem

The web sidebar was capped at a fixed 420px and the right-side detail / file-preview panel at a static viewport-derived cap that did not react to window resizing. On wide monitors neither panel could be dragged wider. Removing those caps outright is unsafe though: a width saved on a large display and restored on a narrow window would push the resize handle and collapse button off-screen, leaving the conversation inaccessible with no in-UI way to shrink the panel.

What changed

Replaced the fixed / static caps with a shared, viewport-aware maximum for both panels. Each panel can now be dragged up to nearly full screen (leaving a minimum for the conversation pane), while the cap updates on window resize and the rendered width is clamped so a restored width or a shrinking window can never push a resize handle off-screen. The viewport tracking and width clamping live in one shared composable so the same logic is not duplicated between the two panels. Default widths are unchanged.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

Make the resize handle max width optional so the web sidebar and right-side detail/preview panel can be resized beyond their previous fixed maximums.
@changeset-bot

changeset-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: eac41eb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jun 22, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@eac41eb
npx https://pkg.pr.new/@moonshot-ai/kimi-code@eac41eb

commit: eac41eb

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f7695d9f9a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-web/src/App.vue
Comment on lines 561 to 562
:min="SIDEBAR_MIN"
:max="SIDEBAR_MAX"
@update:width="sessionColWidth = $event"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the sidebar resize handle reachable after restoring wide widths

If a user widens the sidebar on a large display and later opens the app in a narrower window, the persisted sessionColWidth is restored without any upper bound. Because .app has overflow: hidden and the sidebar resize handle sits after the var(--side-w) grid track, a restored width larger than the viewport pushes both the handle and the collapse button off-screen, leaving the conversation inaccessible with no in-UI way to shrink the sidebar. This needs a viewport-aware cap or another reachable recovery path for the sidebar even if fixed 420px limits are removed.

Useful? React with 👍 / 👎.

wbxl2000 added 2 commits June 23, 2026 01:27
Cap the restored sidebar width at a viewport-aware maximum (viewport width minus the conversation pane minimum) so a width saved on a wide display cannot push the resize handle or collapse button off-screen on a narrower window. The cap updates on resize.
Apply the same viewport-aware maximum to the right-side detail/preview panel and extract the viewport tracking and width clamping into a shared composable used by both panels.
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 26e1cd5bf2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-web/src/App.vue
:default-width="SIDEBAR_DEFAULT"
:min="SIDEBAR_MIN"
:max="SIDEBAR_MAX"
:max="sidebarMax"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make resize caps react to viewport changes

When the desktop window grows after the sidebar handle has mounted, this viewport-derived max value updates in App.vue, but ResizeHandle.vue only calls useResizable({ max: props.max }) once during setup and useResizable destructures that initial number. As a result, opening on a narrow window and then widening it still leaves the sidebar clamped to the old smaller maximum until the handle is remounted, so the new viewport-aware cap does not actually let users drag to the newly available width.

Useful? React with 👍 / 👎.

Comment on lines +26 to +28
const sidebarMax = computed(() =>
panelMaxWidth(viewportWidth.value, SIDEBAR_MIN, CONVERSATION_MIN),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reserve space for the preview panel too

When the right-side detail/file panel is open, sidebarMax still reserves only CONVERSATION_MIN from the full viewport and does not account for the preview panel's current/minimum width. For example, on a 1440px desktop viewport the sidebar can be dragged to 1120px while the preview panel remains at its 320px minimum, leaving the conversation column at 0px; this violates the intended invariant that resizing keeps the conversation pane usable and the controls reachable whenever both side panels are visible.

Useful? React with 👍 / 👎.

Make the resize handle read its max width reactively so a viewport-derived cap keeps working as the window grows after mount. Also have the sidebar reserve the preview panel's minimum width whenever the right-side panel is open, so the conversation column can never be squeezed to zero.
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa2ccb3165

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 40 to 44
const sideWidth = computed(() =>
sidebarCollapsed.value ? SIDEBAR_COLLAPSED_WIDTH : sessionColWidth.value,
sidebarCollapsed.value
? SIDEBAR_COLLAPSED_WIDTH
: clampPanelWidth(sessionColWidth.value, SIDEBAR_MIN, sidebarMax.value),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clamp the sidebar content width too

When a saved/sidebar width is above the new viewport-derived cap, this only clamps sideWidth for the grid track; sessionColWidth remains the larger value and is still passed to Sidebar, whose .col is rendered at that width. On a narrower window or after opening the right panel, the grid column shrinks but the sidebar header/list are laid out at the stale larger width, so controls like the collapse button can be clipped or covered by the conversation pane instead of staying reachable.

Useful? React with 👍 / 👎.

Comment thread apps/kimi-web/src/App.vue Outdated

// True while a file preview or any detail panel claims the right-side slot, so
// the sidebar reserves room for it and the conversation can never be squeezed.
const previewOpen = computed(() => detailTarget.value !== null || previewTarget.value !== null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore stale preview targets when reserving panel space

Including previewTarget keeps the sidebar in the “right panel open” max-width mode even after the panel is no longer visible: for example, open a file preview, switch to a thinking/diff panel, then close that panel. openThinkingPanel/openDiffDetail do not clear the previous file preview target, so detailTarget becomes null but previewTarget remains set, capping the sidebar as if 320px were still reserved for a hidden right panel.

Useful? React with 👍 / 👎.

Render the Sidebar content at the clamped width so controls stay reachable when the saved width exceeds the viewport cap. Also stop reserving space for a hidden right panel by keying the sidebar preview-open check off detailTarget instead of the stale previewTarget.
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 455423346e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

function clamp(value: number): number {
if (!Number.isFinite(value)) return defaultWidth;
return Math.min(max, Math.max(min, Math.round(value)));
return Math.min(toValue(max), Math.max(min, Math.round(value)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clamp stored width before starting a drag

When max drops after the handle has mounted (for example, a wide saved sidebar/preview width is rendered clamped after the window narrows or a detail panel opens), the internal width.value can remain at the old larger value because this clamp only runs when setWidth is called. onPointerDown then captures that stale value as startWidth, so the first drag has to cover the invisible delta before the handle moves; users can appear unable to shrink the now-clamped panel until they release and start a second drag. Sync the internal width when the cap changes, or clamp it before assigning startWidth.

Useful? React with 👍 / 👎.

When the saved width exceeds the current cap (after the window narrows or a side panel opens), start the drag from the clamped width so the handle responds immediately instead of first covering an invisible delta.
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f98d168be4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-web/src/App.vue
// room for it and the conversation can never be squeezed. Keyed off detailTarget
// (the real occupant) rather than previewTarget, which can stay set after the
// panel is hidden.
const previewOpen = computed(() => detailTarget.value !== null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reserve sidebar width only for visible side panels

On desktop, when the user runs bare /btw to close an open side chat, handleCommand calls client.closeSideChat() directly and leaves detailTarget === 'btw'. sidePanelVisible then becomes false because client.sideChatVisible is false, but this computed still stays true, so useSidebarLayout keeps subtracting PREVIEW_MIN from the sidebar maximum after the right panel is gone. That leaves the session sidebar capped at viewport - 640 until some other action clears detailTarget; base this reservation on the actually visible panel state or clear detailTarget on the /btw close path.

Useful? React with 👍 / 👎.

The bare /btw close path called client.closeSideChat() directly, which hid the panel but left detailTarget set to 'btw', so the sidebar kept reserving room for a hidden right panel. Route it through the detail-layer close which clears detailTarget.
@wbxl2000

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: eac41eb9ec

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@wbxl2000 wbxl2000 merged commit 92c2cf0 into main Jun 23, 2026
8 checks passed
@wbxl2000 wbxl2000 deleted the feat/web-unbounded-panel-width branch June 23, 2026 05:14
@github-actions github-actions Bot mentioned this pull request Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant