Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .changeset/bright-cells-shine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
"@tailor-platform/app-shell": minor
---

Add `cellProps(row)`, `headerProps(ctx)`, and `footerProps(ctx)` callbacks to DataTable columns to set `className`, `style`, and `title` on the entire data/header/footer cell, including padding. Each can return `undefined` to keep the defaults; `headerProps` receives the same label and sort context as `header`, and `footerProps` receives the same current-page `rows` as `footer`.
Inline body-cell backgrounds remain visible on hover and selection, including in pinned columns. Footer styling is skipped during loading and errors and for hidden columns; it does not create a footer row by itself. Content, sorting, and context menus keep their existing behavior; existing tables are unchanged.

```tsx
column({
id: "hours",
type: "number",
headerProps: () => ({
style: { backgroundColor: "var(--muted)" },
title: "Monthly overtime hours",
}),
footer: ({ rows }) => rows.reduce((sum, row) => sum + row.hours, 0),
footerProps: ({ rows }) => ({
style: { backgroundColor: "var(--muted)" },
title: `Total overtime for ${rows.length} rows on this page`,
}),
cellProps: (row) =>
row.hours >= 60
? {
style: { backgroundColor: "var(--danger-solid)", color: "var(--danger-contrast)" },
title: "Overtime threshold exceeded",
}
: undefined,
});
```
8 changes: 4 additions & 4 deletions docs-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -473,10 +473,10 @@
],
"hashes": {
"typeSurface": "33eb2bdd6be1c774",
"outline": "8ca624c7ec761939",
"outline": "b3b98ba3cd0bd4a5",
"snapshot": "a97e067c66e46ef6",
"outputMd": "b1ee3ccb6cb4a1f4",
"examples": "10abd548e6affb9d"
"outputMd": "640e1060814bd7e9",
"examples": "c7f4624e218ed59f"
}
},
"date-picker": {
Expand Down Expand Up @@ -1787,7 +1787,7 @@
"packages/core/skills/app-shell-patterns/references/components/combobox.md": "dfb775c7c4307409",
"packages/core/skills/app-shell-patterns/references/components/command-palette.md": "7e5bc675a593791a",
"packages/core/skills/app-shell-patterns/references/components/csv-importer.md": "53d3c795ca21b9dc",
"packages/core/skills/app-shell-patterns/references/components/data-table.md": "b1ee3ccb6cb4a1f4",
"packages/core/skills/app-shell-patterns/references/components/data-table.md": "640e1060814bd7e9",
"packages/core/skills/app-shell-patterns/references/components/date-picker.md": "bc69f14829004f9d",
"packages/core/skills/app-shell-patterns/references/components/default-header.md": "375e55f4b12fa2be",
"packages/core/skills/app-shell-patterns/references/components/default-sidebar.md": "3422388a0cc78571",
Expand Down
72 changes: 72 additions & 0 deletions docs-src/components/data-table.docs.examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,67 @@ import {
useDataTable,
} from "@tailor-platform/app-shell";

export function PerCellStyling() {
type Overtime = { id: string; employee: string; january: number; february: number };
const { column } = createColumnHelper<Overtime>();
const overtimeStyle = (hours: number) => {
const tone = hours >= 60 ? "danger" : hours >= 40 ? "warning" : "success";
return {
backgroundColor: `var(--${tone}-solid)`,
color: `var(--${tone}-contrast)`,
};
};
const table = useDataTable({
data: {
rows: [
{ id: "1", employee: "Alex", january: 24, february: 48 },
{ id: "2", employee: "Sam", january: 45, february: 64 },
{ id: "3", employee: "Robin", january: 62, february: 32 },
],
},
columns: [
column({ id: "employee", label: "Employee", type: "text", width: 160 }),
column({
id: "january",
label: "January (hours)",
type: "number",
width: 180,
cellProps: (row) => ({
style: overtimeStyle(row.january),
title: `${row.january} hours of overtime`,
}),
}),
column({
id: "february",
label: "February (hours)",
type: "number",
width: 180,
pin: "right",
headerProps: () => ({
className: "astw:whitespace-nowrap",
style: { backgroundColor: "var(--muted)" },
title: "February overtime summary",
}),
cellProps: (row) => ({
className: "astw:tabular-nums",
style: overtimeStyle(row.february),
title: `${row.february} hours of overtime`,
}),
}),
],
rowSelection: {},
});

return (
<div className="space-y-3">
<p>Overtime: below 40 hours is safe, 40–59 is caution, 60 or more is danger.</p>
<DataTable.Root value={table}>
<DataTable.Table />
</DataTable.Root>
</div>
);
}

export function ColumnFooters() {
type Line = { id: string; item: string; quantity: number | null };
const [rows, setRows] = useState<Line[]>([
Expand Down Expand Up @@ -34,6 +95,17 @@ export function ColumnFooters() {
),
},
footer: aggregations.sum((row) => row.quantity),
footerProps: ({ rows }) =>
rows.length > 0
? {
className: "tabular-nums",
style: {
backgroundColor: "var(--success-solid)",
color: "var(--success-contrast)",
},
title: `Quantity total for ${rows.length} items on this page`,
}
: undefined,
}),
],
});
Expand Down
Loading
Loading