Skip to content

fix(table): resolve column resize only working on first page (SD-1772)#1959

Merged
tupizz merged 1 commit intomainfrom
tadeu/sd-1772-table-columns-only-resizable-on-first-page-of-document
Feb 6, 2026
Merged

fix(table): resolve column resize only working on first page (SD-1772)#1959
tupizz merged 1 commit intomainfrom
tadeu/sd-1772-table-columns-only-resizable-on-first-page-of-document

Conversation

@tupizz
Copy link
Contributor

@tupizz tupizz commented Feb 6, 2026

Summary

Fixes table column resize handles not appearing on tables beyond the first page of a document.

Demo

CleanShot.2026-02-06.at.10.35.27.mp4

Root Cause

updateOverlayRect() in TableResizeOverlay.vue was computing the overlay position relative to the table element's offsetParent (the .superdoc-page containing the table), but the overlay itself is rendered as a child of div.super-editor — whose position: absolute resolves against .super-editor-container, a completely different coordinate space.

DOM hierarchy:

div.super-editor-container  ← overlay's actual offset parent
  div.super-editor
    div.editor-element
      div.superdoc-page[page=1]  ← table's offset parent (page 1)
        div.superdoc-table-fragment
      div.superdoc-page[page=2]  ← table's offset parent (page 2)
        div.superdoc-table-fragment
    <TableResizeOverlay />  ← position: absolute, sibling of editor-element

The old code did:

const parent = props.tableElement.offsetParent; // → .superdoc-page
left = tableRect.left - parentRect.left;  // position within the page
top = tableRect.top - parentRect.top;     // position within the page

This produced page-relative coordinates (e.g., top: 150px within page 2), but the overlay's position: absolute resolved against super-editor-container. On page 1, the numbers coincidentally aligned since page 1 starts near the top of the container. On page 2+, the overlay was placed near the top of the editor — completely off-screen from the actual table.

Fix

Changed updateOverlayRect() to compute coordinates relative to the overlay's own offsetParent (overlayEl.value.offsetParent) instead of the table's offset parent. This ensures the overlay is correctly positioned regardless of which page the table is on.

// Before (broken): used table's offset parent (.superdoc-page)
const parent = props.tableElement.offsetParent;

// After (fixed): use overlay's own offset parent (.super-editor-container)
const referenceEl = overlayEl.value?.offsetParent;

Why This Doesn't Cause Side Effects

  • The fix only changes which element is used as the coordinate reference — the math (getBoundingClientRect subtraction) is identical
  • On page 1, both the old and new reference elements produce the same result (the offset difference is negligible)
  • The overlay's hover detection (isNearColumnBoundary in SuperEditor.vue) is unaffected — it uses viewport-relative getBoundingClientRect coordinates which work correctly on all pages
  • Drag behavior is unaffected — it uses delta calculations (event.clientX - initialX) that are position-independent

Test Plan

  • Open a multi-page document with tables on different pages
  • Verify column resize handles appear when hovering column borders on page 1
  • Verify column resize handles appear when hovering column borders on page 2+
  • Verify column drag-to-resize works correctly on all pages
  • Verify resize handles track correctly during scroll
  • Test with imported DOCX files containing tables on multiple pages

Use the overlay's own offset parent for position calculations instead
of the table element's offset parent. The table fragment's offsetParent
is its .superdoc-page container, but the resize overlay is rendered as
a child of .super-editor whose offset parent is .super-editor-container.
This coordinate space mismatch caused the overlay to be positioned at
page-relative coordinates within the editor-container space, placing it
off-screen for tables on any page after the first.
Copilot AI review requested due to automatic review settings February 6, 2026 13:34
@linear
Copy link

linear bot commented Feb 6, 2026

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes table column resize overlay positioning so resize handles appear correctly for tables on pages after the first, by aligning overlay coordinates with the overlay’s actual positioning context.

Changes:

  • Add a DOM ref for the overlay element so positioning can be computed against the overlay’s own offsetParent.
  • Update updateOverlayRect() to compute overlay left/top relative to overlayEl.offsetParent instead of tableElement.offsetParent.
  • Adjust inline documentation/comments to reflect the new coordinate reference.
Comments suppressed due to low confidence (1)

packages/super-editor/src/components/TableResizeOverlay.vue:299

  • updateOverlayRect() now relies on overlayEl.value?.offsetParent, but when visible first flips true the overlay element hasn’t been rendered yet (due to v-if), so overlayEl.value is still null and the code falls back to tableElement.offsetLeft/offsetTop. That fallback is page-relative (the original bug’s coordinate space) and can briefly place the overlay incorrectly on page 2+ (and potentially never correct if visible toggles off quickly).

Consider deferring the initial updateOverlayRect() until after the overlay DOM is mounted (e.g., nextTick when visible becomes true / tableElement changes), and/or using a non-table-based reference element for the fallback (the overlay container / editor container) so the fallback can’t reintroduce page-relative positioning.

  // Position overlay relative to its own offset parent (the element that
  // position:absolute resolves against), NOT the table's offset parent.
  // The table's offsetParent is its .superdoc-page, but the overlay is rendered
  // as a child of .super-editor — a different coordinate space. Using the table's
  // page as reference caused the overlay to be mispositioned on pages after the first.
  const referenceEl = overlayEl.value?.offsetParent;
  if (referenceEl) {
    const referenceRect = referenceEl.getBoundingClientRect();
    const left = tableRect.left - referenceRect.left + (referenceEl.scrollLeft || 0);
    const top = tableRect.top - referenceRect.top + (referenceEl.scrollTop || 0);
    overlayRect.value = {
      left,
      top,
      width: tableRect.width,
      height: tableRect.height,
    };
  } else {
    // Fallback: use table's own offset position
    overlayRect.value = {
      left: props.tableElement.offsetLeft,
      top: props.tableElement.offsetTop,
      width: tableRect.width,
      height: tableRect.height,
    };
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@luccas-harbour luccas-harbour left a comment

Choose a reason for hiding this comment

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

LGTM

@tupizz tupizz merged commit df43867 into main Feb 6, 2026
10 checks passed
@tupizz tupizz deleted the tadeu/sd-1772-table-columns-only-resizable-on-first-page-of-document branch February 6, 2026 17:59
@superdoc-bot
Copy link

superdoc-bot bot commented Feb 6, 2026

🎉 This PR is included in superdoc v1.11.0-next.21

The release is available on GitHub release

@superdoc-bot
Copy link

superdoc-bot bot commented Feb 6, 2026

🎉 This PR is included in superdoc v1.12.0-next.1

The release is available on GitHub release

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants