perf(data-table): improve data table layout and badge display - #5460
Conversation
- compute each column's width as a percentage of total column size instead of a fixed pixel value, letting the colgroup scale fluidly with the table container.
- stabilize commitSearchValue in toolbar by reading table/searchKey via refs, eliminating recreation on every parent render - store onColumnFiltersChange in a ref so debounce effect is not reset when the caller passes a new function reference each render - wrap DataTableRow in React.memo with a custom comparator that ignores getColumnClassName reference churn - memoize selectedValues Set in DataTableFacetedFilter and wrap with React.memo to prevent rerenders on unrelated state changes - cache cell meta reads in CompactRow and FallbackRow to a single pass per row; memoize hasCompactMeta in MobileCardList - memoize hideable columns list in DataTableViewOptions and colSpan in DataTableView - remove tableClassName and colgroup from scroll-sync effect deps; cache toolbar button NodeList via useLayoutEffect to avoid per-keydown DOM queries
- remove JS scroll-sync effect and event listener between split header and body containers. - merge separate header/body tables into a single scrollable table element, reducing DOM complexity. - apply CSS sticky positioning to the header for a simpler, hardware-accelerated freeze effect.
- switch from bg-muted/50 and bg-muted/30 to color-mix(in oklch) to produce opaque blended backgrounds that prevent scroll content from showing through pinned cells. - expose --table-header-bg CSS variable so pinned header cells inherit the exact same computed color as the thead background. - add group class to TableRow to enable group-hover selectors on pinned cell styles.
- add pinned?: 'left' | 'right' to ColumnMeta so pinning is declared once in the column definition and applies to both header and body automatically - DataTableView derives pinnedColumns from meta.pinned at runtime, merged with any explicit pinnedColumns prop; explicit entries take precedence - add header and meta.pinned: 'right' to all actions columns across channels, users, api-keys, redemption-codes, models, deployments, and subscriptions tables
…nment - add BadgeListCell component to data-table for badge lists with overflow tooltip, replacing duplicated renderLimitedItems helpers in channels, models, and pricing columns - move StatusBadge -ml-1.5 alignment into the component itself via a table-cell context selector, so callers no longer need manual offset wrappers - remove the table-cell-level -ml-1.5 selector from TableCell now that alignment is handled by StatusBadge directly
…tion - move mobileTitle, mobileBadge, mobileHidden into the global ColumnMeta augmentation so the type is shared across the project - remove the local MobileColumnMeta interface and getCellMeta helper from mobile-card-list.tsx - direct col.columnDef.meta access is now type-safe without explicit casting
- auto-render string `header` values via DataTableColumnHeader so sortable/non-sortable columns work without boilerplate function wrappers
- promote mobile layout hints (mobileTitle, mobileBadge, mobileHidden) into the global ColumnMeta type, removing the local MobileColumnMeta cast in mobile-card-list
- migrate all column files from `meta: { label }` to top-level `header: t('...')`, cutting ~180 lines of repetitive template code
- ViewOptions and MobileCardList label resolution now reads string header first, then meta.label as fallback
- introduce StatusBadgeType ('badge' | 'text' | 'underline') and StatusBadgeTypeContext so ancestors can override rendering without touching call sites
- mobile card field rows now use the text type via context, showing badges as plain colored text instead of pills
- ProviderBadge gains data-slot='provider-badge' to enable targeted CSS resets in compact layouts
- replace the implicit [[data-slot=table-cell]>&]:-ml-1.5 rule with explicit -ml-1.5 at each column call site
- derive toolbar search state from the active table filter to avoid render-time ref writes. - extract faceted filter selection updates into a pure helper for clearer single and multi-select behavior. - split pinned column resolution into focused helpers so explicit and meta pins merge predictably.
|
Caution Review failedPull request was closed or merged during review WalkthroughThis PR refactors the data-table infrastructure and column definitions across the application. It introduces a StatusBadge type system with context support, adds a new BadgeListCell component for rendering badge lists with overflow handling, optimizes core table rendering via memoization and hook improvements, restructures the toolbar search with IME composition tracking, and systematically updates column definitions to use direct translated headers and consistent badge alignment. ChangesData Table Infrastructure Refactor and Column Standardization
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…mNous#5460) * perf(table): use percentage-based column widths - compute each column's width as a percentage of total column size instead of a fixed pixel value, letting the colgroup scale fluidly with the table container. * perf(data-table): reduce unnecessary re-renders across table components - stabilize commitSearchValue in toolbar by reading table/searchKey via refs, eliminating recreation on every parent render - store onColumnFiltersChange in a ref so debounce effect is not reset when the caller passes a new function reference each render - wrap DataTableRow in React.memo with a custom comparator that ignores getColumnClassName reference churn - memoize selectedValues Set in DataTableFacetedFilter and wrap with React.memo to prevent rerenders on unrelated state changes - cache cell meta reads in CompactRow and FallbackRow to a single pass per row; memoize hasCompactMeta in MobileCardList - memoize hideable columns list in DataTableViewOptions and colSpan in DataTableView - remove tableClassName and colgroup from scroll-sync effect deps; cache toolbar button NodeList via useLayoutEffect to avoid per-keydown DOM queries * perf(data-table): replace scroll-sync split header with CSS sticky - remove JS scroll-sync effect and event listener between split header and body containers. - merge separate header/body tables into a single scrollable table element, reducing DOM complexity. - apply CSS sticky positioning to the header for a simpler, hardware-accelerated freeze effect. * fix(data-table): replace opacity muted colors with color-mix - switch from bg-muted/50 and bg-muted/30 to color-mix(in oklch) to produce opaque blended backgrounds that prevent scroll content from showing through pinned cells. - expose --table-header-bg CSS variable so pinned header cells inherit the exact same computed color as the thead background. - add group class to TableRow to enable group-hover selectors on pinned cell styles. * feat(data-table): support column pinning via meta.pinned - add pinned?: 'left' | 'right' to ColumnMeta so pinning is declared once in the column definition and applies to both header and body automatically - DataTableView derives pinnedColumns from meta.pinned at runtime, merged with any explicit pinnedColumns prop; explicit entries take precedence - add header and meta.pinned: 'right' to all actions columns across channels, users, api-keys, redemption-codes, models, deployments, and subscriptions tables * style(row-actions): align action buttons to leading edge of column * refactor(data-table): extract BadgeListCell and centralize badge alignment - add BadgeListCell component to data-table for badge lists with overflow tooltip, replacing duplicated renderLimitedItems helpers in channels, models, and pricing columns - move StatusBadge -ml-1.5 alignment into the component itself via a table-cell context selector, so callers no longer need manual offset wrappers - remove the table-cell-level -ml-1.5 selector from TableCell now that alignment is handled by StatusBadge directly * style(row-actions): offset action buttons to align with column header text * refactor(data-table): consolidate mobile meta into ColumnMeta declaration - move mobileTitle, mobileBadge, mobileHidden into the global ColumnMeta augmentation so the type is shared across the project - remove the local MobileColumnMeta interface and getCellMeta helper from mobile-card-list.tsx - direct col.columnDef.meta access is now type-safe without explicit casting * refactor(data-table): simplify column header and meta config - auto-render string `header` values via DataTableColumnHeader so sortable/non-sortable columns work without boilerplate function wrappers - promote mobile layout hints (mobileTitle, mobileBadge, mobileHidden) into the global ColumnMeta type, removing the local MobileColumnMeta cast in mobile-card-list - migrate all column files from `meta: { label }` to top-level `header: t('...')`, cutting ~180 lines of repetitive template code - ViewOptions and MobileCardList label resolution now reads string header first, then meta.label as fallback * feat(status-badge): add text and underline display types - introduce StatusBadgeType ('badge' | 'text' | 'underline') and StatusBadgeTypeContext so ancestors can override rendering without touching call sites - mobile card field rows now use the text type via context, showing badges as plain colored text instead of pills - ProviderBadge gains data-slot='provider-badge' to enable targeted CSS resets in compact layouts - replace the implicit [[data-slot=table-cell]>&]:-ml-1.5 rule with explicit -ml-1.5 at each column call site * refactor(data-table): simplify table filtering internals - derive toolbar search state from the active table filter to avoid render-time ref writes. - extract faceted filter selection updates into a pure helper for clearer single and multi-select behavior. - split pinned column resolution into focused helpers so explicit and meta pins merge predictably. Co-authored-by: t0ng7u <dev@aiass.cc>
…mNous#5460) * perf(table): use percentage-based column widths - compute each column's width as a percentage of total column size instead of a fixed pixel value, letting the colgroup scale fluidly with the table container. * perf(data-table): reduce unnecessary re-renders across table components - stabilize commitSearchValue in toolbar by reading table/searchKey via refs, eliminating recreation on every parent render - store onColumnFiltersChange in a ref so debounce effect is not reset when the caller passes a new function reference each render - wrap DataTableRow in React.memo with a custom comparator that ignores getColumnClassName reference churn - memoize selectedValues Set in DataTableFacetedFilter and wrap with React.memo to prevent rerenders on unrelated state changes - cache cell meta reads in CompactRow and FallbackRow to a single pass per row; memoize hasCompactMeta in MobileCardList - memoize hideable columns list in DataTableViewOptions and colSpan in DataTableView - remove tableClassName and colgroup from scroll-sync effect deps; cache toolbar button NodeList via useLayoutEffect to avoid per-keydown DOM queries * perf(data-table): replace scroll-sync split header with CSS sticky - remove JS scroll-sync effect and event listener between split header and body containers. - merge separate header/body tables into a single scrollable table element, reducing DOM complexity. - apply CSS sticky positioning to the header for a simpler, hardware-accelerated freeze effect. * fix(data-table): replace opacity muted colors with color-mix - switch from bg-muted/50 and bg-muted/30 to color-mix(in oklch) to produce opaque blended backgrounds that prevent scroll content from showing through pinned cells. - expose --table-header-bg CSS variable so pinned header cells inherit the exact same computed color as the thead background. - add group class to TableRow to enable group-hover selectors on pinned cell styles. * feat(data-table): support column pinning via meta.pinned - add pinned?: 'left' | 'right' to ColumnMeta so pinning is declared once in the column definition and applies to both header and body automatically - DataTableView derives pinnedColumns from meta.pinned at runtime, merged with any explicit pinnedColumns prop; explicit entries take precedence - add header and meta.pinned: 'right' to all actions columns across channels, users, api-keys, redemption-codes, models, deployments, and subscriptions tables * style(row-actions): align action buttons to leading edge of column * refactor(data-table): extract BadgeListCell and centralize badge alignment - add BadgeListCell component to data-table for badge lists with overflow tooltip, replacing duplicated renderLimitedItems helpers in channels, models, and pricing columns - move StatusBadge -ml-1.5 alignment into the component itself via a table-cell context selector, so callers no longer need manual offset wrappers - remove the table-cell-level -ml-1.5 selector from TableCell now that alignment is handled by StatusBadge directly * style(row-actions): offset action buttons to align with column header text * refactor(data-table): consolidate mobile meta into ColumnMeta declaration - move mobileTitle, mobileBadge, mobileHidden into the global ColumnMeta augmentation so the type is shared across the project - remove the local MobileColumnMeta interface and getCellMeta helper from mobile-card-list.tsx - direct col.columnDef.meta access is now type-safe without explicit casting * refactor(data-table): simplify column header and meta config - auto-render string `header` values via DataTableColumnHeader so sortable/non-sortable columns work without boilerplate function wrappers - promote mobile layout hints (mobileTitle, mobileBadge, mobileHidden) into the global ColumnMeta type, removing the local MobileColumnMeta cast in mobile-card-list - migrate all column files from `meta: { label }` to top-level `header: t('...')`, cutting ~180 lines of repetitive template code - ViewOptions and MobileCardList label resolution now reads string header first, then meta.label as fallback * feat(status-badge): add text and underline display types - introduce StatusBadgeType ('badge' | 'text' | 'underline') and StatusBadgeTypeContext so ancestors can override rendering without touching call sites - mobile card field rows now use the text type via context, showing badges as plain colored text instead of pills - ProviderBadge gains data-slot='provider-badge' to enable targeted CSS resets in compact layouts - replace the implicit [[data-slot=table-cell]>&]:-ml-1.5 rule with explicit -ml-1.5 at each column call site * refactor(data-table): simplify table filtering internals - derive toolbar search state from the active table filter to avoid render-time ref writes. - extract faceted filter selection updates into a pure helper for clearer single and multi-select behavior. - split pinned column resolution into focused helpers so explicit and meta pins merge predictably. Co-authored-by: t0ng7u <dev@aiass.cc>
…mNous#5460) * perf(table): use percentage-based column widths - compute each column's width as a percentage of total column size instead of a fixed pixel value, letting the colgroup scale fluidly with the table container. * perf(data-table): reduce unnecessary re-renders across table components - stabilize commitSearchValue in toolbar by reading table/searchKey via refs, eliminating recreation on every parent render - store onColumnFiltersChange in a ref so debounce effect is not reset when the caller passes a new function reference each render - wrap DataTableRow in React.memo with a custom comparator that ignores getColumnClassName reference churn - memoize selectedValues Set in DataTableFacetedFilter and wrap with React.memo to prevent rerenders on unrelated state changes - cache cell meta reads in CompactRow and FallbackRow to a single pass per row; memoize hasCompactMeta in MobileCardList - memoize hideable columns list in DataTableViewOptions and colSpan in DataTableView - remove tableClassName and colgroup from scroll-sync effect deps; cache toolbar button NodeList via useLayoutEffect to avoid per-keydown DOM queries * perf(data-table): replace scroll-sync split header with CSS sticky - remove JS scroll-sync effect and event listener between split header and body containers. - merge separate header/body tables into a single scrollable table element, reducing DOM complexity. - apply CSS sticky positioning to the header for a simpler, hardware-accelerated freeze effect. * fix(data-table): replace opacity muted colors with color-mix - switch from bg-muted/50 and bg-muted/30 to color-mix(in oklch) to produce opaque blended backgrounds that prevent scroll content from showing through pinned cells. - expose --table-header-bg CSS variable so pinned header cells inherit the exact same computed color as the thead background. - add group class to TableRow to enable group-hover selectors on pinned cell styles. * feat(data-table): support column pinning via meta.pinned - add pinned?: 'left' | 'right' to ColumnMeta so pinning is declared once in the column definition and applies to both header and body automatically - DataTableView derives pinnedColumns from meta.pinned at runtime, merged with any explicit pinnedColumns prop; explicit entries take precedence - add header and meta.pinned: 'right' to all actions columns across channels, users, api-keys, redemption-codes, models, deployments, and subscriptions tables * style(row-actions): align action buttons to leading edge of column * refactor(data-table): extract BadgeListCell and centralize badge alignment - add BadgeListCell component to data-table for badge lists with overflow tooltip, replacing duplicated renderLimitedItems helpers in channels, models, and pricing columns - move StatusBadge -ml-1.5 alignment into the component itself via a table-cell context selector, so callers no longer need manual offset wrappers - remove the table-cell-level -ml-1.5 selector from TableCell now that alignment is handled by StatusBadge directly * style(row-actions): offset action buttons to align with column header text * refactor(data-table): consolidate mobile meta into ColumnMeta declaration - move mobileTitle, mobileBadge, mobileHidden into the global ColumnMeta augmentation so the type is shared across the project - remove the local MobileColumnMeta interface and getCellMeta helper from mobile-card-list.tsx - direct col.columnDef.meta access is now type-safe without explicit casting * refactor(data-table): simplify column header and meta config - auto-render string `header` values via DataTableColumnHeader so sortable/non-sortable columns work without boilerplate function wrappers - promote mobile layout hints (mobileTitle, mobileBadge, mobileHidden) into the global ColumnMeta type, removing the local MobileColumnMeta cast in mobile-card-list - migrate all column files from `meta: { label }` to top-level `header: t('...')`, cutting ~180 lines of repetitive template code - ViewOptions and MobileCardList label resolution now reads string header first, then meta.label as fallback * feat(status-badge): add text and underline display types - introduce StatusBadgeType ('badge' | 'text' | 'underline') and StatusBadgeTypeContext so ancestors can override rendering without touching call sites - mobile card field rows now use the text type via context, showing badges as plain colored text instead of pills - ProviderBadge gains data-slot='provider-badge' to enable targeted CSS resets in compact layouts - replace the implicit [[data-slot=table-cell]>&]:-ml-1.5 rule with explicit -ml-1.5 at each column call site * refactor(data-table): simplify table filtering internals - derive toolbar search state from the active table filter to avoid render-time ref writes. - extract faceted filter selection updates into a pure helper for clearer single and multi-select behavior. - split pinned column resolution into focused helpers so explicit and meta pins merge predictably. Co-authored-by: t0ng7u <dev@aiass.cc>
Important
📝 变更描述 / Description
(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
概述
改动说明
效果
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
Summary by CodeRabbit
Release Notes
New Features
Improvements
Style & Visual Updates