Skip to content

Commit ec4211c

Browse files
Merge pull request #868 from gadget-inc/mill/AutoTableCustomHeaderRenderers
Updated AutoTable to allow custom column header components
2 parents c8da7f4 + 707a6db commit ec4211c

File tree

9 files changed

+63
-29
lines changed

9 files changed

+63
-29
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@gadgetinc/react": patch
3+
---
4+
5+
Updated AutoTable to allow custom column header components

packages/react/spec/auto/hooks/useTable.spec.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,10 @@ describe("useTable hook", () => {
313313
}
314314
}"
315315
`);
316-
expect(result.current[0].columns?.map((column) => column.field)).toEqual(["name", "inventoryCount"]);
316+
expect(result.current[0].columns?.map((column) => (column.type === "CustomRenderer" ? undefined : column.field))).toEqual([
317+
"name",
318+
"inventoryCount",
319+
]);
317320
expect(result.current[0].rows).toMatchInlineSnapshot(`
318321
[
319322
{
@@ -380,7 +383,7 @@ describe("useTable hook", () => {
380383
}
381384
}"
382385
`);
383-
expect(result.current[0].columns?.map((column) => column.field)).toEqual([
386+
expect(result.current[0].columns?.map((column) => (column.type === "CustomRenderer" ? undefined : column.field))).toEqual([
384387
"name",
385388
"hasMany",
386389
"hasOne",
@@ -463,7 +466,7 @@ describe("useTable hook", () => {
463466
}
464467
}"
465468
`);
466-
expect(result.current[0].columns?.map((column) => column.field)).toEqual([
469+
expect(result.current[0].columns?.map((column) => (column.type === "CustomRenderer" ? undefined : column.field))).toEqual([
467470
"name",
468471
"hasMany.edges.node.name",
469472
"hasOne.name",
@@ -574,7 +577,6 @@ describe("useTable hook", () => {
574577
"type": "String",
575578
},
576579
{
577-
"field": "Custom column",
578580
"header": "Custom column",
579581
"identifier": "000-000-000-000-1",
580582
"render": [Function],
@@ -654,7 +656,7 @@ describe("useTable hook", () => {
654656
`);
655657

656658
// The list should not contain "name" and "inventoryCount" because they are excluded
657-
expect(result.current[0].columns?.map((column) => column.field)).toEqual([
659+
expect(result.current[0].columns?.map((column) => (column.type === "CustomRenderer" ? undefined : column.field))).toEqual([
658660
"id",
659661
"anything",
660662
"description",

packages/react/spec/auto/polaris/table/PolarisAutoTable.spec.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ describe("PolarisAutoTable", () => {
287287
{
288288
identifier: sampleUUID1,
289289
header: "Custom cell",
290-
field: "Custom cell",
290+
render: () => "Custom cell",
291291
type: "CustomRenderer",
292292
sortable: false,
293293
},
@@ -351,14 +351,14 @@ describe("PolarisAutoTable", () => {
351351
{
352352
identifier: sampleUUID1,
353353
header: "Custom cell",
354-
field: "Custom cell",
354+
render: () => "Custom cell",
355355
type: "CustomRenderer",
356356
sortable: false,
357357
},
358358
{
359359
identifier: sampleUUID2,
360360
header: "Custom cell",
361-
field: "Custom cell",
361+
render: () => "Custom cell",
362362
type: "CustomRenderer",
363363
sortable: false,
364364
},

packages/react/spec/auto/storybook/table/AutoTable.stories.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,17 +169,31 @@ const CustomCheckboxCell = ({ record }: { record: any }) => {
169169
);
170170
};
171171

172+
const ColorChangingText = (props: { text: string }) => {
173+
const [color, setColor] = React.useState("#000000");
174+
175+
React.useEffect(() => {
176+
const interval = setInterval(() => {
177+
const randomColor = "#" + Math.floor(Math.random() * 16777215).toString(16);
178+
setColor(randomColor);
179+
}, 1000);
180+
181+
return () => clearInterval(interval);
182+
}, []);
183+
return <div style={{ color }}>{props.text}</div>;
184+
};
185+
172186
export const CustomCellWithUseAction: any = {
173187
args: {
174188
model: api.autoTableTest,
175189
columns: [
176190
"bool",
177191
{
178-
header: "Pass the whole function",
192+
header: <ColorChangingText text="Pass the whole function" />,
179193
render: CustomCheckboxCell,
180194
},
181195
{
182-
header: "JSX style",
196+
header: <ColorChangingText text="JSX style" />,
183197
render: (props: any) => <CustomCheckboxCell {...props} />,
184198
},
185199
],

packages/react/src/auto/polaris/PolarisAutoTable.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ const gadgetToPolarisDirection = (direction?: SortOrder) => {
4949
return undefined;
5050
};
5151

52-
const getColumnIndex = (columns: TableColumn[], apiIdentifier: string | undefined) => {
53-
return columns.findIndex((column) => column.field === apiIdentifier);
52+
const maybeGetColumnIndex = (columns: TableColumn[], apiIdentifier: string | undefined) => {
53+
return columns.findIndex((column) => (column.type === "CustomRenderer" ? undefined : column.field === apiIdentifier));
5454
};
5555

5656
export type PolarisAutoTableProps<
@@ -127,8 +127,11 @@ const PolarisAutoTableComponent = <
127127

128128
const handleColumnSort = (headingIndex: number) => {
129129
if (columns) {
130-
const columnApiIdentifier = columns[headingIndex].field;
131-
sort.handleColumnSort(columnApiIdentifier);
130+
const currentColumn = columns[headingIndex];
131+
const columnApiIdentifier = currentColumn.type === "CustomRenderer" ? undefined : currentColumn.field;
132+
if (columnApiIdentifier) {
133+
sort.handleColumnSort(columnApiIdentifier);
134+
}
132135
}
133136
};
134137

@@ -147,7 +150,9 @@ const PolarisAutoTableComponent = <
147150

148151
if (columns) {
149152
for (const column of columns) {
150-
headings.push({ title: column.header });
153+
headings.push({
154+
title: column.header as string, // Polaris type says that this must be a string, but this works with a ReactNode
155+
});
151156
sortable.push(column.sortable);
152157
}
153158
}
@@ -247,7 +252,7 @@ const PolarisAutoTableComponent = <
247252
: undefined
248253
}
249254
sortDirection={gadgetToPolarisDirection(sort.direction)}
250-
sortColumnIndex={columns ? getColumnIndex(columns, sort.column) : undefined}
255+
sortColumnIndex={columns ? maybeGetColumnIndex(columns, sort.column) : undefined}
251256
onSort={(headingIndex) => handleColumnSort(headingIndex)}
252257
selectable={props.selectable === undefined ? bulkActionOptions.length !== 0 : props.selectable}
253258
lastColumnSticky={props.lastColumnSticky}

packages/react/src/auto/shadcn/ShadcnAutoTable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export const makeAutoTable = (elements: ShadcnElements) => {
139139
variant="ghost"
140140
size="sm"
141141
className="cursor-pointer"
142-
onClick={() => sort.handleColumnSort(column.field)}
142+
onClick={() => (column.type === "CustomRenderer" ? undefined : sort.handleColumnSort(column.field))}
143143
{...hoverProps}
144144
>
145145
{ColumnHeaderLabel}

packages/react/src/auto/shadcn/table/ShadcnAutoTableColumnSortIndicator.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ export const makeShadcnAutoTableColumnSortIndicator = (elements: ShadcnElements)
1212
function ShadcnAutoTableColumnSortIndicator(props: { column: TableColumn; sortState: SortState; isHovered: boolean }) {
1313
const { column, sortState, isHovered } = props;
1414
const handleSort = useCallback(() => {
15+
if (column.type === "CustomRenderer") {
16+
return;
17+
}
1518
sortState.handleColumnSort(column.field);
16-
}, [sortState, column.field]);
19+
}, [sortState, column.type, column.type === "CustomRenderer" ? undefined : column.field]);
1720

18-
if (!column.sortable) {
21+
if (!column.sortable || column.type === "CustomRenderer") {
1922
return null;
2023
}
2124

packages/react/src/use-table/helpers.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ export const getTableColumns = (spec: Pick<TableSpec, "fieldMetadataTree" | "tar
156156
identifier,
157157
render: targetColumn.render,
158158
header: targetColumn.header,
159-
field: targetColumn.header,
160159
type: "CustomRenderer",
161160
sortable: false,
162161
style: targetColumn.style,

packages/react/src/use-table/types.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,26 @@ export type TableColumn = {
2929
/** Identifier for the column */
3030
identifier: string;
3131
/** Human-readable header value for the column */
32-
header: string;
33-
/** Dot-separated path to the field in the record */
34-
field: string;
35-
type: ColumnType;
32+
header: ReactNode;
3633
/** parent relationship type if the parent field is a relationship */
3734
relationshipType?: RelationshipType;
3835
sortable: boolean;
3936
/** For controlling if the time is shown on DateTime cell renderers */
4037
includeTime?: boolean;
41-
/** Custom render function */
42-
render?: CustomCellRenderer;
4338
/** Custom style for the cells in the column */
4439
style?: React.CSSProperties;
45-
};
40+
} & (
41+
| {
42+
type: GadgetFieldType;
43+
/** Dot-separated path to the field in the record */
44+
field: string;
45+
}
46+
| {
47+
type: "CustomRenderer";
48+
/** Custom render function */
49+
render: CustomCellRenderer;
50+
}
51+
);
4652

4753
export type TableRow = Record<string, ColumnValueType | ReactNode>;
4854

@@ -149,15 +155,15 @@ export type RelatedFieldColumn = {
149155
};
150156

151157
export type CustomCellColumn = {
152-
header: string;
158+
header: ReactNode;
153159
render: CustomCellRenderer;
154160
style?: React.CSSProperties;
155161
};
156162

157163
export type CustomCellRenderer = (props: { record: GadgetRecord<any>; index: number }) => ReactNode;
158164

159165
export type CellDetailColumn = {
160-
header?: string;
166+
header?: ReactNode;
161167
field: string;
162168
sortable?: boolean;
163169
style?: React.CSSProperties;

0 commit comments

Comments
 (0)