Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGridPro] Keep bottom pinned row at the bottom #13313

Merged
merged 15 commits into from
Jul 9, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,14 @@ describe('<DataGridPremium /> - Clipboard', () => {
{ id: 2, brand: 'Puma' },
];
render(
<DataGridPremium
columns={columns}
rows={rows}
cellSelection
sortModel={[{ field: 'brand', sort: 'asc' }]}
/>,
<div style={{ width: 300, height: 300 }}>
<DataGridPremium
columns={columns}
rows={rows}
cellSelection
sortModel={[{ field: 'brand', sort: 'asc' }]}
/>
</div>,
);

const cell = getCell(0, 0);
Expand All @@ -143,15 +145,17 @@ describe('<DataGridPremium /> - Clipboard', () => {

it('should not escape double quotes when copying multiple cells to clipboard', () => {
render(
<DataGridPremium
columns={[{ field: 'value' }]}
rows={[
{ id: 0, value: '1 " 1' },
{ id: 1, value: '2' },
]}
cellSelection
disableRowSelectionOnClick
/>,
<div style={{ width: 300, height: 300 }}>
<DataGridPremium
columns={[{ field: 'value' }]}
rows={[
{ id: 0, value: '1 " 1' },
{ id: 1, value: '2' },
]}
cellSelection
disableRowSelectionOnClick
/>
</div>,
);

const cell = getCell(0, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ describe('<DataGridPro /> - Pagination', () => {

it('should log an error if rowCount is used with client-side pagination', () => {
expect(() => {
render(<DataGridPro rows={[]} columns={[]} paginationMode="client" rowCount={100} />);
render(
<div style={{ width: 300, height: 300 }}>
<DataGridPro rows={[]} columns={[]} paginationMode="client" rowCount={100} />
</div>,
);
}).toErrorDev([
'MUI X: Usage of the `rowCount` prop with client side pagination (`paginationMode="client"`) has no effect. `rowCount` is only meant to be used with `paginationMode="server"`.',
]);
Expand Down
3 changes: 2 additions & 1 deletion packages/x-data-grid/src/components/base/GridOverlays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ function GridOverlayWrapper(props: React.PropsWithChildren<GridOverlaysProps>) {

let height: React.CSSProperties['height'] =
dimensions.viewportOuterSize.height -
dimensions.headersTotalHeight -
dimensions.topContainerHeight -
dimensions.bottomContainerHeight -
(dimensions.hasScrollX ? dimensions.scrollbarSize : 0);

if ((rootProps.autoHeight && currentPage.rows.length === 0) || height === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) {
</RenderZone>
</Content>

{rows.length > 0 && <SpaceFiller />}
<SpaceFiller rowsLength={rows.length} />

<BottomContainer>
<rootProps.slots.pinnedRows position="bottom" virtualScroller={virtualScroller} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,29 @@ const Pinned = styled('div')({
position: 'sticky',
height: '100%',
boxSizing: 'border-box',
borderTop: '1px solid var(--DataGrid-rowBorderColor)',
borderTop: '1px solid var(--rowBorderColor)',
backgroundColor: 'var(--DataGrid-pinnedBackground)',
});
const PinnedLeft = styled(Pinned)({
left: 0,
borderRight: '1px solid var(--DataGrid-rowBorderColor)',
borderRight: '1px solid var(--rowBorderColor)',
});
const PinnedRight = styled(Pinned)({
right: 0,
borderLeft: '1px solid var(--DataGrid-rowBorderColor)',
borderLeft: '1px solid var(--rowBorderColor)',
});

const Main = styled('div')({
flexGrow: 1,
borderTop: '1px solid var(--DataGrid-rowBorderColor)',
borderTop: '1px solid var(--rowBorderColor)',
});

function GridVirtualScrollerFiller() {
type Props = {
/** The number of rows */
rowsLength: number;
};

function GridVirtualScrollerFiller({ rowsLength }: Props) {
const apiRef = useGridApiContext();
const {
viewportOuterSize,
Expand All @@ -54,7 +59,16 @@ function GridVirtualScrollerFiller() {
}

return (
<Filler className={gridClasses.filler} role="presentation" style={{ height }}>
<Filler
className={gridClasses.filler}
role="presentation"
style={
{
height,
'--rowBorderColor': rowsLength === 0 ? 'transparent' : 'var(--DataGrid-rowBorderColor)',
} as React.CSSProperties
}
>
{leftPinnedWidth > 0 && (
<PinnedLeft
className={gridClasses['filler--pinnedLeft']}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,22 +517,13 @@ export const useGridVirtualScroller = () => {
);

const contentSize = React.useMemo(() => {
// In cases where the columns exceed the available width,
// the horizontal scrollbar should be shown even when there're no rows.
// Keeping 1px as minimum height ensures that the scrollbar will visible if necessary.
const height = Math.max(contentHeight, 1);

Comment on lines -520 to -524
Copy link
Contributor Author

@romgrk romgrk Jun 19, 2024

Choose a reason for hiding this comment

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

I think this code was preventing this 0-height warning from running in some cases, so fixing it broke some tests all over the place that didn't have explicit dimensions on the grid container. I'll need to debug & update those tests before merging this PR. The test runner also doesn't seem to match the warning to which test it originated from precisely, so sometimes it marks one test as failed but the warning came from another test. As in if I run the test with .only it succeeds, but if I run the test suite as a whole it fails. Lots of fun ahead.

const size: React.CSSProperties = {
width: needsHorizontalScrollbar ? columnsTotalWidth : 'auto',
height,
height: contentHeight,
};

if (rootProps.autoHeight) {
if (currentPage.rows.length === 0) {
size.height = getMinimalContentHeight(apiRef); // Give room to show the overlay when there no rows.
} else {
size.height = contentHeight;
}
if (rootProps.autoHeight && currentPage.rows.length === 0) {
size.height = getMinimalContentHeight(apiRef); // Give room to show the overlay when there no rows.
}

return size;
Expand Down
28 changes: 15 additions & 13 deletions packages/x-data-grid/src/tests/DataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,21 @@ describe('<DataGrid />', () => {
];
expect(() => {
render(
<DataGrid
{...(
Object.keys(DATA_GRID_PROPS_DEFAULT_VALUES) as Array<
keyof typeof DATA_GRID_PROPS_DEFAULT_VALUES
>
).reduce((acc, key) => {
// @ts-ignore
acc[key] = undefined;
return acc;
}, {})}
rows={rows}
columns={columns}
/>,
<div style={{ height: 300, width: 300 }}>
<DataGrid
{...(
Object.keys(DATA_GRID_PROPS_DEFAULT_VALUES) as Array<
keyof typeof DATA_GRID_PROPS_DEFAULT_VALUES
>
).reduce((acc, key) => {
// @ts-ignore
acc[key] = undefined;
return acc;
}, {})}
rows={rows}
columns={columns}
/>
</div>,
);
}).not.toErrorDev();
});
Expand Down
4 changes: 2 additions & 2 deletions packages/x-data-grid/src/tests/layout.DataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,7 @@ describe('<DataGrid /> - Layout & warnings', () => {
}

render(
<div style={{ height: '100%', width: 400.6 }}>
<div style={{ height: 300, width: 400.6 }}>
<DataGrid rows={[{ id: 1 }]} columns={[{ field: 'id', flex: 1 }]} />
</div>,
);
Expand Down Expand Up @@ -1213,7 +1213,7 @@ describe('<DataGrid /> - Layout & warnings', () => {
}

render(
<div style={{ height: 'auto', width: 1584 }}>
<div style={{ height: 300, width: 1584 }}>
<DataGrid
rows={[{ id: 1 }]}
columns={[
Expand Down
14 changes: 8 additions & 6 deletions packages/x-data-grid/src/tests/pagination.DataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -730,12 +730,14 @@ describe('<DataGrid /> - Pagination', () => {
];
expect(() => {
const { setProps } = render(
<DataGrid
columns={columns}
rows={rows}
initialState={{ pagination: { paginationModel: { pageSize: 2, page: 1 } } }}
pageSizeOptions={[2]}
/>,
<div style={{ width: 300, height: 300 }}>
<DataGrid
columns={columns}
rows={rows}
initialState={{ pagination: { paginationModel: { pageSize: 2, page: 1 } } }}
pageSizeOptions={[2]}
/>
</div>,
);
setProps({ rows: rows.slice(0, 2) });
}).not.to.throw();
Expand Down
2 changes: 1 addition & 1 deletion test/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const webpack = require('webpack');

const CI = Boolean(process.env.CI);

process.env.CHROME_BIN = chromium.executablePath();
process.env.CHROME_BIN ||= chromium.executablePath();

// Karma configuration
module.exports = function setKarmaConfig(config) {
Expand Down
44 changes: 44 additions & 0 deletions test/regressions/data-grid/DataGridPinnedBottomRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as React from 'react';
import { DataGridPro } from '@mui/x-data-grid-pro';
import {
randomCity,
randomEmail,
randomId,
randomInt,
randomTraderName,
randomUserName,
} from '@mui/x-data-grid-generator';

const columns = [
{ field: 'name', headerName: 'Name', width: 150 },
{ field: 'city', headerName: 'City', width: 150 },
{ field: 'username', headerName: 'Username' },
{ field: 'email', headerName: 'Email', width: 200 },
{ field: 'age', type: 'number', headerName: 'Age' },
];

const rows = [];

function getRow() {
return {
id: randomId(),
name: randomTraderName(),
city: randomCity(),
username: randomUserName(),
email: randomEmail(),
age: randomInt(10, 80),
};
}

const pinnedRows = {
top: [getRow()],
bottom: [getRow()],
};

export default function RowPinning() {
return (
<div style={{ height: 500, width: '100%' }}>
<DataGridPro columns={columns} rows={rows} pinnedRows={pinnedRows} />
</div>
);
}