Skip to content

fix(components): paint table columns at their measured widths - #265

Merged
LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/table-column-widths
Sep 22, 2026
Merged

LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/table-column-widths

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Severity Medium, category correctness. Location: crates/rustmotion-components/src/table.rs:116

Impact

TableIntrinsic::compute_width (intrinsic.rs:911-949) measures every header and every cell, keeps a per-column max (col_widths[i] = col_widths[i].max(w + cell_padding * 2.0)) and returns the sum. The painter then throws that per-column distribution away and gives each column total_w / col_count. For an uneven table (e.g. headers ["ID", "Description of the incident"], natural widths 60px and 400px → intrinsic 460px) the painter allocates 230px per column; the 400px column's text is drawn from align_text_x at a position computed against a 230px cell and there is no per-cell clip (table.rs:203-262 draws each cell with draw_text_with_fallback and only advances col_x += cw), so the text overlaps the neighbouring column or spills past the table's right edge. With column_align: "right" it spills backwards into the previous column. The measurer's own doc comment (intrinsic.rs:884-888) asserts the opposite: "Natural size formula (matches the painter exactly) ... otherwise each column gets max(header_text_width + 2 × cell_padding, min_col_width)" — the painter implements no such rule, and compute_width has no min_col_width either.

Fix

Extract the per-column width computation into one function on Table (returning Vec<f32>), have TableIntrinsic sum its result and resolve_column_widths return it directly, scaling proportionally when the laid-out width differs from the natural one. Fix the now-false doc comment at intrinsic.rs:884.

Evidence the audit read

fn resolve_column_widths(&self, total_w: f32) -> Vec<f32> {
        let col_count = self.headers.len().max(1);
        if let Some(widths) = &self.column_widths {
            ...
        } else {
            vec![total_w / col_count as f32; col_count]
        }
    }

Stacked on fix/cascade-reaches-painters, which carries the previous finding of this workstream. GitHub shows only this finding's diff; merge in order.

Part of the September 2026 audit remediation chantier. Refs #220 (RM-08).

@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 21, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 21, 2026
@LeadcodeDev
LeadcodeDev force-pushed the fix/cascade-reaches-painters branch from 6dc5764 to dc957fe Compare September 22, 2026 06:11
@LeadcodeDev
LeadcodeDev force-pushed the fix/table-column-widths branch from 14fbbe3 to 5b62def Compare September 22, 2026 06:12
@LeadcodeDev
LeadcodeDev force-pushed the fix/cascade-reaches-painters branch from dc957fe to 42c4881 Compare September 22, 2026 08:36
@LeadcodeDev
LeadcodeDev force-pushed the fix/table-column-widths branch from 5b62def to 19e4361 Compare September 22, 2026 08:36
@LeadcodeDev
LeadcodeDev force-pushed the fix/cascade-reaches-painters branch from 42c4881 to 5fba6d1 Compare September 22, 2026 08:46
@LeadcodeDev
LeadcodeDev force-pushed the fix/table-column-widths branch from 19e4361 to 575be98 Compare September 22, 2026 08:46
@LeadcodeDev
LeadcodeDev changed the base branch from fix/cascade-reaches-painters to chantier/audit-2026-09 September 22, 2026 08:54
@LeadcodeDev
LeadcodeDev force-pushed the fix/table-column-widths branch from 575be98 to c03a977 Compare September 22, 2026 09:02
`TableIntrinsic::compute_width` (intrinsic.rs:911-949) measures every header and every cell, keeps a per-column max (`col_widths[i] = col_widths[i].max(w + cell_padding * 2.0)`) and returns the **sum**. The painter then throws that per-column distribution away and gives each column `total_w / col_count`. For an uneven table (e.g. headers `["ID", "Description of the incident"]`, natural widths 60px and 400px → intrinsic 460px) the painter allocates 230px per column; the 400px column's text is drawn from `align_text_x` at a position computed against a 230px cell and there is no per-cell clip (table.rs:203-262 draws each cell with `draw_text_with_fallback` and only advances `col_x += cw`), so the text overlaps the neighbouring column or spills past the table's right edge. With `column_align: "right"` it spills backwards into the previous column. The measurer's own doc comment (intrinsic.rs:884-888) asserts the opposite: "Natural size formula (matches the painter exactly) ... otherwise each column gets `max(header_text_width + 2 × cell_padding, min_col_width)`" — the painter implements no such rule, and `compute_width` has no `min_col_width` either.

Refs #220
@LeadcodeDev
LeadcodeDev force-pushed the fix/table-column-widths branch from c03a977 to bd2b246 Compare September 22, 2026 09:06
@LeadcodeDev
LeadcodeDev merged commit 3e5708b into chantier/audit-2026-09 Sep 22, 2026
LeadcodeDev added a commit that referenced this pull request Sep 22, 2026
`TableIntrinsic::compute_width` (intrinsic.rs:911-949) measures every header and every cell, keeps a per-column max (`col_widths[i] = col_widths[i].max(w + cell_padding * 2.0)`) and returns the **sum**. The painter then throws that per-column distribution away and gives each column `total_w / col_count`. For an uneven table (e.g. headers `["ID", "Description of the incident"]`, natural widths 60px and 400px → intrinsic 460px) the painter allocates 230px per column; the 400px column's text is drawn from `align_text_x` at a position computed against a 230px cell and there is no per-cell clip (table.rs:203-262 draws each cell with `draw_text_with_fallback` and only advances `col_x += cw`), so the text overlaps the neighbouring column or spills past the table's right edge. With `column_align: "right"` it spills backwards into the previous column. The measurer's own doc comment (intrinsic.rs:884-888) asserts the opposite: "Natural size formula (matches the painter exactly) ... otherwise each column gets `max(header_text_width + 2 × cell_padding, min_col_width)`" — the painter implements no such rule, and `compute_width` has no `min_col_width` either.

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant