fix: stop a wide table from re-wrapping the rest of the document - #6
Open
adaasch wants to merge 1 commit into
Open
fix: stop a wide table from re-wrapping the rest of the document#6adaasch wants to merge 1 commit into
adaasch wants to merge 1 commit into
Conversation
A table too wide to fit widened the page for everything below it: every paragraph, heading and rule after it wrapped at the *table's* width, so reading the rest of the document meant scrolling sideways. The cause is that `ui.available_width()` stops being the page width the moment anything overflows. egui grows a `Ui`'s `max_rect` to contain any widget placed in it (`Placer::advance_after_rects`), and every later widget sizes itself from that grown rect. `set_max_width` cannot undo it, because it refuses to shrink a `Ui` below the `min_rect` the table just expanded. Two changes, because either alone leaves half the problem: - Tables that cannot fit at their natural minimum widths are now squeezed proportionally until they do, and the long tokens that made them too wide break across lines (epaint breaks anywhere when a row offers no word boundary). A table only overflows when it has more columns than the viewport can hold at MIN_TABLE_COL_PX each — on a phone-width window a five-column table now fits instead of overflowing. - The renderer tracks the page's right edge, sampled before anything can widen the Ui, and wraps against that. It is an edge rather than a width because the pollution spreads: a blockquote opened inside a widened Ui is widened too, so its own width is no more trustworthy than its parent's. An edge composes — any nested Ui still knows where it starts. Labels and separators, which size themselves from the Ui and ignore any width handed to them, get a child Ui narrow enough to hold them; that child is only created when the page has actually been polluted. So a table that genuinely cannot fit still overflows and still gets a horizontal scrollbar, but the overflow stays inside the table. Two tests asserted the old contract (overflow rather than squeeze) and now assert the new one; four more cover the squeeze, the floor, the redistribution and the give-up case. Co-Authored-By: Claude Opus 5 (1M context) <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.
Wide tables broke text wrapping for the whole document below them.
The bug
A table too wide to fit widened the page for everything after it: every
paragraph, heading and rule following it wrapped at the table's width, so
reading the rest of the document meant scrolling sideways.
ui.available_width()stops meaning "page width" the moment anythingoverflows. egui grows a
Ui'smax_rectto contain every widget placed in it(
Placer::advance_after_rects→Region::expand_to_include_rect), and everylater widget sizes itself from that grown rect.
set_max_widthcannot undo it,because it refuses to shrink a
Uibelow themin_rectthe table justexpanded.
Reproduced headlessly before changing anything: paragraphs before the table
wrapped at 884px, paragraphs after ran off the edge at ~2600px.
The fix
Two changes, because either alone leaves half the problem.
Tables that cannot fit are squeezed instead of overflowing. When even the
minimum column widths do not fit, columns shrink proportionally until they do,
and the long tokens that made them too wide break across lines (epaint already
falls back to breaking anywhere when a row offers no word boundary). A table
now only overflows when it has more columns than the viewport can hold at
MIN_TABLE_COL_PXeach. At phone width (420px) a five-column table fits whereit used to blow the page apart.
The renderer tracks the page's right edge, sampled before anything can
widen the
Ui, and wraps against that. It is an edge rather than a widthbecause the pollution spreads: the first attempt clamped a width, and a
blockquote opened inside an already-widened
Uiinherited the pollution, soits content came out 20px too wide and spilled past the quote's padding. An
edge composes — any nested
Uistill knows where it starts. Labels andseparators ignore any width handed to them and size from the
Ui, so those geta child
Uinarrow enough to hold them; that child is only created when thepage has actually been polluted.
A table that genuinely cannot fit still overflows and still gets a horizontal
scrollbar. The difference is that the overflow now stays inside the table.
Verification
master).blockquotes, tables inside list items, phone-width windows, and
README.md/tests/sample.mdfor regressions.Behaviour changes to review
Two existing tests asserted the old contract (overflow rather than squeeze).
Those are deliberate behaviour changes, so both were rewritten to state the new
contract rather than loosened, and four tests added covering the squeeze, the
floor, the redistribution and the give-up case.
One judgement call: giving wide tables their own horizontal scroll area (what
GitHub does) was considered and rejected — a nested scroll area competes with
the outer one for drag gestures, which would land squarely on the Android
build. Squeeze-plus-clamp gets the same result for every table that can
plausibly fit, without that risk.
🤖 Generated with Claude Code