Skip to content

fix(tables): expand auto-width tables to fill available page width#2109

Merged
harbournick merged 2 commits intomainfrom
tadeu/fix-auto-table-width-fill-page
Feb 25, 2026
Merged

fix(tables): expand auto-width tables to fill available page width#2109
harbournick merged 2 commits intomainfrom
tadeu/fix-auto-table-width-fill-page

Conversation

@tupizz
Copy link
Contributor

@tupizz tupizz commented Feb 19, 2026

Summary

Closes SD-1956 https://linear.app/superdocworkspace/issue/SD-1956/bug-auto-layout-tables-with-explicit-tblgrid-tiny-tcw-render-squished

  • Tables without explicit w:tblW (or with type="auto") were rendering at ~1/3 page width instead of filling the available content area like Microsoft Word does
  • Root cause was in the measuring-dom layer: auto-layout tables only scaled down (when too wide) but never up to fill available space
  • Also fixed resolveTableWidth() not recognizing type='dxa' — the most common explicit width type in OOXML — which caused dxa-width tables to incorrectly fall into the auto-layout path

Why this was happening

The table measurement pipeline in measureTableBlock() has two branches:

  1. Explicit width branch (hasExplicitWidth || hasFixedLayout): scales columns both up and down to match the declared table width
  2. Auto-layout branch (no explicit width): only scaled down when columns exceeded available space, but never scaled up — leaving narrow imported column widths as-is

When a DOCX file has no w:tblW element (or type="auto"), resolveTableWidth() returned undefined, so hasExplicitWidth was false. The auto-layout branch would receive narrow column widths from the import (e.g., 100px per column from w:tcW cell widths or the fallback grid), and since the total was less than the page width, no scaling occurred.

Additionally, resolveTableWidth() only recognized type='pct' and type='px'/'pixel', but not type='dxa' — even though dxa values are already converted to pixels during import by the tbl-translator. This meant tables with explicit dxa widths also fell into the auto-layout path.

What we changed to prevent this

  1. Scale up auto-layout tables (ECMA-376 §2.4.64): When a table has no explicit width, the layout algorithm (§2.4.49/§2.4.50) uses autofit, which in practice expands the table to fill the available page content width. The auto-layout branch now scales columns proportionally in both directions to match this behavior.

  2. Handle dxa type in resolveTableWidth(): Added type='dxa' alongside 'px'/'pixel' so that tables with explicit dxa widths are correctly recognized as having an explicit width, preventing them from being affected by the auto-layout scale-up.

Test plan

  • All 224 measuring-dom tests pass (updated 12 existing tests to reflect new auto-layout behavior)
  • All 663 super-editor test files pass (6162 tests)
  • All 474 layout-engine tests pass
  • TypeScript typecheck passes
  • Visual verification: load AI-generated DOCX with auto-width tables → tables fill page width
  • Visual verification: existing DOCX files with explicit table widths render unchanged

Tables without explicit w:tblW (or with type="auto") were rendering at a
fraction of the page width instead of filling the available content area
like Word does.
Copilot AI review requested due to automatic review settings February 19, 2026 11:06
@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

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

This PR fixes table layout behavior for auto-width tables in the measuring-dom layer. Previously, tables without explicit width (or with type="auto") only scaled down when too wide but never scaled up to fill available space, resulting in tables rendering at approximately 1/3 page width instead of filling the content area like Microsoft Word does.

Changes:

  • Added type='dxa' recognition in resolveTableWidth() to correctly identify DXA-width tables as having explicit width
  • Modified auto-layout branch to scale columns both up and down proportionally to fill available page width, following ECMA-376 autofit behavior
  • Replaced the complex scaleColumnWidths() function with inline scaling logic that uses simpler last-column rounding adjustment

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/layout-engine/measuring/dom/src/index.ts Added 'dxa' type handling in resolveTableWidth(), removed scaleColumnWidths() helper function, updated auto-layout branch to scale columns proportionally to fill available width
packages/layout-engine/measuring/dom/src/index.test.ts Updated 12 test expectations to reflect new auto-layout behavior where tables expand to fill available width

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

@linear
Copy link

linear bot commented Feb 19, 2026

…to full page width

Updated the table measurement logic to prevent scaling up column widths when explicit widths are defined. Adjusted tests to reflect the new behavior where tables without explicit widths default to filling the available page content width, aligning with Word's autofit behavior.
Copy link
Collaborator

@harbournick harbournick left a comment

Choose a reason for hiding this comment

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

LGTM

@harbournick harbournick merged commit 15f36bc into main Feb 25, 2026
3 checks passed
@harbournick harbournick deleted the tadeu/fix-auto-table-width-fill-page branch February 25, 2026 00:00
@superdoc-bot
Copy link
Contributor

superdoc-bot bot commented Feb 25, 2026

🎉 This PR is included in superdoc v1.17.0-next.4

The release is available on GitHub release

harbournick pushed a commit that referenced this pull request Feb 28, 2026
# [1.17.0](v1.16.0...v1.17.0) (2026-02-28)

### Bug Fixes

* active track change ([#2163](#2163)) ([108c14d](108c14d))
* add currentTotalPages getter and pagination-update event ([#2202](#2202)) ([95b4579](95b4579)), closes [#958](#958)
* always call resolveComment after custom TC bubble handlers (SD-2049) ([#2204](#2204)) ([34fb4e0](34fb4e0))
* backward replace insert text ([#2172](#2172)) ([66f0849](66f0849))
* **collaboration:** deduplicate updateYdocDocxData during replaceFile (SD-1920) ([#2162](#2162)) ([52962fc](52962fc))
* **comments:** cross-page collision avoidance for floating comment bubbles (SD-1998) ([#2180](#2180)) ([6cfbeca](6cfbeca))
* **comments:** remove synchronous dispatch from plugin apply() (SD-1940) ([#2157](#2157)) ([887175b](887175b))
* **css:** scope ProseMirror CSS to prevent bleeding into host apps (SD-1850) ([#2134](#2134)) ([b9d98fa](b9d98fa))
* document-api improvements, plan mode, query.match, mutations ([6221580](6221580))
* **document-api:** delete table cell fix ([#2209](#2209)) ([5e5c43f](5e5c43f))
* **document-api:** distribute columns command fixes ([#2207](#2207)) ([8f4eaf7](8f4eaf7))
* **document-api:** fix cell shading in document api ([#2215](#2215)) ([456f60e](456f60e))
* **document-api:** insert table cell ([#2210](#2210)) ([357ee90](357ee90))
* **document-api:** plan-engine reliability fixes and error diagnostics ([#2185](#2185)) ([abfd81b](abfd81b))
* **document-api:** split table cell command ([#2217](#2217)) ([0b3e2b4](0b3e2b4))
* **document-api:** split table command ([#2214](#2214)) ([ec31699](ec31699))
* **editor:** render styles applied inside SDT fields (SD-2011) ([#2188](#2188)) ([9c34be3](9c34be3))
* **editor:** selection highlight flickers when dragging across mark boundaries (SD-2024) ([#2205](#2205)) ([ba03e76](ba03e76))
* extract duplicate block identity normalization from docxImporter ([7f7ff93](7f7ff93))
* improve backspace behavior near run boundaries for tracked changes ([#2175](#2175)) ([6c9c7a3](6c9c7a3))
* **layout:** per-section footer constraints for multi-section docs (SD-1837) ([#2022](#2022)) ([e11acc5](e11acc5))
* normalize review namespace into trackChanges, harden input validation ([33e907b](33e907b))
* outside click for toolbar dropdown ([#2174](#2174)) ([5f859c7](5f859c7))
* preserve line spacing and indentation on Google Docs paste ([#2183](#2183)) ([b9a7357](b9a7357)), closes [#2151](#2151)
* **shapes:** render grouped DrawingML shapes with custom geometry (SD-1877) ❇️ ([#2105](#2105)) ([14985a5](14985a5))
* support cell spacing ([#1879](#1879)) ([1639967](1639967))
* **tables:** expand auto-width tables to fill available page width ([#2109](#2109)) ([15f36bc](15f36bc))
* text highlight on export ([#2189](#2189)) ([9cbd022](9cbd022))
* track highlight changes ([#2192](#2192)) ([e164625](e164625))
* undo/redo actions ([#2161](#2161)) ([495e92f](495e92f))

### Features

* allow custom accept/reject handlers for TC bubbles ([#1921](#1921)) ([e30abf6](e30abf6))
* **document-api:** add format operations font size alignment color font family ([#2179](#2179)) ([f19c688](f19c688))
* **document-api:** add plan-based mutation engine with query.match and style capture ([#2160](#2160)) ([365293a](365293a))
* **document-api:** doc default initial styles ([#2184](#2184)) ([f25e41f](f25e41f))
* **document-api:** include anchored text in comments list response ([#2177](#2177)) ([b3a2912](b3a2912))
* **document-api:** inline formatting parity core end-to-end ([#2197](#2197)) ([b405b03](b405b03))
* **document-api:** inline formatting rpr parity ([#2198](#2198)) ([41ab771](41ab771))
* **document-api:** section commands ([#2199](#2199)) ([ec4abe3](ec4abe3))
* **document-api:** support deleting entire block nodes not only text ([#2181](#2181)) ([2897246](2897246))
* **document-api:** table of contents commands ([#2200](#2200)) ([baa72c4](baa72c4))
* **document-api:** tables namespace and commands ([#2182](#2182)) ([b80ee31](b80ee31))
* **markdown:** add markdown override to sdk, improve conversion ([#2196](#2196)) ([04a1c71](04a1c71))
* preserve w:view setting through DOCX round-trip ([#2190](#2190)) ([48b4210](48b4210)), closes [#2070](#2070)
* **track-changes:** clear comment bubbles when bulk accept or reject TCs ([#2159](#2159)) ([27fbe8e](27fbe8e))

### Performance Improvements

* **comments:** batch tracked change comment creation on load ([#2166](#2166)) ([0c2eca5](0c2eca5))
* **comments:** batch tracked change creation and virtualize floating bubbles (SD-1997) ([#2168](#2168)) ([70fd7d9](70fd7d9))
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.

3 participants