Merge pull request #7921 from egnwd/core-table-cellStyle-fn
[core-components] Allow for material-table cellStyle function from the backstage Table component
This commit is contained in:
@@ -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
|
||||
@@ -326,3 +326,49 @@ export const FilterTable = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<div className={classes.container}>
|
||||
<Table
|
||||
options={{ paging: false }}
|
||||
data={testData10}
|
||||
columns={columns}
|
||||
title="Backstage Table"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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('<Table />', () => {
|
||||
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(
|
||||
<Table data={minProps.data} columns={columns} />,
|
||||
);
|
||||
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(
|
||||
<Table data={minProps.data} columns={columns} />,
|
||||
);
|
||||
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(
|
||||
<Table data={minProps.data} columns={columns} />,
|
||||
);
|
||||
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(
|
||||
<Table data={minProps.data} columns={columns} />,
|
||||
);
|
||||
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(
|
||||
<Table subtitle="subtitle" {...minProps} />,
|
||||
|
||||
@@ -169,12 +169,26 @@ function convertColumns<T extends object>(
|
||||
): TableColumn<T>[] {
|
||||
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<T>,
|
||||
) => React.CSSProperties;
|
||||
cellStyle = (data, rowData, rowColumn) => {
|
||||
const style = cellStyleFn(data, rowData, rowColumn);
|
||||
return { ...style, fontWeight: theme.typography.fontWeightBold };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user