Skip to content

perf(data-table): improve data table layout and badge display - #5460

Merged
t0ng7u merged 12 commits into
mainfrom
perf/table-style
Jun 12, 2026
Merged

perf(data-table): improve data table layout and badge display#5460
t0ng7u merged 12 commits into
mainfrom
perf/table-style

Conversation

@QuentinHsu

@QuentinHsu QuentinHsu commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)

概述

  • 优化默认前端的数据表格体系,重点改善表头滚动、列配置、徽章展示和移动端行布局的一致性。

改动说明

  • 将 split header 的滚动同步改为 CSS sticky 表头,减少滚动监听和跨容器同步逻辑。
  • 支持通过列 meta 配置 pinned column、移动端标题/徽章/隐藏字段,并让字符串 header 自动使用排序列头组件。
  • 新增 BadgeListCell 统一处理徽章列表截断和 tooltip 展示,减少模型、分组、定价等表格里的重复渲染代码。
  • 扩展 StatusBadge 的 text/underline 展示类型,并在移动端字段区域用上下文切换为更紧凑的文本样式。
  • 调整多个业务表格列和 row actions 的对齐方式,让表格内容与列头视觉位置更一致。

效果

  • 表格滚动与固定列交互更轻量,移动端列表和桌面表格的徽章展示更统一。
  • 业务表格列定义更简洁,后续新增字段时可复用共享的 data-table meta 与 BadgeListCell 能力。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

  • Closes # (如有)

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

(请在此粘贴截图、关键日志或测试报告,以证明变更生效)

Summary by CodeRabbit

Release Notes

  • New Features

    • Added badge list cell component with automatic tooltip support for displaying multiple items
  • Improvements

    • Simplified column header rendering across all data tables
    • Optimized mobile card list layout and rendering performance
    • Enhanced keyboard navigation in bulk action menus
    • Pinned action columns for better table scrolling
  • Style & Visual Updates

    • Updated header background styling for improved color consistency
    • Refined badge alignment and spacing throughout tables
    • Enhanced status badge styling modes

- 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.
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

This 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.

Changes

Data Table Infrastructure Refactor and Column Standardization

Layer / File(s) Summary
Status Badge Type System and Context
src/components/status-badge.tsx
Introduces StatusBadgeType enum ('badge' | 'text' | 'underline') and StatusBadgeTypeContext to enable flexible badge styling. StatusBadge now accepts optional type prop and derives effective type from prop or context, supporting pill-based badges and plain text/underline variants.
BadgeListCell Component and Core Export
src/components/data-table/core/badge-list-cell.tsx, src/components/data-table/index.ts
New BadgeListCell component displays status badges with configurable max inline count, renders dash placeholder when empty, and wraps excess items in a scrollable tooltip. Re-exported from main data-table module.
Core Table Styling Updates
src/components/data-table/static/static-data-table-classnames.ts, src/components/data-table/core/column-pinning.ts, src/components/data-table/layout/data-table-page.tsx, src/components/ui/table.tsx
Replaces opacity-based backgrounds (bg-muted/30, hover:bg-muted/50) with explicit color-mix(...) expressions for header and row styling. Removes status-badge-specific margin selectors from TableCell. Updates header pinning class logic to use CSS variable fallbacks.
Core Table Rendering and Memoization
src/components/data-table/core/data-table-row.tsx, src/components/data-table/core/data-table-header.tsx, src/components/data-table/core/data-table-colgroup.tsx
Wraps DataTableRow with React.memo and custom comparator to skip re-renders when row, className, or selection state unchanged. Refactors header to use renderHeaderContent helper for string headers, meta labels, and placeholder handling. Updates colgroup to compute column widths as percentages of total visible size.
DataTableView Split Header and Meta-based Pinning
src/components/data-table/core/data-table-view.tsx
Restructures split-header view to render single sticky-positioned table header instead of dual-host layout; removes scroll synchronization logic. Adds getMetaPinnedColumns and mergePinnedColumns helpers to resolve column pinning from both TanStack meta and explicit props.
Hook Optimizations and Ref Caching
src/components/data-table/hooks/use-debounced-column-filter.ts, src/components/data-table/toolbar/bulk-actions.tsx, src/components/data-table/toolbar/view-options.tsx, src/components/data-table/toolbar/faceted-filter.tsx
Optimizes hook dependencies by storing callbacks in refs, caches toolbar buttons via useLayoutEffect for keyboard navigation, memoizes hideable column lists, extracts faceted-filter selection logic into getNextSelectedValues helper and wraps component with React.memo.
Toolbar Search State Refactor with IME Composition
src/components/data-table/toolbar/toolbar.tsx
Replaces ref-based search state with React state model including SearchDraft type, isSearchComposing flag, and debounce-driven commit logic. Queuing and event handlers rewritten to track draft edits and composition lifecycle, applying filter only when composition inactive and debounced value differs from committed value.
Mobile Card List Context Integration
src/components/data-table/layout/mobile-card-list.tsx
Wraps badge/provider cell content in StatusBadgeTypeContext with 'text' mode for mobile display, computes cellMetas once per render via useMemo for both CompactRow and FallbackRow, memoizes hasCompactMeta computation based on visible columns.
Provider Badge Explicit Props
src/components/provider-badge.tsx
Expands ProviderBadge to explicitly pass label, autoColor, size='sm', and conditional className='pl-0' (when no icon) to StatusBadge, replacing single-line invocation with structured prop passing.
Channels, Keys, Models Deployments, and Pricing Column Definitions
src/features/channels/components/channels-columns.tsx, src/features/keys/components/api-keys-columns.tsx, src/features/models/components/deployments-columns.tsx, src/features/pricing/components/pricing-columns.tsx
Systematically replace DataTableColumnHeader-based headers with direct t('...') translations, import and use BadgeListCell for Models/Groups/Tags/Endpoints/Groups columns, add -ml-1.5 badge alignment class consistently, update meta to use mobileHidden/mobileTitle/mobileBadge flags, and pin Actions columns right via meta: { pinned: 'right' }.
Models, Subscriptions, Redemption Codes, Users Column Definitions
src/features/models/components/models-columns.tsx, src/features/subscriptions/components/subscriptions-columns.tsx, src/features/redemption-codes/components/redemptions-columns.tsx, src/features/users/components/users-columns.tsx
Continue systematic column definition updates: use BadgeListCell for multi-item columns, replace header component renders with direct translations, add -ml-1.5 badge/spacing alignment throughout, update responsive metadata patterns, pin Actions columns right.
Usage Logs Column Definitions
src/features/usage-logs/components/columns/common-logs-columns.tsx, src/features/usage-logs/components/columns/drawing-logs-columns.tsx, src/features/usage-logs/components/columns/task-logs-columns.tsx
Replace DataTableColumnHeader usage with direct translated headers across all log table columns, add -ml-1.5 badge alignment for status/type columns, remove meta.label entries, standardize responsive metadata (mobileTitle/mobileHidden).
Row Actions Layout Adjustments
src/features/channels/components/data-table-row-actions.tsx, src/features/keys/components/data-table-row-actions.tsx, src/features/models/components/data-table-row-actions.tsx, src/features/redemption-codes/components/data-table-row-actions.tsx, src/features/subscriptions/components/data-table-row-actions.tsx, src/features/users/components/data-table-row-actions.tsx
Wraps dropdown menus in -ml-2/-ml-1.5 spaced containers and updates flex layout classes for consistent row action positioning across all feature tables.
System Settings and TanStack Meta Types
src/features/system-settings/models/model-ratio-table-columns.tsx, src/tanstack-table.d.ts
Updates model-ratio-table Mode column badge alignment by adding -ml-1.5 and removes select column label. Extends TanStack ColumnMeta type with pinned field ('left' | 'right'), mobile metadata (mobileTitle/mobileBadge/mobileHidden), and removes sortable field.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • QuantumNous/new-api#5393: Overlaps with toolbar search refactoring, adding debounce + IME composition guarding to the same search input logic.
  • QuantumNous/new-api#5405: Builds on shared data-table infrastructure by updating core table/pinning modules with related styling and column resolution changes.

Suggested reviewers

  • Calcium-Ion
  • creamlike1024
  • seefs001

🐰 A badge here, a badge there,
Context wraps them everywhere!
Columns sorted, headers clean,
Best refactor ever seen!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.37% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'perf(data-table): improve data table layout and badge display' accurately summarizes the main changes: performance improvements to the data table system focusing on layout optimization and badge rendering consolidation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/table-style

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@t0ng7u
t0ng7u merged commit 27b2b2c into main Jun 12, 2026
1 of 2 checks passed
@Calcium-Ion
Calcium-Ion deleted the perf/table-style branch June 13, 2026 08:34
ruanhangjian pushed a commit to ruanhangjian/new-api that referenced this pull request Jul 11, 2026
…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>
zhaodechao2008 pushed a commit to zhaodechao2008/new-api that referenced this pull request Jul 27, 2026
…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>
330079598 pushed a commit to 330079598/new-api that referenced this pull request Aug 19, 2026
…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>
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