diff --git a/.changeset/four-years-develop.md b/.changeset/four-years-develop.md
new file mode 100644
index 0000000000..cfd3704f2f
--- /dev/null
+++ b/.changeset/four-years-develop.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Allow for `cellStyle` property on `TableColumn` to be a function as well as `React.CSSProperties` as per the Material UI Table component
diff --git a/packages/core-components/src/components/Table/Table.stories.tsx b/packages/core-components/src/components/Table/Table.stories.tsx
index 7785764b22..b057d0a12c 100644
--- a/packages/core-components/src/components/Table/Table.stories.tsx
+++ b/packages/core-components/src/components/Table/Table.stories.tsx
@@ -326,3 +326,49 @@ export const FilterTable = () => {
);
};
+
+export const StyledTable = () => {
+ const classes = useStyles();
+ const columns: TableColumn[] = [
+ {
+ title: 'Column 1',
+ field: 'col1',
+ highlight: true,
+ cellStyle: (_, rowData: any & { tableData: { id: number } }) => {
+ return rowData.tableData.id % 2 === 0
+ ? {
+ color: '#6CD75F',
+ }
+ : {
+ color: '#DC3D5A',
+ };
+ },
+ },
+ {
+ title: 'Column 2',
+ field: 'col2',
+ cellStyle: { color: '#2FA5DC' },
+ },
+ {
+ title: 'Numeric value',
+ field: 'number',
+ type: 'numeric',
+ },
+ {
+ title: 'A Date',
+ field: 'date',
+ type: 'date',
+ },
+ ];
+
+ return (
+
+ );
+};
diff --git a/packages/core-components/src/components/Table/Table.test.tsx b/packages/core-components/src/components/Table/Table.test.tsx
index fb231fde31..12431dea59 100644
--- a/packages/core-components/src/components/Table/Table.test.tsx
+++ b/packages/core-components/src/components/Table/Table.test.tsx
@@ -18,17 +18,18 @@ import React from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { Table } from './Table';
+const column1 = {
+ title: 'Column 1',
+ field: 'col1',
+};
+
+const column2 = {
+ title: 'Column 2',
+ field: 'col2',
+};
+
const minProps = {
- columns: [
- {
- title: 'Column 1',
- field: 'col1',
- },
- {
- title: 'Column 2',
- field: 'col2',
- },
- ],
+ columns: [column1, column2],
data: [
{
col1: 'first value, first row',
@@ -47,6 +48,100 @@ describe('', () => {
expect(rendered.getByText('second value, second row')).toBeInTheDocument();
});
+ describe('with style rows', () => {
+ describe('with CSS Properties object', () => {
+ const styledColumn2 = {
+ ...column2,
+ cellStyle: {
+ color: 'blue',
+ },
+ };
+
+ it('renders non-highlighted correctly', async () => {
+ const columns = [column1, styledColumn2];
+
+ const rendered = await renderInTestApp(
+ ,
+ );
+ expect(rendered.getByText('second value, first row')).toHaveStyle({
+ color: 'blue',
+ });
+ });
+
+ it('renders highlighted column correctly', async () => {
+ const columns = [
+ column1,
+ {
+ ...styledColumn2,
+ highlight: true,
+ },
+ ];
+
+ const rendered = await renderInTestApp(
+ ,
+ );
+ expect(rendered.getByText('second value, first row')).toHaveStyle({
+ color: 'blue',
+ 'font-weight': 700,
+ });
+ });
+ });
+
+ describe('with CSS Properties function', () => {
+ const styledColumn2 = {
+ ...column2,
+ cellStyle: (
+ _data: any,
+ rowData: any & { tableData: { id: number } },
+ ) => {
+ return rowData.tableData.id % 2 === 0
+ ? {
+ color: 'green',
+ }
+ : {
+ color: 'red',
+ };
+ },
+ };
+
+ it('renders non-highlighted columns correctly', async () => {
+ const columns = [column1, styledColumn2];
+
+ const rendered = await renderInTestApp(
+ ,
+ );
+ expect(rendered.getByText('second value, first row')).toHaveStyle({
+ color: 'green',
+ });
+ expect(rendered.getByText('second value, second row')).toHaveStyle({
+ color: 'red',
+ });
+ });
+
+ it('renders highlighted columns correctly', async () => {
+ const columns = [
+ column1,
+ {
+ ...styledColumn2,
+ highlight: true,
+ },
+ ];
+
+ const rendered = await renderInTestApp(
+ ,
+ );
+ expect(rendered.getByText('second value, first row')).toHaveStyle({
+ color: 'green',
+ 'font-weight': 700,
+ });
+ expect(rendered.getByText('second value, second row')).toHaveStyle({
+ color: 'red',
+ 'font-weight': 700,
+ });
+ });
+ });
+ });
+
it('renders with subtitle', async () => {
const rendered = await renderInTestApp(
,
diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx
index f433e7cdc5..e90ed04871 100644
--- a/packages/core-components/src/components/Table/Table.tsx
+++ b/packages/core-components/src/components/Table/Table.tsx
@@ -169,12 +169,26 @@ function convertColumns(
): TableColumn[] {
return columns.map(column => {
const headerStyle: React.CSSProperties = {};
- const cellStyle: React.CSSProperties =
- typeof column.cellStyle === 'object' ? column.cellStyle : {};
+
+ let cellStyle = column.cellStyle || {};
if (column.highlight) {
headerStyle.color = theme.palette.textContrast;
- cellStyle.fontWeight = theme.typography.fontWeightBold;
+
+ if (typeof cellStyle === 'object') {
+ (cellStyle as React.CSSProperties).fontWeight =
+ theme.typography.fontWeightBold;
+ } else {
+ const cellStyleFn = cellStyle as (
+ data: any,
+ rowData: T,
+ column?: Column,
+ ) => React.CSSProperties;
+ cellStyle = (data, rowData, rowColumn) => {
+ const style = cellStyleFn(data, rowData, rowColumn);
+ return { ...style, fontWeight: theme.typography.fontWeightBold };
+ };
+ }
}
return {