Skip to content

feat: drag-to-resize sidebar width#170

Open
ssiohan wants to merge 2 commits into
erictli:mainfrom
ssiohan:feature/resizable-sidebar
Open

feat: drag-to-resize sidebar width#170
ssiohan wants to merge 2 commits into
erictli:mainfrom
ssiohan:feature/resizable-sidebar

Conversation

@ssiohan

@ssiohan ssiohan commented Jun 10, 2026

Copy link
Copy Markdown

Summary

  • Add an interactive drag handle on the right edge of the sidebar to customize its width
  • The handle appears on hover; drag to resize in real-time with a live px indicator
  • Keyboard accessible: focus the handle, then ←/→ (16px), Shift+←/→ (64px), Home/End (min/max)
  • Double-click resets to the original width
  • Opt-in by default: the sidebar keeps its original 16rem width until you resize it; a custom width is then clamped to 180–800px and persisted in settings as sidebarWidthPx
  • Hidden while the sidebar is collapsed or in focus mode
  • Included in "Reset to defaults"

Changes

File Description
src-tauri/src/lib.rs Add sidebarWidthPx to the persisted Settings struct
src/types/note.ts Add sidebarWidthPx to Settings
src/lib/sidebar.ts New: shared sidebar width bounds (min/max)
src/context/ThemeContext.tsx Sidebar width state (null until resized), validated load, setters, reset, --sidebar-width variable
src/components/layout/SidebarResizeHandle.tsx New: drag + keyboard resize handle with live indicator and double-click reset
src/components/layout/Sidebar.tsx Let the sidebar root fill its container (w-64w-full)
src/App.tsx Drive sidebar width via --sidebar-width (fallback 16rem), mount the handle
src/App.css Suppress the sidebar transition during drag

Test plan

  • npm run build passes
  • cargo clippy -- -D warnings passes
  • Handle appears on hover at the right edge of the sidebar
  • Dragging resizes the sidebar and its content in real-time with a px indicator
  • Keyboard: ←/→ (16px), Shift+←/→ (64px), Home/End (min/max); focus indicator visible
  • Double-click resets to the original width
  • Width persists after closing and reopening the app
  • No change to the default layout until the sidebar is resized
  • Hidden in focus mode / when the sidebar is collapsed

Summary by CodeRabbit

  • New Features
    • Users can now resize the sidebar by dragging the separator handle; width can be adjusted with Arrow keys (Shift for larger steps) and Home/End to jump to min/max.
    • Double-click the resize handle to reset the sidebar width to the default.
    • Sidebar width preference is saved per folder and restored on return visits.
  • UX Improvements
    • Resize interaction temporarily suppresses sidebar transitions for a smoother drag.
    • The resize handle is shown only when the sidebar is visible (not in focus mode).

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f1a078df-6a8f-4389-9b7f-c91aa3f40240

📥 Commits

Reviewing files that changed from the base of the PR and between 79448e0 and 20ce677.

📒 Files selected for processing (4)
  • src-tauri/src/lib.rs
  • src/components/layout/SidebarResizeHandle.tsx
  • src/context/ThemeContext.tsx
  • src/lib/sidebar.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src-tauri/src/lib.rs
  • src/lib/sidebar.ts
  • src/context/ThemeContext.tsx
  • src/components/layout/SidebarResizeHandle.tsx

📝 Walkthrough

Walkthrough

Adds interactive sidebar width resizing with persistent storage. New SidebarResizeHandle component enables pointer drag and keyboard navigation (Arrow keys, Home/End) to adjust width between min/max bounds, with live CSS updates during drag and committed persistence to backend settings via theme context.

Changes

Resizable Sidebar Feature

Layer / File(s) Summary
Type contracts and resize bounds
src/lib/sidebar.ts, src/types/note.ts, src-tauri/src/lib.rs
Export SIDEBAR_MIN_PX (180) and SIDEBAR_MAX_PX (800) constants defining the valid resize range. Frontend Settings interface and backend Rust Settings struct both add optional sidebarWidthPx field for persistence.
Theme context state and persistence
src/context/ThemeContext.tsx
Extend ThemeContextType with sidebarWidthPx state and two setters. Load and validate width from backend on init. setSidebarWidthPx persists to backend with clamping and null-to-reset semantics. setSidebarWidthLive updates CSS variable immediately during drag. New effect syncs state to --sidebar-width CSS variable. Integrate width reset into editor/font reset flow.
Sidebar resize handle component
src/components/layout/SidebarResizeHandle.tsx
React component with full pointer and keyboard interaction. Pointer handlers (down/move/up/cancel) track drag state, compute width deltas, apply clamping. Keyboard handlers support ArrowLeft/Right with Shift modifier for larger steps, plus Home/End to jump to bounds. Double-click resets to default. Disables transitions during drag and displays width tooltip. ARIA-accessible separator element.
Layout component integration and styling
src/App.tsx, src/components/layout/Sidebar.tsx, src/App.css
App.tsx imports and conditionally renders SidebarResizeHandle when sidebar is visible and focus mode inactive. Sidebar container uses inline style.width for dynamic sizing instead of fixed Tailwind classes. Sidebar.tsx component root width changed to w-full to fill allocated space. CSS rule disables transitions on sidebar during drag via .sidebar-no-transition [data-sidebar] selector.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant Handle as SidebarResizeHandle
  participant Theme as ThemeContext
  participant CSS as CSS/DOM
  participant Backend as Backend

  rect rgba(200, 220, 255, 0.5)
    Note over User,Backend: Sidebar Width Initialization
    Theme->>Backend: Load settings
    Backend-->>Theme: Return sidebarWidthPx (if set)
    Theme->>Theme: Validate and clamp to SIDEBAR_MIN/MAX
    Theme->>CSS: Set --sidebar-width CSS variable
  end

  rect rgba(200, 255, 220, 0.5)
    Note over User,Backend: User Drags Resize Handle
    User->>Handle: Pointer down on separator
    Handle->>Handle: Store start X position and initial width
    Handle->>CSS: Add sidebar-no-transition class
    
    loop Pointer move
      User->>Handle: Move pointer
      Handle->>Handle: Compute width delta and clamp
      Handle->>Theme: setSidebarWidthLive(px)
      Theme->>CSS: Update --sidebar-width immediately
      Handle->>Handle: Update and show width tooltip
    end
    
    User->>Handle: Release pointer
    Handle->>Theme: setSidebarWidthPx(px)
    Theme->>Backend: Persist clamped width
    Theme->>CSS: Remove sidebar-no-transition
    Handle->>Handle: Clear drag state
  end

  rect rgba(255, 220, 220, 0.5)
    Note over User,Backend: Double-Click Reset
    User->>Handle: Double-click separator
    Handle->>Theme: setSidebarWidthPx(null)
    Theme->>Backend: Persist undefined (reset)
    Theme->>CSS: Remove --sidebar-width variable
  end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested Reviewers

  • erictli

Poem

A sidebar stretches, contracts, glides,
Dragged by your cursor, left and right—
CSS whispers, theme context decides,
Pixels persist through the fuzzy night. 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: drag-to-resize sidebar width' accurately describes the main feature addition—interactive sidebar resizing via dragging—which is the primary focus of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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.

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