Skip to content

feat(data-table): add cell and header props customization - #631

Merged
IzumiSy merged 10 commits into
mainfrom
feat/datatable-cell-header-props
Oct 29, 2026
Merged

IzumiSy merged 10 commits into
mainfrom
feat/datatable-cell-header-props

Conversation

@IzumiSy

@IzumiSy IzumiSy commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

DataTable custom renderers control a cell's content, but cannot style the surrounding cell element. Tables that use background color to communicate row-dependent information cannot reproduce that presentation with a colored span: the cell's padding remains unpainted. Header renderers have the same limitation when a column needs header-level styling.

Related: https://github.com/tailor-inc/platform-planning/issues/2185

Design Decision

Separate content rendering from element customization

Add three column-level callbacks: row-aware cellProps(row) for data-cell <td> elements, headerProps(ctx) for the column's header <th>, and footerProps(ctx) for its footer <td>. All three support only className, style, and title, and may return undefined to keep the defaults.

Existing render(row), header(ctx), and footer continue to own content. headerProps receives the same HeaderRenderContext as header, allowing sort-dependent styling. footerProps receives the same FooterRenderContext as the footer renderer, including the current page's rows; it does not create a footer row by itself. Arbitrary events, refs, and cell spanning are deliberately not exposed, so consumers do not need to coordinate with DataTable's editing, selection, or context-menu behavior.

Preserve table-owned layout and state behavior

Merge consumer classes after built-in classes, and merge inline styles before the declared column width and computed sticky positioning. Explicit inline cell backgrounds remain visible during hover and selection; cells that do not opt in retain their existing appearance and behavior. CSS specificity still applies to class-based backgrounds, and pinned body cells, headers, and footer cells require opaque backgrounds to hide scrolling content.

Alternatives considered

Allowing renderers to replace the entire cell element would transfer responsibility for pinning and interaction props to consumers. A style-only hook would solve the immediate background-color case but introduce a separate API for each additional presentation attribute. A narrowly scoped props object provides a single customization point without opening arbitrary DOM overrides.

Summary

  • Add row-aware cellProps(row), context-aware headerProps(ctx), and footerProps(ctx) across default and custom rendering paths, including truncated and editable body cells.
  • Cover style/class merging, left/right pinning and width precedence, property removal, and preservation of sorting and context menus with regression tests.
  • Document the API boundaries and background-state behavior with a runnable example, regenerate documentation, and include a minor changeset.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Code Metrics Report

main (eee5b85) #631 (b84c9af) +/-
Coverage 89.5% 89.5% +0.0%
Test Execution Time 3m29s 3m29s 0s
Details
  |                     | main (eee5b85) | #631 (b84c9af) |  +/-  |
  |---------------------|----------------|----------------|-------|
+ | Coverage            |          89.5% |          89.5% | +0.0% |
  |   Files             |            236 |            236 |     0 |
  |   Lines             |           7512 |           7517 |    +5 |
+ |   Covered           |           6727 |           6732 |    +5 |
  | Test Execution Time |          3m29s |          3m29s |    0s |

Code coverage of files in pull request scope (93.7% → 93.8%, patch 100.0%)

Files Coverage +/- Patch Coverage Status
packages/core/src/components/data-table/data-table.tsx 93.8% +0.0% 100.0% modified

Reported by octocov

@IzumiSy
IzumiSy marked this pull request as ready for review October 22, 2026 04:45
@IzumiSy
IzumiSy requested a review from a team as a code owner October 22, 2026 04:45
@IzumiSy
IzumiSy marked this pull request as draft October 22, 2026 05:04
@IzumiSy

IzumiSy commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

I would like to rebase this PR and cover footerProps as well once #633 gets merged.

@IzumiSy

IzumiSy commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

…eader-props

# Conflicts:
#	docs-manifest.json
#	docs-src/components/data-table.docs.examples.tsx
#	docs-src/components/data-table.docs.outline.md
#	docs/components/data-table.md
#	packages/core/src/components/data-table/types.ts

Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>

Copilot AI commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Merged main and resolved the conflicts, preserving the cell/header props API alongside the new column-footer support. Merge commit: 726ded3.

@IzumiSy
IzumiSy marked this pull request as ready for review October 26, 2026 07:01
@IzumiSy
IzumiSy requested a balanced review from Copilot October 26, 2026 07:01
@IzumiSy

IzumiSy commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

/review

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Code Review has started processing this issue comment

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation, tests, and documentation consistently support the callback APIs; only a non-blocking PR-description correction remains.

1 open issue
What changed in this PR

Adds DataTable column customization for surrounding body, header, and footer elements, allowing full-cell styling without replacing content renderers.

Changes:

  • Adds cellProps(row), headerProps(ctx), and footerProps(ctx) callbacks supporting classes, inline styles, and titles.
  • Adds regression coverage for styling, property removal, pinning, width precedence, and existing interactions.
  • Documents the APIs with runnable examples and includes a minor-release changeset.
File Description
packages/​core/​src/​components/​data-table/​types.ts Defines the three customization callbacks and their contracts.
packages/​core/​src/​components/​data-table/​data-table.tsx Applies custom props to body, header, and footer cells.
packages/​core/​src/​components/​data-table/​data-table.test.tsx Covers header sort context and preserved interactions.
packages/​core/​src/​components/​data-table/​data-table-styling.test.tsx Adds styling, pinning, and lifecycle regression coverage.
docs/​components/​data-table.md Updates generated API documentation and examples.
docs-src/​components/​data-table.docs.outline.md Documents customization boundaries and behavior.
docs-src/​components/​data-table.docs.examples.tsx Adds full-cell styling and styled-footer examples.
docs-manifest.json Updates documentation generation hashes.
.changeset/​bright-cells-shine.md Records the new APIs for a minor release.

Review effort: Balanced

Comment thread packages/core/src/components/data-table/types.ts
@IzumiSy

IzumiSy commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

…eader-props

# Conflicts:
#	docs-manifest.json
#	docs-src/components/data-table.docs.examples.tsx
#	docs-src/components/data-table.docs.outline.md
#	docs/components/data-table.md

Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>

Copilot AI commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Merged the latest main and resolved the documentation conflicts, preserving both the DataTable props API and aggregation support. Merge commit: 102538c.

@IzumiSy

IzumiSy commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

…eader-props

# Conflicts:
#	docs-manifest.json

Co-authored-by: IzumiSy <982850+IzumiSy@users.noreply.github.com>

Copilot AI commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Merged the latest main and resolved the generated documentation manifest conflict by regenerating docs from the merged authored sources. Merge commit: c51f3a3.

@interacsean interacsean left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one loose thought comment, but I think let's go!


Use `cellProps(row)` to set `className`, `style`, and `title` on the actual data-cell `<td>`, including its padding. Return `undefined` to keep the defaults. This works with built-in renderers, custom `render`, truncation tooltips, and editable cells. It does not customize headers, footers, loading placeholders, empty/error states, or the built-in selection, expansion, and action cells. Content stays owned by `render`; events, refs, and cell spanning are not supported through `cellProps`.

An explicit `style.backgroundColor` stays visible during row hover and selection, for both scrollable and pinned columns. Cells returning `undefined` retain the default hover/selection backgrounds; checkboxes and row selection semantics are unchanged. Classes are merged after built-in classes, but CSS specificity still applies: pinned cells have their own group-hover and group-aria-selected backgrounds, which a plain background class does not override. Use `style.backgroundColor` when an informational background must remain visible in every state. Keep the value or another non-color cue visible so color is not the only way to understand the cell.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something for the future: it seems there is no way to set the backgroundColor of a hover or selected state cell

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is possible with the existing cellProps.className hook. For example, with Tailwind v4:

cellProps: () => ({
  className: `
    bg-orange-50!
    [tr:not([aria-selected=true]):hover_&]:bg-orange-200!
    [tr[aria-selected=true]_&]:bg-orange-300!
  `,
}),

This uses a light background normally, a darker one when hovering an unselected row, and another background while selected. Selection takes precedence even when hovering.

The arbitrary variants target the parent row’s state, and the ! modifiers override the built-in pinned-cell backgrounds.

The inline backgroundColor example in this doc is intended to preserve the same background across states. For state-specific backgrounds, they can be defined entirely in className instead—no separate CSS file or additional API is needed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well my thoughts are while this is some handy CSS work, it is not ergonomic, it's not guided so if a consumer needed to do it, it would be on the dev/agent to work out how, and the aria-selected on the tr relies on something the appshell is doing internally.

Let's just leave it for now anyway

@IzumiSy
IzumiSy merged commit b8ead52 into main Oct 29, 2026
8 checks passed
@IzumiSy
IzumiSy deleted the feat/datatable-cell-header-props branch October 29, 2026 03:43
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.

4 participants