Skip to content

feat: collapsible sidebar#2305

Open
basmilius wants to merge 5 commits intopingdotgg:mainfrom
basmilius:feat/collapsible-sidebar
Open

feat: collapsible sidebar#2305
basmilius wants to merge 5 commits intopingdotgg:mainfrom
basmilius:feat/collapsible-sidebar

Conversation

@basmilius
Copy link
Copy Markdown
Contributor

@basmilius basmilius commented Apr 23, 2026

What Changed

  • Added a sidebar.toggle keybinding command bound to mod+b by default, gated on when: "!terminalFocus" so it stays out of the way inside the terminal drawer.
  • Added a matching Toggle sidebar action to the command palette that surfaces the active shortcut hint.
  • Lifted SidebarProvider to the root layout so both the palette and the global chat shortcut handler can call useSidebar().toggleSidebar().
  • Exposed sidebar open/collapsed state via data-state on the sidebar wrapper so chrome can react with group-data-* classes instead of reading the context everywhere.
  • Electron drag-region headers (ChatView, NoActiveThreadState, settings) reserve pl-[90px] when the sidebar is collapsed so the macOS traffic lights don't overlap the active title. Windows/Linux fall through to the existing wco: overrides. The padding transitions at the same duration-200 ease-linear as the sidebar width, so it slides in sync.
  • Ran the sidebar toggle on the capture phase because Lexical's core onKeyDown claims mod+b for the bold command and calls preventDefault, which would trip the event.defaultPrevented guard in the shared handler.
  • Updated apps/web/src/keybindings.test.ts, apps/server/src/keybindings.test.ts defaults, and KEYBINDINGS.md.

Why

Closes #2282. The thread sidebar was always visible, which made it hard to fully focus on the active chat. A toggle is the smallest useful change that enables focus mode while keeping thread switching (mod+1..9, mod+shift+[/]) available even when the sidebar is collapsed — those listeners live on window in Sidebar.tsx and the sidebar DOM stays mounted under collapsible="offcanvas", so nothing extra was needed to satisfy that requirement from the issue.

Reusing the existing SidebarProvider / useSidebar() / cookie persistence already shipped in ui/sidebar.tsx kept the diff small and means sidebar state still survives reloads.

UI Changes

Video attached showing open → collapsed → open with mod+b, thread switching while collapsed, and the animated header padding on macOS so the traffic lights aren't covered.

Schermopname.2026-04-23.om.12.20.58.mov

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

Medium Risk
Introduces a new global shortcut (mod+b) and capture-phase keydown handler to toggle the sidebar, which can affect keyboard event precedence and editor behavior. Also changes layout/provider wiring and Electron header padding based on sidebar state, with moderate UI regression risk.

Overview
Adds a new sidebar.toggle command (default mod+b when !terminalFocus) and surfaces it as a Toggle sidebar action in the command palette.

Moves SidebarProvider to the authenticated root so both the command palette and chat route global shortcuts can call useSidebar().toggleSidebar(), and exposes sidebar state via data-state on the sidebar wrapper for styling.

Updates Electron drag-region headers (chat, empty state, settings) to adjust left padding with a transition when the sidebar is collapsed, and adds tests/docs for the new default binding (including a capture-phase handler so the toggle wins over in-editor mod+b).

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

Note

Add collapsible sidebar with mod+b keyboard shortcut

  • Adds a sidebar.toggle command bound to mod+b (when not in terminal focus) as a default keybinding in shared/src/keybindings.ts and registered in the keybindings contract.
  • Moves SidebarProvider from AppSidebarLayout up to the root route so CommandPalette and the global shortcut handler can both access sidebar context.
  • Adds a capture-phase keydown handler in _chat.tsx that intercepts mod+b before Lexical's bold handler can claim it.
  • Exposes data-state on the sidebar wrapper div, allowing ChatView and NoActiveThreadState headers to animate left-padding on collapse via CSS group selectors.
  • Adds a 'Toggle sidebar' action to the command palette with the sidebar.toggle shortcut.

Macroscope summarized 8f620b9.

Adds a `sidebar.toggle` keybinding command so users can collapse and
re-expand the thread sidebar to focus on the active chat, addressing
pingdotgg#2282. The default shortcut is `mod+b` and is gated on
`!terminalFocus` so it doesn't interfere with shell shortcuts.

- Contract: register `sidebar.toggle` as a static keybinding command.
- Server: add the default rule so it gets backfilled into the user's
  keybindings.json on startup.
- Web: lift `SidebarProvider` to the root so both the command palette
  and the global keydown handler in `_chat.tsx` can call
  `useSidebar().toggleSidebar()`. Expose sidebar state via
  `data-state` on the wrapper so header chrome can react without
  calling `useSidebar()`.
- Palette: add a "Toggle sidebar" action with the bound shortcut hint.
- Chrome: reserve 90px padding-left on the Electron drag-region
  headers when the sidebar is collapsed, so the macOS traffic lights
  don't overlap the active title; animate the padding to match the
  sidebar's width transition.
- Tests + docs updated.
Lexical's core keydown handler claims mod+b for the bold formatting
command and calls preventDefault, even under PlainTextPlugin. The
existing `event.defaultPrevented` guard in the global chat shortcut
handler then dropped the sidebar toggle before we could act.

Move sidebar.toggle into its own effect bound on the capture phase so
we see the event before Lexical does, and stopPropagation to keep it
from reaching the editor. Other shortcuts (chat.new, chat.newLocal)
stay on the bubble-phase listener since Lexical doesn't intercept
their keys.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 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: 1266c9c1-81dc-414d-9017-06d0559c05dd

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:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 23, 2026
@basmilius basmilius changed the title Feat/collapsible sidebar feat: collapsible sidebar Apr 23, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 92c64f5. Configure here.

Comment thread apps/web/src/routes/_chat.tsx
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Apr 23, 2026

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature allowing users to collapse/expand the sidebar via mod+b shortcut. While well-implemented with tests, new UI capabilities warrant human review to ensure the behavior meets product expectations.

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

The bubble-phase handler in ChatRouteGlobalShortcuts already bails out
when useCommandPaletteStore.getState().open is true. The new
capture-phase listener for sidebar.toggle was missing that guard, so
mod+b would collapse the sidebar behind the open dialog.

Flagged by Cursor Bugbot on PR pingdotgg#2305.
@basmilius
Copy link
Copy Markdown
Contributor Author

@juliusmarminge Do I need to authenticate with Vercel or is it something that needs approval?

@Almighty-Shogun
Copy link
Copy Markdown

For someone who doesn't use T3 on fullscreen, this is very usefull!

basmilius added 2 commits May 1, 2026 11:15
…debar

# Conflicts:
#	apps/web/src/components/AppSidebarLayout.tsx
#	apps/web/src/components/ChatView.tsx
# Conflicts:
#	apps/server/src/keybindings.ts
#	apps/web/src/components/CommandPalette.tsx
#	apps/web/src/routes/__root.tsx
@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

@basmilius is attempting to deploy a commit to the Ping Labs Team on Vercel.

A member of the Team first needs to authorize it.

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

Labels

size:M 30-99 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.

[Feature]: Collapsible sidebar

2 participants