diff --git a/docs/data/data-grid/column-groups/BasicGroupingDemo.js b/docs/data/data-grid/column-groups/BasicGroupingDemo.js index 8c19a4ed80382..5d44b45aea362 100644 --- a/docs/data/data-grid/column-groups/BasicGroupingDemo.js +++ b/docs/data/data-grid/column-groups/BasicGroupingDemo.js @@ -58,19 +58,6 @@ export default function BasicGroupingDemo() { return (
\ No newline at end of file diff --git a/docs/data/data-grid/column-groups/BreakingGroupDemo.js b/docs/data/data-grid/column-groups/BreakingGroupDemo.js index 5e15a81562720..ebb00387cb99e 100644 --- a/docs/data/data-grid/column-groups/BreakingGroupDemo.js +++ b/docs/data/data-grid/column-groups/BreakingGroupDemo.js @@ -63,19 +63,6 @@ export default function BreakingGroupDemo() { return (
\ No newline at end of file diff --git a/docs/data/data-grid/column-groups/CustomizationDemo.js b/docs/data/data-grid/column-groups/CustomizationDemo.js index 60db52dc072dd..77e75c11d710c 100644 --- a/docs/data/data-grid/column-groups/CustomizationDemo.js +++ b/docs/data/data-grid/column-groups/CustomizationDemo.js @@ -62,19 +62,6 @@ export default function CustomizationDemo() { return (
\ No newline at end of file diff --git a/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts b/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts index 8a8379b107abb..594724b930201 100644 --- a/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts +++ b/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts @@ -77,7 +77,7 @@ export const DATA_GRID_PROPS_DEFAULT_VALUES: DataGridPropsWithDefaultValues = { disableColumnReorder: false, disableColumnResize: false, keepNonExistentRowsSelected: false, - headerGroupingRowHeight: 32, + headerGroupingRowHeight: 56, }; export const useDataGridProps = (inProps: DataGridProps) => { diff --git a/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnGroupHeader.tsx b/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnGroupHeader.tsx index 2d13e4b2313e1..d00e8a50b3261 100644 --- a/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnGroupHeader.tsx +++ b/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnGroupHeader.tsx @@ -13,10 +13,16 @@ interface GridColumnGroupHeaderProps { width: number; fields: string[]; colIndex: number; // TODO: use this prop to get accessible column group + isLastColumn: boolean; + extendRowFullWidth: boolean; + depth: number; + maxDepth: number; } type OwnerState = GridColumnGroupHeaderProps & { showRightBorder: boolean; + depth: number; + maxDepth: number; classes?: DataGridProcessedProps['classes']; }; @@ -37,21 +43,49 @@ const useUtilityClasses = (ownerState: OwnerState) => { }; function GridColumnGroupHeader(props: GridColumnGroupHeaderProps) { - const { groupId, width, fields, colIndex } = props; + const { groupId, width, depth, maxDepth, fields, colIndex, isLastColumn, extendRowFullWidth } = + props; const rootProps = useGridRootProps(); const apiRef = useGridApiContext(); const columnGroupsLookup = useGridSelector(apiRef, gridColumnGroupsLookupSelector); + const { hasScrollX, hasScrollY } = apiRef.current.getRootDimensions() ?? { + hasScrollX: false, + hasScrollY: false, + }; + + const { headerName = groupId ?? '', description = '' } = groupId + ? columnGroupsLookup[groupId] + : {}; - const { headerName = groupId, description = '' } = groupId ? columnGroupsLookup[groupId] : {}; + let headerComponent: React.ReactNode = null; + + const render = groupId && columnGroupsLookup[groupId]?.renderHeaderGroup; + if (groupId && render) { + headerComponent = render({ + headerName, + description, + depth, + maxDepth, + fields, + colIndex, + isLastColumn, + }); + } const headerCellRef = React.useRef(null); + const removeLastBorderRight = isLastColumn && hasScrollX && !hasScrollY; + const showRightBorder = !isLastColumn + ? rootProps.showColumnRightBorder + : !removeLastBorderRight && !extendRowFullWidth; + const ownerState = { ...props, classes: rootProps.classes, - showRightBorder: false, + showRightBorder, + depth, }; const classes = useUtilityClasses(ownerState); @@ -72,11 +106,13 @@ function GridColumnGroupHeader(props: GridColumnGroupHeaderProps) { >
- + {headerComponent || ( + + )}
diff --git a/packages/grid/x-data-grid/src/components/containers/GridRootStyles.ts b/packages/grid/x-data-grid/src/components/containers/GridRootStyles.ts index eda99b4732e40..e557da7654dd2 100644 --- a/packages/grid/x-data-grid/src/components/containers/GridRootStyles.ts +++ b/packages/grid/x-data-grid/src/components/containers/GridRootStyles.ts @@ -1,4 +1,4 @@ -import { CSSInterpolation } from '@mui/system'; +import { borderBottom, CSSInterpolation } from '@mui/system'; import { darken, lighten, alpha, styled } from '@mui/material/styles'; import { gridClasses } from '../../constants/gridClasses'; @@ -139,6 +139,15 @@ export const GridRootStyles = styled('div', { display: 'flex', alignItems: 'center', }, + [`& .${gridClasses.columnGroupHeaderTitleContainerContent}`]: { + borderBottom: `solid ${theme.palette.divider} 2px`, + }, + [`& .${gridClasses.withBorder} .${gridClasses.columnGroupHeaderTitleContainerContent}`]: { + borderBottom: `none`, + }, + [`& .${gridClasses.withBorder}.${gridClasses.columnGroupHeader}`]: { + borderBottom: `solid ${borderColor} 1px`, + }, [`& .${gridClasses.sortIcon}, & .${gridClasses.filterIcon}`]: { fontSize: 'inherit', }, diff --git a/packages/grid/x-data-grid/src/constants/gridClasses.ts b/packages/grid/x-data-grid/src/constants/gridClasses.ts index e89a6268747bd..7eedf2d93f622 100644 --- a/packages/grid/x-data-grid/src/constants/gridClasses.ts +++ b/packages/grid/x-data-grid/src/constants/gridClasses.ts @@ -125,6 +125,10 @@ export interface GridClasses { * Styles applied to the column header's title excepted buttons. */ columnHeaderTitleContainerContent: string; + /** + * Styles applied to the column group header's title excepted buttons. + */ + columnGroupHeaderTitleContainerContent: string; /** * Styles applied to the column headers. */ @@ -458,13 +462,14 @@ export const gridClasses = generateUtilityClasses('MuiDataGrid', [ 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader', - 'columnGroupHeader', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderDropZone', 'columnHeaderTitle', 'columnHeaderTitleContainer', + 'columnGroupHeader', 'columnHeaderTitleContainerContent', + 'columnGroupHeaderTitleContainerContent', 'columnHeaders', 'columnHeadersInner', 'columnHeadersInner--scrollable', diff --git a/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 288ae1141aca9..ef885e4fc147b 100644 --- a/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -475,6 +475,10 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { width={width} fields={fields} colIndex={colIndex} + depth={depthIndex} + isLastColumn={colIndex === visibleColumns.length - fields.length} + extendRowFullWidth={!rootProps.disableExtendRowFullWidth} + maxDepth={headerToRender.length} /> ); })} diff --git a/packages/grid/x-data-grid/src/models/gridColumnGrouping.ts b/packages/grid/x-data-grid/src/models/gridColumnGrouping.ts index 2b5696080100e..6d947f2271e79 100644 --- a/packages/grid/x-data-grid/src/models/gridColumnGrouping.ts +++ b/packages/grid/x-data-grid/src/models/gridColumnGrouping.ts @@ -10,6 +10,16 @@ export function isLeaf(node: GridColumnNode): node is LeafColumn { return (node).field !== undefined; } +type ColumnGroupHeaderParams = { + headerName: string; + description: string; + depth: number; + maxDepth: number; + fields: string[]; + colIndex: number; + isLastColumn: boolean; +}; + export type GridColumnGroup = { /** * A unique string identifying the group @@ -32,6 +42,12 @@ export type GridColumnGroup = { * @default false */ freeReordering?: boolean; + /** + * Allows to render a component in the column group header cell. + * @param {ColumnGroupHeaderParams} params Object containing parameters for the renderer. + * @returns {React.ReactNode} The element to be rendered. + */ + renderHeaderGroup?: (params: ColumnGroupHeaderParams) => React.ReactNode; }; export type GridColumnGroupingModel = GridColumnGroup[];