Skip to content

Conversation

@matthewlipski
Copy link
Collaborator

@matthewlipski matthewlipski commented Dec 3, 2025

Summary

This PR makes it so that the height of the side menu is now set in FloatingUI middleware on SideMenuController. This is a change from the old method, which uses a more convoluted useEffect hook + CSS.

The side menu height is set in order to make it appear vertically centred for some blocks, and aligned top for others. While this is also possible with the placement option in useFloatingProps, it's not exactly that simple due to e.g. file blocks with captions. For these, we want the side menu ignore the caption for the vertical alignment, so it's actually centred relative to the block.

Additionally, two bugs with the file panel and side menu have been fixed. The file panel would show up below any nested blocks, while the side menu was horizontally indented with nested blocks. These were fixed by adding more options to the BlockPopover component, detailed in the changes list below.

Rationale

This continues with the theme of moving responsibilities to FloatingUI where possible, which we started doing as part of the major refactor in #2143. The bugs are also regressions that should be fixed.

Changes

  • Removed useEffect hook from SideMenu component.
  • Removed setting side menu height in CSS.
  • Added size middleware to SideMenuController to set the side menu height.
  • Added includeNestedBlocks option to BlockPopover. When true, this works the same as before, using the entire block as the reference element. When false, it uses the block's content as the reference element. Defaults to true.
  • Added spanEditorWidth option to BlockPopover. When false, this works the same as before, where the boundingClientRect is the same size & position as the reference element. When true, the x position and width are used for the boundingClientRect, and only the reference element y position and height are used.

Impact

This actually also fixes a previously unknown bug with the file panel thanks to that addition of includeNestedBlocks. Because it used the whole block as the reference element, it would show beneath all child blocks.

Testing

Went through the Notion UI testing doc to ensure no regressions for UI elements using the BlockPopover (file panel, side menu & AI menu). Added test cases to all UI elements for nested blocks.

Screenshots/Video

N/A

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

@vercel
Copy link

vercel bot commented Dec 3, 2025

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

Project Deployment Preview Updated (UTC)
blocknote Ready Ready Preview Dec 3, 2025 4:49pm
blocknote-website Ready Ready Preview Dec 3, 2025 4:49pm

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 3, 2025

Open in StackBlitz

@blocknote/ariakit

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/ariakit@2224

@blocknote/code-block

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/code-block@2224

@blocknote/core

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/core@2224

@blocknote/mantine

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/mantine@2224

@blocknote/react

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/react@2224

@blocknote/server-util

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/server-util@2224

@blocknote/shadcn

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/shadcn@2224

@blocknote/xl-ai

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-ai@2224

@blocknote/xl-docx-exporter

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-docx-exporter@2224

@blocknote/xl-email-exporter

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-email-exporter@2224

@blocknote/xl-multi-column

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-multi-column@2224

@blocknote/xl-odt-exporter

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-odt-exporter@2224

@blocknote/xl-pdf-exporter

npm i https://pkg.pr.new/TypeCellOS/BlockNote/@blocknote/xl-pdf-exporter@2224

commit: 785bc45

Copy link
Collaborator

@YousefED YousefED left a comment

Choose a reason for hiding this comment

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

see comments.

Also it made me think of a separate thing; did we test the block-side menu in multi-column? afaik it wasn't listed under the test cases

return {
element: node,
};
const blockContentElement = blockElement.firstElementChild;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure I like the use of firstElementChild. It assumes a specific dom structure to get the dom element - which is not typesafe / futureproof.

Better approach would be to use the methods we have like getblockinfo to get the content block, and then call getdomatpos for it

(example; the current approach would probably break for column blocks which don't have blockContent)

middleware: [
size({
apply({ elements }) {
// TODO: Need to fetch the block from extension, else it's
Copy link
Collaborator

Choose a reason for hiding this comment

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

this code is called in useMemo, so the apply function only gets recreated when the deps array changes


if (block.type === "heading") {
if (!block.props.level || block.props.level === 1) {
elements.floating.style.setProperty("height", "78px");
Copy link
Collaborator

Choose a reason for hiding this comment

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

we can't base this on pixels here. What if someone changes the font or font-size in css?

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.

3 participants