-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
[DataGrid] Fix resizing right pinned column #15107
Changes from all commits
182191f
30c1e6e
4fec408
028b3d3
e8befe2
1f552a5
934afe5
bd9f8e0
5901e7d
a19328a
1da2274
c5dcb25
84ecae7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,28 +67,6 @@ export interface GridRowProps extends React.HTMLAttributes<HTMLDivElement> { | |
[x: string]: any; // Allow custom attributes like data-* and aria-* | ||
} | ||
|
||
function EmptyCell({ width }: { width: number }) { | ||
if (!width) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div | ||
role="presentation" | ||
className={clsx(gridClasses.cell, gridClasses.cellEmpty)} | ||
style={{ '--width': `${width}px` } as React.CSSProperties} | ||
/> | ||
); | ||
} | ||
|
||
EmptyCell.propTypes = { | ||
// ----------------------------- Warning -------------------------------- | ||
// | These PropTypes are generated from the TypeScript type definitions | | ||
// | To update them edit the TypeScript types and run "pnpm proptypes" | | ||
// ---------------------------------------------------------------------- | ||
width: PropTypes.number.isRequired, | ||
} as any; | ||
|
||
const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(props, refProp) { | ||
const { | ||
selected, | ||
|
@@ -454,10 +432,6 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow( | |
} | ||
: null; | ||
|
||
const expandedWidth = | ||
dimensions.viewportOuterSize.width - dimensions.columnsTotalWidth - scrollbarWidth; | ||
const emptyCellWidth = Math.max(0, expandedWidth); | ||
|
||
return ( | ||
<div | ||
ref={handleRef} | ||
|
@@ -477,8 +451,7 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow( | |
style={{ width: offsetLeft }} | ||
/> | ||
{cells} | ||
{emptyCellWidth > 0 && <EmptyCell width={emptyCellWidth} />} | ||
{rightCells.length > 0 && <div role="presentation" className={gridClasses.filler} />} | ||
<div role="presentation" className={clsx(gridClasses.cell, gridClasses.cellEmpty)} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rendering the empty cell all the time improves resizing of the right-pinned cells Before before.movAfter after.movThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally the actions column would also move with the right pinned column... |
||
{rightCells} | ||
{scrollbarWidth !== 0 && <ScrollbarFiller pinnedRight={pinnedColumns.right.length > 0} />} | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -567,6 +567,7 @@ export const GridRootStyles = styled('div', { | |
lineHeight: 'inherit', | ||
}, | ||
[`& .${c.cellEmpty}`]: { | ||
flex: 1, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This way the empty cell always takes up the right amount of space in a row. Shrinks when the row is full of cells, grows when there aren't enough to fill a row. |
||
padding: 0, | ||
height: 'unset', | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -300,12 +300,14 @@ export const useGridColumnResize = ( | |
const prevWidth = refs.columnHeaderElement!.offsetWidth; | ||
const widthDiff = newWidth - prevWidth; | ||
const columnWidthDiff = newWidth - refs.initialColWidth; | ||
const newTotalWidth = refs.initialTotalWidth + columnWidthDiff; | ||
|
||
apiRef.current.rootElementRef?.current?.style.setProperty( | ||
'--DataGrid-rowWidth', | ||
`${newTotalWidth}px`, | ||
); | ||
if (columnWidthDiff > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before before.movAfter after.mov |
||
const newTotalWidth = refs.initialTotalWidth + columnWidthDiff; | ||
apiRef.current.rootElementRef?.current?.style.setProperty( | ||
'--DataGrid-rowWidth', | ||
`${newTotalWidth}px`, | ||
); | ||
} | ||
|
||
refs.colDef!.computedWidth = newWidth; | ||
refs.colDef!.width = newWidth; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import * as React from 'react'; | ||
import { DataGridPro } from '@mui/x-data-grid-pro'; | ||
import { randomTraderName, randomEmail } from '@mui/x-data-grid-generator'; | ||
|
||
const columns = [ | ||
{ field: 'name', headerName: 'Name', width: 160 }, | ||
{ field: 'email', headerName: 'Email', width: 200 }, | ||
{ field: 'age', headerName: 'Age', type: 'number' }, | ||
]; | ||
|
||
const rows = [ | ||
{ | ||
id: 1, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 25, | ||
}, | ||
]; | ||
|
||
export default function DataGridBordered() { | ||
return ( | ||
<div style={{ height: 400, width: '100%' }}> | ||
<DataGridPro rows={rows} columns={columns} showCellVerticalBorder showColumnVerticalBorder /> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import * as React from 'react'; | ||
import { DataGridPro } from '@mui/x-data-grid-pro'; | ||
import { randomTraderName, randomEmail } from '@mui/x-data-grid-generator'; | ||
|
||
const columns = [ | ||
{ field: 'name', headerName: 'Name', width: 160 }, | ||
{ field: 'email', headerName: 'Email', width: 200 }, | ||
{ field: 'age', headerName: 'Age', type: 'number' }, | ||
]; | ||
|
||
const rows = [ | ||
{ | ||
id: 1, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 25, | ||
}, | ||
]; | ||
|
||
export default function DataGridPinnedColumnsBordered() { | ||
return ( | ||
<div style={{ height: 400, width: '100%' }}> | ||
<DataGridPro | ||
rows={rows} | ||
columns={columns} | ||
initialState={{ pinnedColumns: { left: ['name'], right: ['age'] } }} | ||
showCellVerticalBorder | ||
showColumnVerticalBorder | ||
/> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import * as React from 'react'; | ||
import DeleteIcon from '@mui/icons-material/Delete'; | ||
import EditIcon from '@mui/icons-material/Edit'; | ||
import { DataGridPro, GridActionsCellItem } from '@mui/x-data-grid-pro'; | ||
import { | ||
randomCreatedDate, | ||
randomTraderName, | ||
randomEmail, | ||
randomUpdatedDate, | ||
} from '@mui/x-data-grid-generator'; | ||
|
||
const columns = [ | ||
{ field: 'name', headerName: 'Name', width: 160, editable: true }, | ||
{ field: 'email', headerName: 'Email', width: 200, editable: true }, | ||
{ field: 'age', headerName: 'Age', type: 'number', editable: true }, | ||
{ | ||
field: 'dateCreated', | ||
headerName: 'Date Created', | ||
type: 'date', | ||
width: 180, | ||
editable: true, | ||
}, | ||
{ | ||
field: 'lastLogin', | ||
headerName: 'Last Login', | ||
type: 'dateTime', | ||
width: 220, | ||
editable: true, | ||
}, | ||
{ | ||
field: 'actions', | ||
type: 'actions', | ||
width: 100, | ||
getActions: () => [ | ||
<GridActionsCellItem icon={<EditIcon />} label="Edit" />, | ||
<GridActionsCellItem icon={<DeleteIcon />} label="Delete" />, | ||
], | ||
}, | ||
]; | ||
|
||
const rows = [ | ||
{ | ||
id: 1, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 25, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 2, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 32, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 3, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 45, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 4, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 28, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 5, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 39, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 6, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 52, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 7, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 33, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 8, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 41, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 9, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 36, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
{ | ||
id: 10, | ||
name: randomTraderName(), | ||
email: randomEmail(), | ||
age: 29, | ||
dateCreated: randomCreatedDate(), | ||
lastLogin: randomUpdatedDate(), | ||
}, | ||
]; | ||
|
||
export default function DataGridPinnedColumnsScrollbars() { | ||
return ( | ||
<div style={{ height: 400, width: '100%' }}> | ||
<DataGridPro | ||
rows={rows} | ||
columns={columns} | ||
initialState={{ pinnedColumns: { left: ['name'], right: ['actions'] } }} | ||
/> | ||
</div> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why we need this + the empty cell. Perhaps I'm missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't remember :| You should build a test case with all the variations of:
And then check if all the cases behave correctly. Make sure to enable vertical borders on all cells, we need to make sure that borders are where they're supposed to be (by default the grid only has vertical border on pinned sections).
We should probably create a visual regression test based on that.