Repository navigation
feat(editor): resizable table columns with proportional widths (#36) - #38
Merged
Merged
Conversation
Editors can drag the line between two table columns to move width from one to the other. Widths are stored as proportions, so a table keeps its layout on every screen and always fills the page width; readers see the result and it is saved with the page. Column resizing was configured but never worked on existing pages: Tiptap installs prosemirror-tables' resizing only when the editor is editable at creation, and pages open in view mode, so switching to Edit never showed the handles. A table node view (TableColumnView) now renders every table, draws one drag strip per inner border and commits a drag as one transaction; prosemirror-tables' pixel resizing is disabled. The existing `colwidth` cell attribute now holds relative weights, normalised to 1000 on each drag (no schema change). Unset columns share what is left of the total, so tables resized before this keep their dragged column widest. Long URLs now wrap inside their cell. Closes #36 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cargo-deny's advisories check started failing on two entries added to the RustSec database after main last passed: - RUSTSEC-2021-0157: ammonia < 4.1.7 does not escape quotes in CSS url() inside style attributes. Pin ammonia to 4.1.7, the patched 4.1 release; the only lockfile change. knot was not reachable: the public share page uses ammonia's default builder, which strips style attributes. - RUSTSEC-2024-0449: unsafe-libyaml is unmaintained. It comes in through figment's Yaml provider (serde_yaml), figment 0.10.19 is the latest, and there is no known vulnerability. Ignored in deny.toml with the path, reachability (only the operator's KNOT_CONFIG file) and drop condition, following the file's convention. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #36.
What changes for users
Escapecancels a drag, and a vertical swipe that starts on a column line still scrolls.Why resizing never worked
KnotTablealready hadresizable: true, but Tiptap decides whether to install prosemirror-tables'columnResizingplugin fromeditor.isEditableat creation.KnotEditorcreates the editor read-only for every existing page (view mode is the default) and later callssetEditable(true)without re-creating it, so the plugin was never installed. Only brand-new pages, which open in edit mode, could be resized.How
columnWidths.ts: the width model, as pure functions. It reads thecolwidthcell attribute as relative weights (viaTableMap, so colspans and rowspans are handled), turns them into shares, moves one border with a 40px floor, and writes all columns back normalised to exactly 1000 (largest-remainder rounding).TableColumnView.ts: the table node view, installed for every table whatever the editability.<colgroup>and a handle layer with one strip per inner border, placed at the running total of the shares, so no measuring is needed.TableExtensions.ts:resizable: false(no more pixel resizing). It overridesaddNodeViewand alsorenderHTML, so the clipboard andgetHTML()carry the same percentages.prose.css:overflow-wrap: anywhereon cells.display: flow-rootand the table keeps its margin inside it, so spacing around existing tables is unchanged (checked againstmainin Chromium).Compatibility
colwidthkeeps riding Yjs and stays out of the canonical markdown schema.[300, null, null, null]) keep the dragged column widest. Unset columns share what is left of 1000.Testing
Unit (vitest/jsdom):
Escapeand pointer cancel, viewers, a read-only-created editor switched to edit, remote changes mid-drag, and the HTML serialisation.e2e:
e2e/flows/table-column-resize.spec.tscovers: page opened in view mode → Edit → drag → reload → width kept.main's table extension.maintoo.mainas well; excalidraw passed on re-run.Other checks:
tsc --noEmit,eslint src --max-warnings 0andvite buildare clean.cargochecks were not re-run.main.Known limitations / follow-ups
aria-hidden.Spec:
docs/superpowers/specs/2026-10-12-table-column-resize-design.md· Plan:docs/superpowers/plans/2026-10-12-table-column-resize.md🤖 Generated with Claude Code