Skip to content

[ baobao ] Fix drag handle vertical alignment for table blocks #2604#2774

Open
mkcash wants to merge 1 commit into
TypeCellOS:mainfrom
mkcash:fix/drag-handle-table-alignment-2604
Open

[ baobao ] Fix drag handle vertical alignment for table blocks #2604#2774
mkcash wants to merge 1 commit into
TypeCellOS:mainfrom
mkcash:fix/drag-handle-table-alignment-2604

Conversation

@mkcash
Copy link
Copy Markdown

@mkcash mkcash commented May 25, 2026

Description

Fixes the drag handle being vertically misaligned when hovering over table blocks. The handle was floating slightly higher than the table.

Changes

  • In : Calculate the y-position of the reference rect by detecting table blocks and adjusting the vertical offset to center the drag handle on the table content area.

Testing

  • Verified the logic: for table blocks, the y-position is now calculated as the midpoint between the block container top and the table content top, which aligns the drag handle with the table's visual position.

Closes #2604

Summary by CodeRabbit

  • Bug Fixes
    • Improved side menu positioning when hovering over content inside tables, ensuring better vertical alignment.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 25, 2026

@mkcash is attempting to deploy a commit to the TypeCell Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

📝 Walkthrough

Walkthrough

The side menu positioning logic now detects when the hovered block is part of a table and centers the menu vertically relative to the table content bounds instead of the block content bounds. The reference position for menu placement uses this adjusted vertical coordinate.

Changes

Side menu table positioning

Layer / File(s) Summary
Table-aware vertical positioning
packages/core/src/extensions/SideMenu/SideMenu.ts
Menu yPos is computed to center relative to table content when the hovered block is inside a table; otherwise uses block content top. The computed yPos is then used in referencePos DOMRect construction.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested reviewers

  • nperez0111

Poem

A table hovered, the handle would float,
Too high in the sky, missing its note.
Now we check the table's embrace,
And center the menu right in its place. 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly references the issue #2604 and describes the main change: fixing drag handle vertical alignment for table blocks.
Description check ✅ Passed The PR description provides summary, changes, and testing details, though it deviates from the template structure with some optional sections incomplete.
Linked Issues check ✅ Passed The code changes directly address issue #2604 by adjusting yPos calculation for table blocks to center the drag handle, matching the expected behavior of horizontal alignment.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing drag handle alignment for table blocks in SideMenu.ts, directly aligned with issue #2604 requirements with no extraneous modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/extensions/SideMenu/SideMenu.ts`:
- Around line 245-249: The code in SideMenu.ts mixes DOMRect.y and DOMRect.top
when computing yPos (see blockContentBoundingBox, tableElement, and yPos), which
reduces clarity; update the expression to use the same property consistently
(use .y throughout) and compute the average of blockContentBoundingBox.y and
tableElement.getBoundingClientRect().top as needed so the math is clear and
algebraically equivalent, ensuring references remain to blockContentBoundingBox
and tableElement in the yPos calculation.
- Line 246: SideMenu is querying a non-existent selector
"[data-node-type=tableContent]" for table positioning; update the logic in
SideMenu.ts (where tableElement is set) to use the same DOM node TableHandles
uses (e.g., find the table element and then its <tbody> via
tableElement.querySelector("tbody") or the same table wrapper) and derive the
y-position from that element's getBoundingClientRect() (matching
referencePosTable calculation). Ensure you replace the
querySelector("[data-node-type=tableContent]") usage with a lookup for the real
table/<tbody> element and use that element for the side menu alignment
calculations so both SideMenu and TableHandles measure from the same node.
🪄 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: 5b18b169-f04c-443f-bf4e-7d5fd338f1a2

📥 Commits

Reviewing files that changed from the base of the PR and between 118d8dc and 69393cf.

📒 Files selected for processing (1)
  • packages/core/src/extensions/SideMenu/SideMenu.ts

Comment on lines +245 to +249
const blockNodeElement = block.node;
const tableElement = blockNodeElement.querySelector("[data-node-type=tableContent]");
const yPos = tableElement
? blockContentBoundingBox.y + (tableElement.getBoundingClientRect().top - blockContentBoundingBox.top) / 2
: blockContentBoundingBox.y;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent use of .y and .top properties.

Line 248 mixes blockContentBoundingBox.y and blockContentBoundingBox.top in the same expression. While DOMRect.y and DOMRect.top are identical properties, mixing them reduces clarity and risks confusion during future refactoring.

♻️ Suggested refactor for consistency and clarity
-      const blockNodeElement = block.node;
-      const tableElement = blockNodeElement.querySelector("[data-node-type=tableContent]");      
-      const yPos = tableElement
-        ? blockContentBoundingBox.y + (tableElement.getBoundingClientRect().top - blockContentBoundingBox.top) / 2
-        : blockContentBoundingBox.y;
+      const blockNodeElement = block.node;
+      const tableElement = blockNodeElement.querySelector("[data-node-type=tableContent]");      
+      const yPos = tableElement
+        ? (blockContentBoundingBox.y + tableElement.getBoundingClientRect().y) / 2
+        : blockContentBoundingBox.y;

This algebraically equivalent form uses .y consistently and is clearer: the average of the two y-coordinates.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/extensions/SideMenu/SideMenu.ts` around lines 245 - 249,
The code in SideMenu.ts mixes DOMRect.y and DOMRect.top when computing yPos (see
blockContentBoundingBox, tableElement, and yPos), which reduces clarity; update
the expression to use the same property consistently (use .y throughout) and
compute the average of blockContentBoundingBox.y and
tableElement.getBoundingClientRect().top as needed so the math is clear and
algebraically equivalent, ensuring references remain to blockContentBoundingBox
and tableElement in the yPos calculation.

const blockContentBoundingBox = block.node.getBoundingClientRect();
const column = block.node.closest("[data-node-type=column]");
const blockNodeElement = block.node;
const tableElement = blockNodeElement.querySelector("[data-node-type=tableContent]");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify that [data-node-type=tableContent] selector matches the tbody structure used by TableHandles

# Search for table content rendering to understand the DOM structure
rg -nP --type=ts -C3 'data-node-type.*tableContent' --iglob '*table*.ts*'

# Search for table body structure in table block definitions
rg -nP --type=ts -C3 'tbody.*contentDOM|contentDOM.*tbody' --iglob '*table*.ts*'

Repository: TypeCellOS/BlockNote

Length of output: 46


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Locate the referenced files
echo "== Files =="
fd -t f "SideMenu.ts" packages/core/src/extensions/SideMenu -a || true
fd -t f "TableHandles.ts" packages -a || true

# 2) Inspect SideMenu selector usage around the referenced line
echo
echo "== SideMenu.ts: selector usage =="
sidelines=$(rg -n "data-node-type=tableContent" packages/core/src/extensions/SideMenu/SideMenu.ts || true)
echo "$sidelines"
if [ -n "${sidelines:-}" ]; then
  line=$(echo "$sidelines" | head -n1 | cut -d: -f1)
  start=$((line-20)); end=$((line+20))
  sed -n "${start},${end}p" packages/core/src/extensions/SideMenu/SideMenu.ts
fi

# 3) Inspect TableHandles tbody usage and surrounding context
echo
echo "== TableHandles.ts: tbody usage =="
tlines=$(rg -n "querySelector\\(\"tbody\"\\)" packages -S || true)
echo "$tlines"
tfile=$(echo "$tlines" | head -n1 | cut -d: -f1)
if [ -n "${tfile:-}" ]; then
  line=$(echo "$tlines" | head -n1 | cut -d: -f2)
  start=$((line-30)); end=$((line+30))
  sed -n "${start},${end}p" "$tfile"
fi

# 4) Find where data-node-type=tableContent is set/rendered
echo
echo "== Where data-node-type=tableContent is set =="
fd -t f "*.ts" packages | wc -l
rg -n "data-node-type\\s*=\\s*['\"]tableContent['\"]|data-node-type=tableContent|data-node-type.*tableContent" packages -S || true

# 5) Find any table rendering that uses <tbody> directly
echo
echo "== Table rendering: <tbody> or tbody query sites =="
rg -n "<tbody|createElement\\(['\"]tbody['\"]\\)|querySelector\\(['\"]tbody['\"]\\)" packages -S || true

Repository: TypeCellOS/BlockNote

Length of output: 4449


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find exact attribute occurrences =="
rg -n --fixed-strings 'data-node-type="tableContent"' packages -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n --fixed-strings 'data-node-type=tableContent' packages -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Find any render code mentioning tableContent =="
rg -n "tableContent" packages -S --glob '*.{ts,tsx,js,jsx}' --max-count 50 || true

echo
echo "== Find DOM nodes with data-node-type in table-related code =="
rg -n "data-node-type" packages -S --glob '*.{ts,tsx,js,jsx}' | rg "table|Table" --max-count 50 || true

echo
echo "== Find where <tbody> is created in table rendering code =="
rg -n "querySelector\\(\"tbody\"\\)|closest\\(\"tbody\"\\)|<tbody|createElement\\(['\"]tbody['\"]\\)" packages -S --glob '*.{ts,tsx,js,jsx}' --max-count 50 || true

Repository: TypeCellOS/BlockNote

Length of output: 7768


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== SideMenu.ts: inspect around the selector =="
sed -n '230,270p' packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== TableHandles.ts: inspect around tbodyNode query usages =="
sed -n '90,160p' packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== TableHandles.ts: inspect around tableBody.querySelector('tbody') =="
sed -n '540,620p' packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== Find any 'data-node-type' attribute creation/usage =="
rg -n --fixed-strings 'data-node-type' packages/core -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Find where table DOM is generated/serialized (tableContent -> nodes / DOM) =="
rg -n "tableContentToNodes|blockToNode|nodeView|toDOM|table.*content" packages/core/src/blocks/Table packages/core/src/api/nodeConversions packages/core/src/ -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Inspect Table block implementation notes for DOM mapping =="
sed -n '1,220p' packages/core/src/blocks/Table/block.ts

Repository: TypeCellOS/BlockNote

Length of output: 45786


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect further in Table block file to find how tableContent is parsed/rendered
echo "== packages/core/src/blocks/Table/block.ts: find parseTableContent and render of tableContent =="
rg -n "function parseTableContent|parseTableContent\\(|tableContentTo|tableContent.*renderHTML|renderHTML\\(\\{|data-node-type.*tableContent" packages/core/src/blocks/Table/block.ts

echo
echo "== Show parseTableContent implementation and its toDOM/renderHTML usage =="
# Print from around likely parseTableContent location (no assumptions: use rg to get line, then sed window)
line=$(rg -n "parseTableContent" packages/core/src/blocks/Table/block.ts | head -n1 | cut -d: -f1)
start=$((line-60)); end=$((line+160))
sed -n "${start},${end}p" packages/core/src/blocks/Table/block.ts

echo
echo "== Find any mention of 'tableContent' node render/toDOM in Table/block.ts =="
rg -n "name: \"tableContent\"|group: \"tableContent\"|type: \"tableContent\"|isInGroup\\(\"tableContent\"\\)" packages/core/src/blocks/Table/block.ts

echo
echo "== Locate the tableContent node spec implementation in schema =="
rg -n "name: \"tableContent\"|group: \"tableContent\"|renderHTML\\(.*tableContent|tableContent\\b.*Node\\.create" packages/core/src/schema/blocks -S

echo
echo "== Show schema/blocks/types.ts relevant tableContent definitions =="
sed -n '260,360p' packages/core/src/schema/blocks/types.ts
sed -n '380,460p' packages/core/src/schema/blocks/types.ts

Repository: TypeCellOS/BlockNote

Length of output: 6537


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect parseTableContent body (where tableContent DOM mapping might happen)
echo "== Table/block.ts: inspect parseTableContent implementation =="
line=$(rg -n "function parseTableContent\\(" packages/core/src/blocks/Table/block.ts | head -n1 | cut -d: -f1)
start=$((line-40)); end=$((line+120))
sed -n "${start},${end}p" packages/core/src/blocks/Table/block.ts

echo
# 2) Inspect schema/blocks/types.ts where tableContent is defined
echo "== schema/blocks/types.ts: inspect around data for tableContent =="
rg -n 'type: "tableContent"|group: "tableContent"' packages/core/src/schema/blocks/types.ts
# show relevant regions around the first two hits we saw earlier (~315 and ~402)
sed -n '280,340p' packages/core/src/schema/blocks/types.ts
sed -n '360,440p' packages/core/src/schema/blocks/types.ts

echo
# 3) Inspect Table block/table node view for DOM structure around tbody/tableContent
echo "== Table/block.ts: inspect further down where BlockNoteTableView wraps TableView =="
# continue further down after earlier snippet; search for "tbody" or "table" references
rg -n "tbody|TableView|tableWrapper|data-node-type|data-content-type" packages/core/src/blocks/Table/block.ts
sed -n '220,520p' packages/core/src/blocks/Table/block.ts

Repository: TypeCellOS/BlockNote

Length of output: 17166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find all references to tableParagraph node =="
rg -n "tableParagraph" packages/core -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Find all references to group: \"tableContent\" =="
rg -n "group:\\s*\"tableContent\"|tableContent\\+|tableContent\\b" packages/core/src/blocks/Table/block.ts packages/core/src/schema -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Where are data-node-type attributes set generically? =="
rg -n "data-node-type" packages/core/src/schema packages/core/src/pm-nodes packages/core/src/editor packages/core/src/ -S --glob '*.{ts,tsx,js,jsx}' | head -n 200

echo
echo "== Inspect createSpec/wrapping logic that assigns data-node-type =="
# Look for the code path that uses createDefaultBlockDOMOutputSpec or wrapInBlockStructure
rg -n "createDefaultBlockDOMOutputSpec|wrapInBlockStructure|setAttribute\\(\"data-node-type\"|data-node-type\\s*=\\s*\" \\+" packages/core/src/schema/blocks/createSpec.ts packages/core/src/schema/blocks -S || true

echo
echo "== Inspect createSpec.ts around data-node-type assignment (if present) =="
file="packages/core/src/schema/blocks/createSpec.ts"
if [ -f "$file" ]; then
  rg -n "data-node-type" "$file" -S || true
  # show a chunk around any match
  matchline=$(rg -n "data-node-type" "$file" -S | head -n1 | cut -d: -f1 || true)
  if [ -n "${matchline:-}" ]; then
    start=$((matchline-60)); end=$((matchline+60))
    sed -n "${start},${end}p" "$file"
  fi
fi

Repository: TypeCellOS/BlockNote

Length of output: 7782


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for node/view specs with name: \"tableContent\" =="
rg -n 'name:\s*["'\'']tableContent["'\'']' packages/core/src -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Search for data-node-type=tableContent assignment (setAttribute or template strings) =="
rg -n --fixed-strings 'data-node-type="tableContent"' packages/core/src -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n --fixed-strings 'data-node-type=tableContent' packages/core/src -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Search for tableContent within pm-nodes / block wrappers =="
rg -n "tableContent" packages/core/src/pm-nodes -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n "tableContent" packages/core/src/schema/blocks -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n "tableContent" packages/core/src/schema -S --glob '*.{ts,tsx,js,jsx}' | head -n 100

echo
echo "== Inspect SideMenu logic to see what block.node corresponds to for tables =="
# Print a larger region around where the selector is used
sed -n '180,270p' packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== Inspect TableHandles logic to see how tableElement is determined =="
sed -n '1,220p' packages/core/src/extensions/TableHandles/TableHandles.ts

Repository: TypeCellOS/BlockNote

Length of output: 9726


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== SideMenu.ts: find where referencePos is used =="
rg -n "referencePos" packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== SideMenu.ts: inspect around referencePos usage =="
# show a couple windows around matches
while IFS=: read -r file line rest; do
  start=$((line-40)); end=$((line+80))
  echo "--- $file:$line ---"
  sed -n "${start},${end}p" "$file"
  echo
done < <(rg -n "referencePos" packages/core/src/extensions/SideMenu/SideMenu.ts | head -n 5)

echo "== Confirm no other data-node-type=tableContent occurrences in repo =="
rg -n --fixed-strings 'data-node-type=tableContent' packages/core -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n --fixed-strings 'data-node-type=\"tableContent\"' packages/core -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== TableHandles.ts: find referencePosTable usage =="
rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts
sed -n '220,320p' packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== TableHandles.ts: inspect around where referencePosTable is used to position widgets =="
line=$(rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-60)); end=$((line+120))
  sed -n "${start},${end}p" packages/core/src/extensions/TableHandles/TableHandles.ts
fi

Repository: TypeCellOS/BlockNote

Length of output: 284


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect tableContentToNodes
echo "== blockToNode.ts: locate tableContentToNodes =="
rg -n "function tableContentToNodes|tableContentToNodes\\(" packages/core/src/api/nodeConversions/blockToNode.ts

line=$(rg -n "export function tableContentToNodes" packages/core/src/api/nodeConversions/blockToNode.ts | head -n1 | cut -d: -f1)
start=$((line-80)); end=$((line+200))
echo
echo "== blockToNode.ts: tableContentToNodes implementation =="
sed -n "${start},${end}p" packages/core/src/api/nodeConversions/blockToNode.ts

# Search for data-node-type mention in nodeConversions around table nodes
echo
echo "== Search: data-node-type in nodeConversions =="
rg -n "data-node-type" packages/core/src/api/nodeConversions -S || true

# Inspect how BlockNote wraps block content for node views (createSpec.ts)
echo
echo "== createSpec.ts: inspect wrapInBlockStructure / data-node-type assignment =="
file="packages/core/src/schema/blocks/createSpec.ts"
rg -n "wrapInBlockStructure|data-node-type" "$file" -S || true
# show small windows around the first occurrences
for l in $(rg -n "wrapInBlockStructure|data-node-type" "$file" -S | head -n 3 | cut -d: -f1); do
  start=$((l-60)); end=$((l+80))
  echo
  echo "---- $file:$l ----"
  sed -n "${start},${end}p" "$file"
done

# Inspect wrapInBlockStructure helper implementation
echo
echo "== schema/blocks/internal.ts: inspect wrapInBlockStructure =="
file2="packages/core/src/schema/blocks/internal.ts"
rg -n "function wrapInBlockStructure|wrapInBlockStructure" "$file2" -S || true
line2=$(rg -n "function wrapInBlockStructure" "$file2" -S | head -n1 | cut -d: -f1)
start=$((line2-80)); end=$((line2+200))
sed -n "${start},${end}p" "$file2"

# Inspect TableView node view in Table/block.ts: does it add data-node-type for tableParagraph?
echo
echo "== Table/block.ts: search within file for tableContent-related DOM attributes =="
rg -n "tableParagraph|data-node-type|data-content-type|data-content-type.*table" packages/core/src/blocks/Table/block.ts -S

Repository: TypeCellOS/BlockNote

Length of output: 10763


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect packages/core/src/pm-nodes/BlockContainer.ts data-node-type logic =="
sed -n '1,120p' packages/core/src/pm-nodes/BlockContainer.ts
echo
sed -n '120,240p' packages/core/src/pm-nodes/BlockContainer.ts
echo
echo "== Inspect packages/core/src/pm-nodes/BlockGroup.ts data-node-type logic =="
sed -n '1,120p' packages/core/src/pm-nodes/BlockGroup.ts

echo
echo "== Inspect packages/core/src/schema/blocks/internal.ts wrapInBlockStructure =="
sed -n '1,220p' packages/core/src/schema/blocks/internal.ts

echo
echo "== Inspect packages/core/src/schema/blocks/createSpec.ts around wrapInBlockStructure usage =="
file="packages/core/src/schema/blocks/createSpec.ts"
rg -n "wrapInBlockStructure" "$file" -S
first=$(rg -n "wrapInBlockStructure" "$file" -S | head -n1 | cut -d: -f1)
start=$((first-80)); if [ "$start" -lt 1 ]; then start=1; fi
end=$((first+140))
sed -n "${start},${end}p" "$file"

echo
echo "== Search in createSpec.ts for explicit data-node-type mention =="
rg -n --fixed-strings "data-node-type" "$file" -S || true

Repository: TypeCellOS/BlockNote

Length of output: 16129


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts
line=$(rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts | head -n1 | cut -d: -f1)
start=$((line-80)); end=$((line+140))
sed -n "${start},${end}p" packages/core/src/extensions/TableHandles/TableHandles.ts

Repository: TypeCellOS/BlockNote

Length of output: 2352


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Repo-wide search for data-node-type=tableContent =="
rg -n --fixed-strings 'data-node-type="tableContent"' . -S || true
rg -n --fixed-strings 'data-node-type=tableContent' . -S || true

Repository: TypeCellOS/BlockNote

Length of output: 273


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# SideMenu: inspect where `block.node` comes from (getBlockFromMousePos) + what it contains.
echo "== SideMenu: inspect getBlockFromMousePos usage vicinity =="
rg -n "getBlockFromMousePos\\(" packages/core/src/extensions/SideMenu/SideMenu.ts
sed -n '1,200p' packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== Find definition of getBlockFromMousePos =="
file=$(rg -n "function getBlockFromMousePos|export function getBlockFromMousePos" packages/core/src -S --glob '*.{ts,tsx}' | head -n1 | cut -d: -f1)
line=$(rg -n "function getBlockFromMousePos|export function getBlockFromMousePos" "$file" -S --glob '*.{ts,tsx}' | head -n1 | cut -d: -f2)
start=$((line-60)); end=$((line+180))
sed -n "${start},${end}p" "$file"

echo
echo "== SideMenu: show around the selector and yPos computation =="
sed -n '220,280p' packages/core/src/extensions/SideMenu/SideMenu.ts

# TableHandles: inspect how `this.tableElement` is set and used to query tbody
echo
echo "== TableHandles: locate where this.tableElement is assigned =="
rg -n "this\\.tableElement\\s*=" packages/core/src/extensions/TableHandles/TableHandles.ts
line=$(rg -n "this\\.tableElement\\s*=" packages/core/src/extensions/TableHandles/TableHandles.ts | head -n1 | cut -d: -f1)
start=$((line-80)); end=$((line+160))
sed -n "${start},${end}p" packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== TableHandles: show around referencePosTable computation with tbody =="
# use the existing known line region around the earlier match
sed -n '540,620p' packages/core/src/extensions/TableHandles/TableHandles.ts

Repository: TypeCellOS/BlockNote

Length of output: 5709


Fix table side menu alignment: [data-node-type=tableContent] doesn’t match TableHandles’ <tbody>

SideMenu.ts (line 246) looks for blockNodeElement.querySelector("[data-node-type=tableContent]"), but the only occurrence of data-node-type="tableContent" in the repo is this line—table rendering doesn’t set that attribute. TableHandles.ts measures alignment from the real table body via this.tableElement!.querySelector("tbody") and referencePosTable = tableBody.getBoundingClientRect(), so the side menu’s y positioning won’t be based on the same element.

Update SideMenu to use the same DOM element as TableHandles (e.g., derive y from the table’s <tbody>/table wrapper) instead of [data-node-type=tableContent].

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/extensions/SideMenu/SideMenu.ts` at line 246, SideMenu is
querying a non-existent selector "[data-node-type=tableContent]" for table
positioning; update the logic in SideMenu.ts (where tableElement is set) to use
the same DOM node TableHandles uses (e.g., find the table element and then its
<tbody> via tableElement.querySelector("tbody") or the same table wrapper) and
derive the y-position from that element's getBoundingClientRect() (matching
referencePosTable calculation). Ensure you replace the
querySelector("[data-node-type=tableContent]") usage with a lookup for the real
table/<tbody> element and use that element for the side menu alignment
calculations so both SideMenu and TableHandles measure from the same node.

@nperez0111
Copy link
Copy Markdown
Contributor

Thanks for this @mkcash, but I think we would prefer for this change to be done in CSS, and I think @matthewlipski was working on something for this already. If so, @matthewlipski, can you close this?

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.

Drag handle is not aligned on tables

2 participants