Skip to content

table: Fit a column to its content on double-click of its resize handle - #3489

Merged
huacnlee merged 2 commits into
longbridge:mainfrom
miimsam:table-fit-column-to-content
Oct 13, 2026
Merged

huacnlee merged 2 commits into
longbridge:mainfrom
miimsam:table-fit-column-to-content

Conversation

@miimsam

@miimsam miimsam commented Oct 13, 2026 •

Copy link
Copy Markdown

Description

Double-clicking a column's resize handle now fits the column to its content, as spreadsheets and macOS table views do. The table can't measure what a delegate draws, so it asks the new TableDelegate::fit_column hook for the content width. The table then adds the cell padding, limits the result to the column's min_width and max_width, and emits TableEvent::ColumnWidthsChanged when the width changes. The hook returns None by default, so existing tables behave as before.

The fitted width is rounded up to whole device pixels. Layout rounds widths to the nearest device pixel, and text even a fraction of a pixel wider than its cell gets truncated. Each part (content and both paddings) is rounded separately, and at fractional scale factors the content is bumped one more device pixel when dividing back lands just below it.

The second press of a double-click also starts a drag on the handle, which would snap the fitted edge back under the pointer. Resize drags on a fitted column are ignored until the next single press.

The Data Table story implements the hook. One format_cell function now produces the text for both render_td and fit_column, so a fit measures exactly what is drawn. English and Chinese docs describe the hook, fit_col and col_width.

Before:
Screen.Recording.2026-10-13.at.12.18.45.mov
After:
Screen.Recording.2026-10-13.at.12.11.33.mov

Public API

gpui-component

  • TableDelegate::fit_column(&mut self, col_ix: usize, window: &mut Window, cx: &mut Context<TableState<Self>>) -> Option<Pixels>: returns the width column col_ix's content needs (widest cell or header, as drawn), or None to leave the column unchanged. Called on a double-click of the column's resize handle; returns None by default.
  • TableState::fit_col(&mut self, col_ix: usize, window: &mut Window, cx: &mut Context<Self>) -> bool: fits a column from code, the same as a double-click. Returns whether the delegate gave a width (false for a non-resizable column or a None answer).
  • TableState::col_width(&self, col_ix: usize) -> Option<Pixels>: the width a column is drawn at now, following drags and fits; None past the last column.

How to Test

cargo test -p gpui-component --test integration -- table_fit_column::

Manually, in cargo run → Data Table:

  • Double-click the divider after Symbol, Price, Change % and Name: each column fits its widest text, header included.
  • Double-click the divider of a sortable column: the header text and sort icon both fit.
  • Double-click and then drag slightly: the fitted width holds. A fresh single press and drag resizes as before.

Checklist

  • I have read the CONTRIBUTING document and followed the guidelines.
  • Reviewed the changes in this PR and confirmed AI generated code (If any) is accurate.
  • Passed cargo run for story tests related to the changes.
  • Tested macOS, Windows and Linux platforms performance (if the change is platform-specific) -> Tested only on macOS

AI-assisted: implementation, tests and documentation drafted with Claude Code, then reviewed and revised by me.

@miimsam
miimsam force-pushed the table-fit-column-to-content branch from b36e234 to aac32a0 Compare October 13, 2026 12:08
Double-clicking a column's resize handle asks the new
`TableDelegate::fit_column` hook for the width the column's content needs,
adds the cell padding, clamps it to the column's min and max width and emits
`ColumnWidthsChanged`. The hook returns `None` by default, so existing tables
are unchanged.

The width is rounded up to whole device pixels: layout rounds to the nearest
device pixel, and text a fraction of a pixel wider than its cell is truncated.

Also adds `TableState::fit_col` and `TableState::col_width`. The Data Table
story fits its columns by measuring the same text its cells draw, and the
docs cover the hook in both locales.
@miimsam
miimsam force-pushed the table-fit-column-to-content branch from aac32a0 to bf30574 Compare October 13, 2026 12:28
@miimsam
miimsam marked this pull request as ready for review October 13, 2026 12:30
Use table_cell_size for measurement and synchronize the story delegate size on size changes. Include the extra header inset for columns with custom padding.

Co-authored-by: Codex <codex@openai.com>
@huacnlee
huacnlee enabled auto-merge (squash) October 13, 2026 15:00
@huacnlee

Copy link
Copy Markdown
Member

Thank you, we need this feature very much.

@huacnlee
huacnlee merged commit af2f4c2 into longbridge:main Oct 13, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants