Skip to content

fix: hide side menu on scroll instead of overflow hacks#2630

Merged
YousefED merged 3 commits intomainfrom
fix/hide-side-menu-on-scroll
Apr 7, 2026
Merged

fix: hide side menu on scroll instead of overflow hacks#2630
YousefED merged 3 commits intomainfrom
fix/hide-side-menu-on-scroll

Conversation

@YousefED
Copy link
Copy Markdown
Collaborator

@YousefED YousefED commented Apr 7, 2026

Summary

Hide the side menu when the user scrolls, preventing it from overflowing outside the editor's scroll container (e.g. in docs demos). This reverts the CSS workarounds introduced in #2043 in favor of a proper floating-ui–based solution.

Rationale

PR #2043 added overflow: none and position: relative hacks to the docs demo containers to prevent the side menu from visually escaping the demo box. This approach was fragile and didn't address the root cause. The proper fix is to hide the side menu on scroll — the same UX pattern used for keyboard input.

We prefer to handle this on the floating-ui layer instead of adding additional event listeners in the SideMenu extension, as we're trying to refactor more logic out of our custom extensions and into standard floating-ui patterns.

Changes

  • docs/app/styles.css — Removed .demo { overflow: none } and .demo .bn-container { position: relative } from docs: Made UI elements no longer overflow demo box #2043
  • GenericPopover.tsx — Added mergeWhileElementsMounted helper that composes the default autoUpdate with any additional whileElementsMounted handler provided via props
  • SideMenuController.tsx — Added a whileElementsMounted handler using autoUpdate with ancestorScroll: true to detect scroll and call hideMenuIfNotFrozen()
  • SideMenu.ts — Added hideMenuIfNotFrozen() extension method that hides the menu only when it's not frozen (i.e. drag handle submenu is not open)

Impact

  • Side menu now hides on scroll in any context (not just docs demos)
  • No impact on drag handle submenu — hideMenuIfNotFrozen respects the frozen state
  • GenericPopover's new merge behavior is backwards-compatible: when no whileElementsMounted is passed, behavior is identical to before

Testing

  • Manual testing: verified side menu hides on scroll in docs demos and playground
  • Verified drag handle submenu stays open during scroll (frozen state respected)

Checklist

  • Code follows the project's coding standards.
  • Unit tests covering the new feature have been added.
  • All existing tests pass.
  • The documentation has been updated to reflect the new feature

Additional Notes

Reverts CSS changes from #2043.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Side menu now automatically hides when not frozen during interactions.
    • Table handles (and related controls) now auto-hide when not frozen during interactions.
  • Refactor

    • Improved Floating UI lifecycle integration for more stable popovers and handle positioning.
  • Style

    • Simplified demo container styling (removed certain overflow/position rules), which may affect demo layout/stacking.

Reverts the overflow/positioning workarounds from #2043 and instead
hides the side menu when the user scrolls, preventing it from
overflowing outside the editor's scroll container.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blocknote Ready Ready Preview Apr 7, 2026 1:59pm
blocknote-website Ready Ready Preview Apr 7, 2026 1:59pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7cf5f367-652c-4e6a-87ce-290472beb4ab

📥 Commits

Reviewing files that changed from the base of the PR and between de5f4c6 and d63e8f7.

📒 Files selected for processing (2)
  • packages/core/src/extensions/TableHandles/TableHandles.ts
  • packages/react/src/components/TableHandles/TableHandlesController.tsx

📝 Walkthrough

Walkthrough

Adds auto-hide callbacks for side menu and table handles invoked from Floating UI mounted callbacks; GenericPopover now merges default autoUpdate with user-provided whileElementsMounted; minor CSS cleanup removing .demo overflow/position rules. (49 words)

Changes

Cohort / File(s) Summary
CSS Cleanup
docs/app/styles.css
Removed .demo and .demo .bn-container rules: eliminated overflow: none and position: relative.
Side Menu Extension
packages/core/src/extensions/SideMenu/SideMenu.ts
Added hideMenuIfNotFrozen() extension method that, when menu is not frozen and visible, sets view.state.show = false and emits an update.
Side Menu Controller
packages/react/src/components/SideMenu/SideMenuController.tsx
Passes a whileElementsMounted callback to Floating UI that uses autoUpdate({ ancestorScroll: true, ... }) and calls editor.getExtension(SideMenuExtension)?.hideMenuIfNotFrozen() after initial mount.
Table Handles Extension
packages/core/src/extensions/TableHandles/TableHandles.ts
Added hideHandlesIfNotFrozen() extension method that clears state.show and hides add/remove row/column buttons when not frozen and currently shown, then emits an update.
Table Handles Controller
packages/react/src/components/TableHandles/TableHandlesController.tsx
Introduced whileElementsMounted callback using autoUpdate({ ancestorScroll: true, ... }); floating options for row/column/cell handles and extend buttons now use this callback and include it in memo deps.
Generic Popover
packages/react/src/components/Popovers/GenericPopover.tsx
Added mergeWhileElementsMounted to combine default autoUpdate handler with any user whileElementsMounted in useFloatingOptions; updated useFloating to use the merged handler and exclude the original whileElementsMounted when spreading options (an unused _whileElementsMounted var is introduced during destructuring).

Sequence Diagram

sequenceDiagram
    participant FUI as Floating UI
    participant CTRL as SideMenuController
    participant EDIT as Editor (getExtension)
    participant EXT as SideMenuExtension
    participant STATE as View State

    FUI->>CTRL: whileElementsMounted (mount)
    Note over CTRL: initial mount recorded
    FUI->>CTRL: whileElementsMounted (ancestorScroll/update)
    CTRL->>EDIT: getExtension(SideMenuExtension)
    EDIT->>EXT: hideMenuIfNotFrozen()
    EXT->>EXT: if !menuFrozen and state.show
    alt Menu not frozen & visible
        EXT->>STATE: set state.show = false
        EXT->>STATE: emitUpdate(state)
    end
    FUI->>CTRL: cleanup (unmount)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐇 I tuck the menu when ancestor winds play,
Two handlers dance and tidy the way,
If not frozen, I nudge things out of sight,
Handles hide softly in scrolling flight,
A little hop, and everything’s light.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: replacing CSS overflow hacks with a floating-ui solution to hide the side menu on scroll.
Description check ✅ Passed The description is well-structured with all major template sections completed: Summary, Rationale, Changes, Impact, Testing, Checklist, and Additional Notes. All key information is provided.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/hide-side-menu-on-scroll

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.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 7, 2026

Open in StackBlitz

@blocknote/ariakit

npm i https://pkg.pr.new/@blocknote/ariakit@2630

@blocknote/code-block

npm i https://pkg.pr.new/@blocknote/code-block@2630

@blocknote/core

npm i https://pkg.pr.new/@blocknote/core@2630

@blocknote/mantine

npm i https://pkg.pr.new/@blocknote/mantine@2630

@blocknote/react

npm i https://pkg.pr.new/@blocknote/react@2630

@blocknote/server-util

npm i https://pkg.pr.new/@blocknote/server-util@2630

@blocknote/shadcn

npm i https://pkg.pr.new/@blocknote/shadcn@2630

@blocknote/xl-ai

npm i https://pkg.pr.new/@blocknote/xl-ai@2630

@blocknote/xl-docx-exporter

npm i https://pkg.pr.new/@blocknote/xl-docx-exporter@2630

@blocknote/xl-email-exporter

npm i https://pkg.pr.new/@blocknote/xl-email-exporter@2630

@blocknote/xl-multi-column

npm i https://pkg.pr.new/@blocknote/xl-multi-column@2630

@blocknote/xl-odt-exporter

npm i https://pkg.pr.new/@blocknote/xl-odt-exporter@2630

@blocknote/xl-pdf-exporter

npm i https://pkg.pr.new/@blocknote/xl-pdf-exporter@2630

commit: d63e8f7

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/extensions/SideMenu/SideMenu.ts`:
- Around line 793-797: The method hideMenuIfNotFrozen currently sets
view.state.show = false and calls view.emitUpdate even when the menu is already
hidden; update hideMenuIfNotFrozen to first check that view.state.show is truthy
(and that view exists and is not frozen via view!.menuFrozen) and only then set
show = false and call view!.emitUpdate(view!.state!) to avoid redundant
emissions and re-renders; reference hideMenuIfNotFrozen, view!.menuFrozen,
view!.state!.show, and view!.emitUpdate when locating the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a8eecee9-d1d3-4e88-b69a-77deee5684fd

📥 Commits

Reviewing files that changed from the base of the PR and between 38be5fd and a904e58.

📒 Files selected for processing (4)
  • docs/app/styles.css
  • packages/core/src/extensions/SideMenu/SideMenu.ts
  • packages/react/src/components/Popovers/GenericPopover.tsx
  • packages/react/src/components/SideMenu/SideMenuController.tsx
💤 Files with no reviewable changes (1)
  • docs/app/styles.css

Copy link
Copy Markdown
Contributor

@nperez0111 nperez0111 left a comment

Choose a reason for hiding this comment

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

using floating ui for the scroll dismiss seems like a bit of an abuse, but it works

@nperez0111
Copy link
Copy Markdown
Contributor

table handles would likely want the same fix applied, but it is super minor

Apply the same scroll-hide pattern to table handles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@YousefED YousefED merged commit c651dc6 into main Apr 7, 2026
30 of 32 checks passed
@YousefED YousefED deleted the fix/hide-side-menu-on-scroll branch April 7, 2026 17:19
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.

2 participants