Repository navigation
fix(listview): shared min/max column-width model for CRUD list views - #45824
sadpandajoe wants to merge 12 commits into
Conversation
The Datasets, Dashboards and Charts list tables pin the Name column to a fixed size but left other columns unsized. With auto table layout, spare container width goes to unsized columns, so Dataset and Dashboard Actions (and Dashboard Last modified, Chart Type) stretched to hundreds of pixels while Name stayed squashed. Give every visible column an explicit size so spare width is distributed proportionally across all of them, keep Name as the widest column, bound the Chart Type column, and use a consistent Actions size across the three pages. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
✅ Deploy Preview for superset-docs-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #45824 +/- ##
==========================================
+ Coverage 84.61% 84.69% +0.08%
==========================================
Files 3069 3071 +2
Lines 205513 205636 +123
Branches 48300 48345 +45
==========================================
+ Hits 173893 174171 +278
+ Misses 28320 28165 -155
Partials 3300 3300
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
List view tables sized columns from per-page `size` hints under an auto table layout, so whichever columns were left unsized absorbed all spare width (huge Actions/Type columns, squashed Name) and every page had to be tuned by hand. Give every ListView column a `layout`: a preset from a single COLUMN_LAYOUT_PRESETS table (fixed widths for icons, status badges, counts, avatar groups and actions; min/max/weight ranges for titles, text, long text, tags and dates) or an explicit fixed / min-max object. TableCollection resolves the widths from the measured container width (water-filling spare width by weight, capping each flexible column at its max until all are capped) and renders them with a fixed table layout, scrolling horizontally only when the minimums don't fit. The legacy `size` token keeps working as a fixed width and is deprecated. Only ListView opts in (`managedColumnWidths`); other TableCollection / TableView callers keep the browser's auto layout. Every list page is migrated to presets, and a guard test keeps legacy `size` tokens out of list pages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Status badges render as antd tags with an inline margin, so the dataset "Physical"/"Virtual" type and dashboard "Published"/"Draft" badges need 128px including cell padding; at 112px they overflowed and showed an ellipsis next to the badge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Name cell of the Datasets and Themes lists hard-clipped long titles without an ellipsis and could push the adornments beside them (badges, description tooltip, status tags) out of the cell. Each list view carried its own copy of a flex-row wrapper, and only the Dashboard and Chart copies remembered to make the title link shrinkable; inside a flex row the table cell's own text-overflow does not apply. Add ListViewTitleCell, which owns the flex row, the single-line ellipsis on the title and the non-shrinking adornments once, and use it in the Dataset, Dashboard, Chart and Theme lists in place of the per-page wrappers. Title columns that render bare text or inline links already ellipsize through the shared table cell styles and are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… block when a list scrolls Rework the shared list view preset table from measured content, English and German included: - typed fixed presets: icon/statusIcon 48, statusIcons 64, status 144, flag 176 (boolean columns; longer headers ellipsize with the full text in the header title), count 104, timer 136, people 120, iconList 120, dateRelative 176, dateTwoLine 136, timestamp 240, actions 120, actionsWide 168 - title is the one primary flexible column: min 320, max 640, weight 3 - flexible text 140-280, identifier 180-360 (database, schema, table and dataset names), longtext 200-560, tags 200-320 - statusWide and date are replaced by flag, iconList, dateRelative, dateTwoLine and timestamp When the minimums do not fit, the table scrolls inside its container and the leading block (selection checkbox, favorite star or state icon, and the title) is frozen, but only while that block takes at most half of the container and leaves at least 240px to scroll. The rule lives in pure functions (getLeadingBlockLength, getFrozenColumnCount) with exported tuning constants. Frozen tables set scroll-padding on the scroll container and scroll a focused cell into view, so keyboard focus never lands under the frozen columns. Every list view page is migrated to the new presets; column ids, accessors, renderers, hidden flags and sorting are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Query history and Saved queries "Tables": the first table name ellipsizes while the "(+N)" count stays visible. - Tags list name pill and the Charts "Matrixified" pill get a max width and an ellipsis, so a pill is never cut mid-pill; the chart type name shrinks first. - Saved queries tags show at most three chips, like Dashboards and Charts. - Task names are no longer cut at 30 characters in JS on top of the cell's CSS ellipsis; the tooltip still carries the full name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… tables The header ellipsis and the frozen-block scroll padding only make sense for list views with managed column widths. Scope them to managed tables so TableView and other auto-layout tables keep sizing columns to their headers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| }, | ||
| Header: t('Actions'), | ||
| id: 'actions', | ||
| layout: 'actions', |
There was a problem hiding this comment.
Suggestion: On OAuth2 databases, a user with edit, export, token-management, and delete permissions sees five actions; the 120px preset clips the last control.
Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Css layout issue
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/src/pages/DatabaseList/index.tsx
**Line:** 1046:1046
**Comment:**
*Css Layout Issue: On OAuth2 databases, a user with edit, export, token-management, and delete permissions sees five actions; the 120px preset clips the last control.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fixThere was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 34d8f0f.
The actions column now uses the actionsWide layout preset instead of the 120px preset.
If that's not right, unresolve this thread and CodeAnt will leave it open.
There was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 410786f.
The actions column now uses the actionsWide layout preset instead of the narrower preset.
If that's not right, unresolve this thread and CodeAnt will leave it open.
There was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of 3d51961.
The actions column now uses the actionsWide layout instead of the 120px preset.
If that's not right, unresolve this thread and CodeAnt will leave it open.
There was a problem hiding this comment.
✅ CodeAnt verified this suggestion was addressed in subsequent commits and marked this thread resolved as of efc277f.
The Actions column now uses the actionsWide layout instead of the narrower preset.
If that's not right, unresolve this thread and CodeAnt will leave it open.
| pagination={paginationConfig} | ||
| scroll={{ x: 'max-content' }} | ||
| tableLayout="auto" | ||
| scroll={{ x: columnLayout ? columnLayout.totalWidth : 'max-content' }} |
There was a problem hiding this comment.
Suggestion: TableView does not enable managed widths, but this still sets scroll.x to 'max-content', forcing generic tables into horizontal scrolling and changing their auto-width behavior.
Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Api mismatch
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx
**Line:** 451:451
**Comment:**
*Api Mismatch: `TableView` does not enable managed widths, but this still sets `scroll.x` to `'max-content'`, forcing generic tables into horizontal scrolling and changing their auto-width behavior.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fixThere was a problem hiding this comment.
Not adopting this one. An unmanaged TableView deliberately keeps its pre-existing behavior (scroll.x: max-content with auto table layout); only list views that opt into managed column widths get the new fixed layout and frozen block. A TableView test pins that behavior, so generic tables are unchanged by this PR.
There was a problem hiding this comment.
✅ Customized review instruction saved!
Instruction:
Preserve the existing
scroll.x: 'max-content'and auto table layout for unmanagedTableViewinstances; apply fixed layout and frozen blocks only to list views that opt into managed column widths.
Applied to:
superset-frontend/packages/superset-ui-core/src/components/TableCollection/index.tsx
💡 To manage or update this instruction, visit: CodeAnt AI Settings
A database with OAuth2 enabled shows Edit, Export, Sync permissions, Manage OAuth2 tokens and Delete. Five icons end flush with the 120px actions cell, so the column uses the 168px actionsWide preset like the other five- and six-icon lists. A TableView test pins that generic tables keep the auto layout and content-width scroll. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unding - Annotation start and end dates render as short dates, so they use the relative-date width instead of the full timestamp width. - Focusing a cell inside the frozen leading block no longer scrolls the table back to the start. - The rounding remainder goes to the heaviest flexible column that still has room below its max. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| accessor: 'payload', | ||
| Header: t('Details'), | ||
| size: 'sm', | ||
| layout: 'statusIcons', |
There was a problem hiding this comment.
Suggestion: Rows with several task details, such as payload, dependency, and deduplication indicators, can exceed this fixed-width column and get clipped.
Assessment: 🟠 Major · 🔁 Occurrence: Sometimes · 🏷️ Logic error
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/src/pages/TaskList/index.tsx
**Line:** 567:567
**Comment:**
*Logic Error: Rows with several task details, such as payload, dependency, and deduplication indicators, can exceed this fixed-width column and get clipped.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| * contiguous run of columns from the start and freezing those would hide | ||
| * more than the row's name. | ||
| */ | ||
| export function getLeadingBlockLength(layouts: ColumnLayout[]): number { |
There was a problem hiding this comment.
Suggestion: This lookup recognizes only the 'title' string. A primary-name column using a supported custom min/max layout is not frozen and can scroll out of view.
Assessment: 🟠 Major · 🔁 Occurrence: Rarely · 🏷️ Api mismatch
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/packages/superset-ui-core/src/components/TableCollection/columnWidths.ts
**Line:** 271:271
**Comment:**
*Api Mismatch: This lookup recognizes only the `'title'` string. A primary-name column using a supported custom min/max layout is not frozen and can scroll out of view.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fixThere was a problem hiding this comment.
Not adopting this one. All 22 ListView consumers size their primary name column with the title preset, and none uses a custom {min,max}/{fixed} layout for it, so there is no consumer the current lookup misses. Instead of adding a freeze flag, the rule is now explicit: the getLeadingBlockLength doc comment states that only the title preset marks the frozen primary column, and the ListView.columnLayouts guard test fails if any list page introduces a custom layout object.
There was a problem hiding this comment.
✅ Customized review instruction saved!
Instruction:
Treat only the
titlepreset as identifying the frozen primary-name column; do not flag custom{min,max}or{fixed}layouts as supported primary-name layouts.
Applied to:
superset-frontend/packages/superset-ui-core/src/components/TableCollection/columnWidths.ts
💡 To manage or update this instruction, visit: CodeAnt AI Settings
…back A permanent scroll padding made the browser scroll to the start whenever a frozen cell took focus. Apply the frozen width as scroll padding only while a focused scrolling cell is brought into view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The task details cell can show up to four 16px indicator icons 8px apart, the last with a reuse count. Measured in Chrome that row takes 118px (+999), so the 64px statusIcons preset clipped anything past two icons. Widen the preset to 144px and add a regression test on the measured need. Also document that only the 'title' preset marks the frozen primary column, and guard that no list view page sizes a column with a custom layout object. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lumns antd makes sortable header cells focusable, and list views have no sticky header, so headers scroll with the body. Shift+Tab through the headers with the leading block frozen scrolled each one under the frozen header cells. The managed focus handler only handled body cells; it also handles header cells, so a focused header gets the same frozen-width scroll padding while frozen headers are left alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SUMMARY
The CRUD list tables (Datasets, Dashboards, Charts, Databases, Saved queries, Tags, ...) rendered with an auto table layout where only the Name column was pinned to a width (#37299). Any column without a
sizehint absorbed all spare container width, so Name looked squashed next to a huge, mostly-empty Actions column (Datasets, Dashboards) and an over-wide Type column (Charts); the same bug existed on other lists (Databases and Tags Actions were 1000px+ wide at 1920px).The table stack cannot express a min/max column range natively (react-table's
width/minWidth/maxWidthare only read by its layout plugins, which ListView does not use; antd/rc-table hasminWidthin auto layout only and nomaxWidth). This adds a small shared layer inTableCollectionthat every ListView-based page inherits:TableCollection/columnWidths.ts: oneCOLUMN_LAYOUT_PRESETStable plus a pureresolveColumnWidths(specs, containerWidth). Columns start at their minimum; spare width is shared by weight between the flexible columns, each capped at its maximum (if every flexible column is capped the remainder is still shared, so the table always fills its container); fixed columns never change.icon48,statusIcon48,statusIcons144,status144,flag176,count104,timer136,people120,iconList120,dateRelative176,dateTwoLine136,timestamp240,actions120 andactionsWide168 (5-6 icons). Flexible:title320-640 (the one primary column per list),text140-280,identifier180-360,longtext200-560,tags200-320.fixed: 'left'), but only if that block is at most 50% of the container and at least 240px remain scrollable. Focus is kept visible: scroll padding is applied only during the table's ownscrollIntoViewon focus, for body cells and sortable header cells, so a focused cell is never hidden under the frozen block.ListViewColumn.layouttakes a preset name or an explicit{ fixed }/{ min, max?, weight? }; legacysizestill works as a deprecated fixed width.TableCollectionmeasures its container and passes explicit pixel widths withtableLayout="fixed". This is opt-in viamanagedColumnWidths; onlyListViewenables it, soTableView,AlteredSliceTagand other tables are unchanged.sizehints, unknown presets, custom page layouts, or a page without exactly one title column).The numbers are a starting point that live in one table; they came from a benchmark of the options (public design systems and grid libraries, public name-length and viewport data, and a standalone antd harness that reproduces these widths), not from customer data.
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Datasets list at 1920px (same data, viewport and state; before = unmodified base):
Before
After
Measured on a live build (headless Chrome, normal / extreme-content / +40% text, 2560 to 768px): at 1920px Datasets Actions went from 916px to 120px and Name from 360px to ~590px; Dashboards Actions 447px -> 120px; Charts Type 555px -> bounded. Fixed columns have identical widths at every viewport, no action icon is clipped, and no page-level horizontal scroll appeared. Datasets, Dashboards and Charts do not scroll at 1440px or wider. Before/after pairs for Datasets, Dashboards and Charts at 1920/1440/1024, extreme-content pairs, hover states and the raw numbers are in the same Gist.
Known trade-offs: pages with few columns still give most of a very wide viewport to the title (fixed columns never grow and the table fills its container); Query history (11 columns) and Saved queries with Tags scroll inside the table at 1440px, where the old layout squeezed columns until values were cut off.
Shared title cell
Name cells that put the link in a flex row (Datasets, Dashboards, Charts, Themes) each carried a hand-copied
FlexRowContainer. Only the Dashboard and Chart copies had the rule that lets the link shrink and truncate, so Datasets (and Themes, whose tags were pushed out of the cell at 1440px and below) hard-clipped long names with no ellipsis. A newListViewTitleCellowns that behaviour once (badges before the title and tooltips/tags after it keep their size; the title truncates on one line with the full name in the tooltip), and the four per-page wrappers are deleted (-26 CSS declarations, +12 shared). The shared table styles are unchanged, and the other lists already truncate through the table cell.Before (Datasets, 120-character name, 1440px)
After
TESTING INSTRUCTIONS
npm test -- TableCollection ListView DatasetList DashboardList ChartList(resolver unit tests, managed-mode TableCollection tests, a guard test, freeze-guard and focus tests, renderer regression tests, and per-page tests asserting every visible column resolves within its preset bounds). jsdom cannot measure real layout, so the visual behaviour (widths, freezing, focus) was verified in headless Chrome on a live build and in a standalone harness; screenshots to follow.ADDITIONAL INFORMATION