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[];