Skip to content

Comments

feat: Add copilot sidebar mode with drag-to-resize#2785

Open
EyalAmitay wants to merge 9 commits intoChainlit:mainfrom
EyalAmitay:feat/copilot-sidebar-with-resize
Open

feat: Add copilot sidebar mode with drag-to-resize#2785
EyalAmitay wants to merge 9 commits intoChainlit:mainfrom
EyalAmitay:feat/copilot-sidebar-with-resize

Conversation

@EyalAmitay
Copy link
Contributor

@EyalAmitay EyalAmitay commented Feb 18, 2026

Summary

Adds a new sidebar display mode for the copilot widget. Instead of the default floating popover, the copilot can now render as a full-height side panel anchored to the right edge of the viewport, pushing the host page content to make room. Users can drag the left edge to resize and switch between sidebar and floating modes via a dropdown in the header.

image

Changes

  • Sidebar display mode: Right-side sidebar panel as an alternative to the floating popover
  • Drag-to-resize: Left-edge drag handle (300px min, 50% viewport max) with smooth transitions
  • Display mode toggle: Header dropdown to switch between "Floating" and "Sidebar"; close button in sidebar mode
  • Persistence: Sidebar width and display mode saved to localStorage across sessions
  • useSidebarResize hook: Encapsulates resize logic, body margin management, and drag lifecycle (including window.blur handling for edge cases)
  • DisplayMode type: Consolidated into types.ts, replacing inline string unions

Backward Compatibility

Fully backward compatible — no breaking changes to any existing API or behavior.

  • The displayMode option in IWidgetConfig is additive and optional; defaults to 'floating' when not specified, preserving existing behavior
  • Existing mountChainlitWidget() calls without displayMode work unchanged
  • unmountChainlitWidget() continues to work as before
  • Two new localStorage keys are introduced (chainlit-copilot-displayMode, chainlit-copilot-sidebarWidth) — only read/written when the feature is used, no effect on existing deployments

Configuration

To default to the sidebar mode:

window.mountChainlitWidget({
  chainlitServer: 'http://localhost:8000',
  displayMode: 'sidebar',
});

Test plan

  • E2E: Sidebar opens and pushes body content
  • E2E: Sidebar closes and restores body margin
  • E2E: Drag handle resizes sidebar and updates body margin
  • E2E: Switch between sidebar and floating mode
  • E2E: Unmount cleanup restores body margin
  • E2E: localStorage persistence survives widget remount
  • Build and lint pass
  • Manual: Open, drag left edge to resize
  • Manual: State persists in localstorage
Screen.Recording.2026-02-18.at.5.54.15.PM.mov
image

EyalAmitay and others added 9 commits February 18, 2026 13:37
Add sidebar display mode as an alternative to the floating popover.
The sidebar opens as a fixed panel on the right edge with a drag handle
on the left edge for Notion-style resize (300px min, 50% viewport max).
Width persists to localStorage. Includes display mode toggle in header
and E2E tests for sidebar open/close/resize/mode-switch.
- Fix stale originalMargin capture by splitting into lifecycle + sync effects
  so the true original margin is captured once on open via ref, not re-captured
  on every width change
- Fix userSelect not restored on unmount when drag is in progress
- Fix CSS transition lag during drag by disabling transition on mousedown
  and re-enabling on mouseup
- Add window.blur handler to cancel stuck drags when mouse released outside browser
- Extract resize logic into useSidebarResize hook, consolidate DisplayMode type
- Deduplicate chatContent and renderButtonIcon in widget.tsx
- Add E2E tests for unmount cleanup and localStorage persistence across remounts
Replace drag-based resize test with localStorage pre-set approach.
The Cypress trigger-based drag simulation was unreliable in CI headless
mode, causing the test to fail with 'expected 400 to be above 400'.
- Add copilot.displayMode translation keys to all 20 language files
- Use useTranslation in Header for Floating/Sidebar dropdown labels
- Remove unnecessary code comments across modified files
- Remove backward-compat regression: stop clearing body margin/transition
  in unmountChainlitWidget (React cleanup handles it)
- Guard localStorage write to only persist sidebar width in sidebar mode
- Gate mousemove/mouseup/blur listeners on sidebar mode and open state
- Remove hidden test-only button from sidebar production code
- Remove renderButtonIcon and inline icon in sidebar closed-state button
- Revert unrelated formatting changes in test file
- Remove unnecessary non-null assertions in tests
Disable Radix UI's modal scroll-lock on the display mode DropdownMenu,
which was adding overflow:hidden and padding-right to document.body.
@EyalAmitay EyalAmitay marked this pull request as ready for review February 18, 2026 15:33
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. frontend Pertains to the frontend. labels Feb 18, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 6 files

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

Labels

frontend Pertains to the frontend. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant