diff --git a/docs/src/pages/components/data-grid/rendering/AntDesignGrid.js b/docs/src/pages/components/data-grid/rendering/AntDesignGrid.js
new file mode 100644
index 0000000000000..74d7225697705
--- /dev/null
+++ b/docs/src/pages/components/data-grid/rendering/AntDesignGrid.js
@@ -0,0 +1,17 @@
+import * as React from 'react';
+import { DataGrid } from '@material-ui/data-grid';
+import { useDemoData } from '@material-ui/x-grid-data-generator';
+
+export default function AntDesignGrid() {
+ const { data } = useDemoData({
+ dataSet: 'Commodity',
+ rowLength: 1000,
+ maxColumns: 6,
+ });
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/src/pages/components/data-grid/rendering/AntDesignGrid.tsx b/docs/src/pages/components/data-grid/rendering/AntDesignGrid.tsx
new file mode 100644
index 0000000000000..3fcd144a11100
--- /dev/null
+++ b/docs/src/pages/components/data-grid/rendering/AntDesignGrid.tsx
@@ -0,0 +1,130 @@
+import * as React from 'react';
+import { DataGrid, ComponentProps } from '@material-ui/data-grid';
+import { useDemoData } from '@material-ui/x-grid-data-generator';
+import { createStyles, Theme, makeStyles } from '@material-ui/core/styles';
+import Pagination from '@material-ui/lab/Pagination';
+import PaginationItem from '@material-ui/lab/PaginationItem';
+
+function customCheckbox(theme) {
+ return {
+ '& .MuiCheckbox-root svg': {
+ width: 16,
+ height: 16,
+ backgroundColor: 'transparent',
+ border: `1px solid ${theme.palette.type === 'light' ? '#d9d9d9' : 'rgb(67, 67, 67)'}`,
+ borderRadius: 2,
+ },
+ '& .MuiCheckbox-root svg path': {
+ display: 'none',
+ },
+ '& .MuiCheckbox-root.Mui-checked:not(.MuiCheckbox-indeterminate) svg': {
+ backgroundColor: '#1890ff',
+ borderColor: '#1890ff',
+ },
+ '& .MuiCheckbox-root.Mui-checked .MuiIconButton-label:after': {
+ position: 'absolute',
+ display: 'table',
+ border: '2px solid #fff',
+ borderTop: 0,
+ borderLeft: 0,
+ transform: 'rotate(45deg) translate(-50%,-50%)',
+ opacity: 1,
+ transition: 'all .2s cubic-bezier(.12,.4,.29,1.46) .1s',
+ content: '""',
+ top: '50%',
+ left: '39%',
+ width: 5.71428571,
+ height: 9.14285714,
+ },
+ '& .MuiCheckbox-root.MuiCheckbox-indeterminate .MuiIconButton-label:after': {
+ width: 8,
+ height: 8,
+ backgroundColor: '#1890ff',
+ transform: 'none',
+ top: '39%',
+ border: 0,
+ },
+ }
+}
+
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ root: {
+ border: 0,
+ color: theme.palette.type === 'light' ? 'rgba(0,0,0,.85)' : 'rgba(255,255,255,0.85)',
+ fontFamily: [
+ '-apple-system',
+ 'BlinkMacSystemFont',
+ '"Segoe UI"',
+ 'Roboto',
+ '"Helvetica Neue"',
+ 'Arial',
+ 'sans-serif',
+ '"Apple Color Emoji"',
+ '"Segoe UI Emoji"',
+ '"Segoe UI Symbol"',
+ ].join(','),
+ WebkitFontSmoothing: 'auto',
+ letterSpacing: 'normal',
+ '& .MuiDataGrid-columnsContainer': {
+ backgroundColor: theme.palette.type === 'light' ? '#fafafa' : '#1d1d1d',
+ },
+ '& .MuiDataGrid-iconSeparator': {
+ display: 'none',
+ },
+ '& .MuiDataGrid-colCell, .MuiDataGrid-cell': {
+ borderRight: `1px solid ${theme.palette.type === 'light' ? '#f0f0f0' : '#303030'}`,
+ },
+ '& .MuiDataGrid-columnsContainer, .MuiDataGrid-cell': {
+ borderBottom: `1px solid ${theme.palette.type === 'light' ? '#f0f0f0' : '#303030'}`,
+ },
+ '& .MuiDataGrid-cell': {
+ color: theme.palette.type === 'light' ? 'rgba(0,0,0,.85)' : 'rgba(255,255,255,0.65)',
+ },
+ '& .MuiPaginationItem-root': {
+ borderRadius: 0,
+ },
+ ...customCheckbox(theme),
+ },
+ }),
+);
+
+function CustomPagination(props: ComponentProps) {
+ const { paginationProps } = props;
+
+ return (
+ }
+ onChange={(event, value) => paginationProps.setPage(value)}
+ />
+ );
+}
+
+export default function AntDesignGrid() {
+ const { data } = useDemoData({
+ dataSet: 'Commodity',
+ rowLength: 10,
+ maxColumns: 10,
+ });
+ const classes = useStyles();
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/src/pages/components/data-grid/rendering/CustomEmptyOverlayGrid.js b/docs/src/pages/components/data-grid/rendering/CustomEmptyOverlayGrid.js
new file mode 100644
index 0000000000000..f0f6f19785299
--- /dev/null
+++ b/docs/src/pages/components/data-grid/rendering/CustomEmptyOverlayGrid.js
@@ -0,0 +1,101 @@
+import * as React from 'react';
+import { GridOverlay, DataGrid } from '@material-ui/data-grid';
+import { useDemoData } from '@material-ui/x-grid-data-generator';
+import { createStyles, makeStyles } from '@material-ui//core/styles';
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ '& .MuiDataGrid-overlayContent': {
+ flexDirection: 'column',
+ alignItems: 'center',
+ },
+ '& .ant-empty-img-1': {
+ fill: theme.palette.type === 'light' ? '#aeb8c2' : '#262626',
+ },
+ '& .ant-empty-img-2': {
+ fill: theme.palette.type === 'light' ? '#f5f5f7' : '#595959',
+ },
+ '& .ant-empty-img-3': {
+ fill: theme.palette.type === 'light' ? '#dce0e6' : '#434343',
+ },
+ '& .ant-empty-img-4': {
+ fill: theme.palette.type === 'light' ? '#fff' : '#1c1c1c',
+ },
+ '& .ant-empty-img-5': {
+ fillOpacity: theme.palette.type === 'light' ? '0.8' : '0.08',
+ fill: theme.palette.type === 'light' ? '#f5f5f5' : '#fff',
+ },
+ },
+ label: {
+ marginTop: theme.spacing(1),
+ },
+}));
+
+function CustomNoRowsOverlay() {
+ const classes = useStyles();
+
+ return (
+
+
+ No Rows
+
+ );
+}
+
+export default function CustomEmptyOverlayGrid() {
+ const { data } = useDemoData({
+ dataSet: 'Commodity',
+ rowLength: 100,
+ maxColumns: 6,
+ });
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/src/pages/components/data-grid/rendering/CustomEmptyOverlayGrid.tsx b/docs/src/pages/components/data-grid/rendering/CustomEmptyOverlayGrid.tsx
new file mode 100644
index 0000000000000..72084914a1bad
--- /dev/null
+++ b/docs/src/pages/components/data-grid/rendering/CustomEmptyOverlayGrid.tsx
@@ -0,0 +1,103 @@
+import * as React from 'react';
+import { GridOverlay, DataGrid } from '@material-ui/data-grid';
+import { useDemoData } from '@material-ui/x-grid-data-generator';
+import { createStyles, Theme, makeStyles } from '@material-ui//core/styles';
+
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ root: {
+ '& .MuiDataGrid-overlayContent': {
+ flexDirection: 'column',
+ alignItems: 'center',
+ },
+ '& .ant-empty-img-1': {
+ fill: theme.palette.type === 'light' ? '#aeb8c2' : '#262626',
+ },
+ '& .ant-empty-img-2': {
+ fill: theme.palette.type === 'light' ? '#f5f5f7' : '#595959',
+ },
+ '& .ant-empty-img-3': {
+ fill: theme.palette.type === 'light' ? '#dce0e6' : '#434343',
+ },
+ '& .ant-empty-img-4': {
+ fill: theme.palette.type === 'light' ? '#fff' : '#1c1c1c',
+ },
+ '& .ant-empty-img-5': {
+ fillOpacity: theme.palette.type === 'light' ? '0.8' : '0.08',
+ fill: theme.palette.type === 'light' ? '#f5f5f5' : '#fff',
+ },
+ },
+ label: {
+ marginTop: theme.spacing(1),
+ },
+ }),
+);
+
+function CustomNoRowsOverlay() {
+ const classes = useStyles();
+
+ return (
+
+
+ No Rows
+
+ );
+}
+
+export default function CustomEmptyOverlayGrid() {
+ const { data } = useDemoData({
+ dataSet: 'Commodity',
+ rowLength: 100,
+ maxColumns: 6,
+ });
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/src/pages/components/data-grid/rendering/CustomLoadingOverlayGrid.js b/docs/src/pages/components/data-grid/rendering/CustomLoadingOverlayGrid.js
new file mode 100644
index 0000000000000..ed00919d66b68
--- /dev/null
+++ b/docs/src/pages/components/data-grid/rendering/CustomLoadingOverlayGrid.js
@@ -0,0 +1,34 @@
+import * as React from 'react';
+import { GridOverlay, DataGrid } from '@material-ui/data-grid';
+import LinearProgress from '@material-ui/core/LinearProgress';
+import { useDemoData } from '@material-ui/x-grid-data-generator';
+
+function CustomLoadingOverlay() {
+ return (
+
+
+
+
+
+ );
+}
+
+export default function CustomLoadingOverlayGrid() {
+ const { data } = useDemoData({
+ dataSet: 'Commodity',
+ rowLength: 100,
+ maxColumns: 6,
+ });
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/src/pages/components/data-grid/rendering/CustomLoadingOverlayGrid.tsx b/docs/src/pages/components/data-grid/rendering/CustomLoadingOverlayGrid.tsx
new file mode 100644
index 0000000000000..ed00919d66b68
--- /dev/null
+++ b/docs/src/pages/components/data-grid/rendering/CustomLoadingOverlayGrid.tsx
@@ -0,0 +1,34 @@
+import * as React from 'react';
+import { GridOverlay, DataGrid } from '@material-ui/data-grid';
+import LinearProgress from '@material-ui/core/LinearProgress';
+import { useDemoData } from '@material-ui/x-grid-data-generator';
+
+function CustomLoadingOverlay() {
+ return (
+
+
+
+
+
+ );
+}
+
+export default function CustomLoadingOverlayGrid() {
+ const { data } = useDemoData({
+ dataSet: 'Commodity',
+ rowLength: 100,
+ maxColumns: 6,
+ });
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/src/pages/components/data-grid/rendering/CustomPaginationGrid.tsx b/docs/src/pages/components/data-grid/rendering/CustomPaginationGrid.tsx
index 714f377385571..bb88afba291ba 100644
--- a/docs/src/pages/components/data-grid/rendering/CustomPaginationGrid.tsx
+++ b/docs/src/pages/components/data-grid/rendering/CustomPaginationGrid.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import { makeStyles } from '@material-ui/core/styles';
-import { DataGrid } from '@material-ui/data-grid';
+import { DataGrid, ComponentProps } from '@material-ui/data-grid';
import { useDemoData } from '@material-ui/x-grid-data-generator';
import Pagination from '@material-ui/lab/Pagination';
@@ -10,15 +10,7 @@ const useStyles = makeStyles({
},
});
-interface CustomPaginationProps {
- paginationProps: {
- page: number;
- pageCount: number;
- setPage: (newPage: number) => void;
- };
-}
-
-function CustomPagination(props: CustomPaginationProps) {
+function CustomPagination(props: ComponentProps) {
const { paginationProps } = props;
const classes = useStyles();
diff --git a/docs/src/pages/components/data-grid/rendering/rendering.md b/docs/src/pages/components/data-grid/rendering/rendering.md
index 4d3861314a978..ac9e84e0043f4 100644
--- a/docs/src/pages/components/data-grid/rendering/rendering.md
+++ b/docs/src/pages/components/data-grid/rendering/rendering.md
@@ -222,7 +222,7 @@ By default, 2 columns are rendered outside of the viewport. You can change this
You can disable column virtualization by setting the column buffer to a higher number than the number of rendered columns, e.g. with `columnBuffer={columns.length}` or `columnBuffer={Number.MAX_SAFE_INTEGER}`.
-## Components
+## Components prop
As part of the customization API, the grid allows you to replace and override the following components:
@@ -232,12 +232,28 @@ As part of the customization API, the grid allows you to replace and override th
- `footer`: The component rendered below the viewport.
- `pagination`: The component rendered for the pagination feature.
+### Loading overlay
+
+By default, the loading overlay displays a circular progress.
+This demo replaces it with a linear progress.
+
+{{"demo": "pages/components/data-grid/rendering/CustomLoadingOverlayGrid.js"}}
+
+### No rows overlay
+
+In the following demo, an illustaration is added on top of the default "No Rows" message.
+
+{{"demo": "pages/components/data-grid/rendering/CustomEmptyOverlayGrid.js"}}
+
### Pagination
-By default, pagination uses the [TablePagination](/components/pagination/#table-pagination) component that is optimized for handling tabular data. This demo replaces it with the [Pagination](/components/pagination/) component.
+By default, pagination uses the [TablePagination](/components/pagination/#table-pagination) component that is optimized for handling tabular data.
+This demo replaces it with the [Pagination](/components/pagination/) component.
{{"demo": "pages/components/data-grid/rendering/CustomPaginationGrid.js"}}
## Customization example
-The following grid leverages the Ant Design specification.
+The following grid leverages the CSS customization API to match the Ant Design specification.
+
+{{"demo": "pages/components/data-grid/rendering/AntDesignGrid.js"}}
diff --git a/packages/grid/x-grid-modules/src/components/styled-wrappers/GridRootStyles.ts b/packages/grid/x-grid-modules/src/components/styled-wrappers/GridRootStyles.ts
index b128abcf1d90b..c3cfde8e1fa10 100644
--- a/packages/grid/x-grid-modules/src/components/styled-wrappers/GridRootStyles.ts
+++ b/packages/grid/x-grid-modules/src/components/styled-wrappers/GridRootStyles.ts
@@ -14,6 +14,8 @@ export const useStyles = makeStyles(
position: 'relative',
border: `1px solid ${borderColor}`,
borderRadius: theme.shape.borderRadius,
+ color: theme.palette.text.primary,
+ ...theme.typography.body2,
outline: 'none',
display: 'flex',
flexDirection: 'column',
@@ -32,10 +34,14 @@ export const useStyles = makeStyles(
top: 0,
left: 0,
right: 0,
- bottom: 15,
+ bottom: 0,
alignSelf: 'center',
alignItems: 'center',
zIndex: 10,
+ backgroundColor: fade(
+ theme.palette.background.default,
+ theme.palette.action.disabledOpacity,
+ ),
},
'& .MuiDataGrid-overlayContent': {
flex: 1,
@@ -60,7 +66,6 @@ export const useStyles = makeStyles(
},
'& .MuiDataGrid-colCell, & .MuiDataGrid-cell': {
WebkitTapHighlightColor: 'transparent',
- ...theme.typography.body2,
lineHeight: null,
padding: theme.spacing(0, 2),
},
@@ -94,7 +99,6 @@ export const useStyles = makeStyles(
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
- color: theme.palette.text.primary,
fontWeight: theme.typography.fontWeightMedium,
},
'& .MuiDataGrid-columnSeparator': {
@@ -190,14 +194,14 @@ export const useStyles = makeStyles(
'& .MuiDataGrid-footer': {
display: 'flex',
justifyContent: 'space-between',
+ alignItems: 'center',
+ minHeight: 52, // Match TablePagination min height
},
'& .MuiDataGrid-rowCount, & .MuiDataGrid-selectedRowCount': {
alignItems: 'center',
- ...theme.typography.body2,
display: 'none',
paddingLeft: theme.spacing(2),
[theme.breakpoints.up('md')]: {
- minHeight: 52, // Match TablePagination min height
display: 'flex',
},
},
diff --git a/packages/grid/x-grid-modules/src/hooks/features/useComponents.tsx b/packages/grid/x-grid-modules/src/hooks/features/useComponents.tsx
index 62266c85a97e5..e7fea02d6714f 100644
--- a/packages/grid/x-grid-modules/src/hooks/features/useComponents.tsx
+++ b/packages/grid/x-grid-modules/src/hooks/features/useComponents.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { PaginationProps } from './usePagination';
import {
- ComponentParams,
+ ComponentProps,
ApiRef,
GridComponentOverridesProp,
GridOptions,
@@ -22,7 +22,7 @@ export const useComponents = (
apiRef: ApiRef,
gridRootRef: RootContainerRef,
) => {
- const componentParams: ComponentParams = React.useMemo(
+ const componentProps: ComponentProps = React.useMemo(
() => ({
paginationProps,
rows,
@@ -37,51 +37,51 @@ export const useComponents = (
const headerComponent = React.useMemo(
() =>
componentOverrides?.header
- ? React.createElement(componentOverrides.header, componentParams)
+ ? React.createElement(componentOverrides.header, componentProps)
: null,
- [componentOverrides, componentParams],
+ [componentOverrides, componentProps],
);
const footerComponent = React.useMemo(
() =>
componentOverrides?.footer
- ? React.createElement(componentOverrides.footer, componentParams)
+ ? React.createElement(componentOverrides.footer, componentProps)
: null,
- [componentOverrides, componentParams],
+ [componentOverrides, componentProps],
);
const loadingComponent = React.useMemo(
() =>
componentOverrides?.loadingOverlay ? (
- React.createElement(componentOverrides.loadingOverlay, componentParams)
+ React.createElement(componentOverrides.loadingOverlay, componentProps)
) : (
),
- [componentOverrides, componentParams],
+ [componentOverrides, componentProps],
);
const noRowsComponent = React.useMemo(
() =>
componentOverrides?.noRowsOverlay ? (
- React.createElement(componentOverrides.noRowsOverlay, componentParams)
+ React.createElement(componentOverrides.noRowsOverlay, componentProps)
) : (
),
- [componentOverrides, componentParams],
+ [componentOverrides, componentProps],
);
const paginationComponent = React.useMemo(
() =>
componentOverrides?.pagination
- ? React.createElement(componentOverrides.pagination, componentParams)
+ ? React.createElement(componentOverrides.pagination, componentProps)
: null,
- [componentOverrides, componentParams],
+ [componentOverrides, componentProps],
);
const renderError = React.useCallback(
(props) => {
const ErrorOverlay = componentOverrides?.errorOverlay || ErrorMessage;
- return ;
+ return ;
},
- [componentOverrides?.errorOverlay, componentParams],
+ [componentOverrides?.errorOverlay, componentProps],
);
return {
diff --git a/packages/grid/x-grid-modules/src/models/gridComponentOverridesProp.tsx b/packages/grid/x-grid-modules/src/models/gridComponentOverridesProp.tsx
index 0736500406ca1..fb482e5e96ba3 100644
--- a/packages/grid/x-grid-modules/src/models/gridComponentOverridesProp.tsx
+++ b/packages/grid/x-grid-modules/src/models/gridComponentOverridesProp.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import { ComponentParams } from './params';
+import { ComponentProps } from './params';
/**
* Grid components React prop interface containing all the overridable components.
@@ -8,25 +8,25 @@ export interface GridComponentOverridesProp {
/**
* Pagination component rendered in the grid footer by default.
*/
- pagination?: React.ElementType;
+ pagination?: React.ElementType;
/**
* Loading overlay component rendered when the grid is in a loading state.
*/
- loadingOverlay?: React.ElementType;
+ loadingOverlay?: React.ElementType;
/**
* No rows overlay component rendered when the grid has no rows.
*/
- noRowsOverlay?: React.ElementType;
+ noRowsOverlay?: React.ElementType;
/**
* Footer component rendered at the bottom of the grid viewport.
*/
- footer?: React.ElementType;
+ footer?: React.ElementType;
/**
* Header component rendered above the grid column header bar.
*/
- header?: React.ElementType;
+ header?: React.ElementType;
/**
* Error overlay component rendered above the grid when an error is caught.
*/
- errorOverlay?: React.ElementType;
+ errorOverlay?: React.ElementType;
}
diff --git a/packages/grid/x-grid-modules/src/models/params/componentParams.ts b/packages/grid/x-grid-modules/src/models/params/componentParams.ts
index e57a9a8ce69a8..daa7cfe2c753d 100644
--- a/packages/grid/x-grid-modules/src/models/params/componentParams.ts
+++ b/packages/grid/x-grid-modules/src/models/params/componentParams.ts
@@ -8,7 +8,7 @@ import { ApiRef } from '../api';
/**
* Object passed as React prop in the component override.
*/
-export interface ComponentParams {
+export interface ComponentProps {
/**
* The object containing all pagination details in [[PaginationProps]].
*/
diff --git a/packages/storybook/src/documentation/pages/components.stories.mdx b/packages/storybook/src/documentation/pages/components.stories.mdx
deleted file mode 100644
index 2a743ce4ee9f5..0000000000000
--- a/packages/storybook/src/documentation/pages/components.stories.mdx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { XGrid } from '@material-ui/x-grid';
-import LoadingOverrideDemo from './demos/customization/loadingOverride.demo';
-
-
-
-# Components
-
-As part of our customization API, XGrid allows to replace and override the following components.
-
-- `pagination` - the native pagination component as mentioned in the pagination page [here]()
-- `loadingOverlay` - rendered when the `loading` react prop is set to `true`
-- `noRowsOverlay` - rendered when the `rows` react prop is empty or `[]`
-- `header` - Rendered above the column header bar
-- `footer` - Rendered below the viewport
-
-To achieve this, you need to override the desired property of the `components` react prop.
-
-```tsx
-
-```
-
-Below is an example on how you can replace the loading overlay.
-
-
-
-- TODO add more components?
diff --git a/packages/storybook/src/documentation/pages/demos/customization/loadingOverride.demo.tsx b/packages/storybook/src/documentation/pages/demos/customization/loadingOverride.demo.tsx
deleted file mode 100644
index 28c5b31e6eac9..0000000000000
--- a/packages/storybook/src/documentation/pages/demos/customization/loadingOverride.demo.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Columns, GridOverlay, RowsProp, XGrid } from '@material-ui/x-grid';
-import LinearProgress from '@material-ui/core/LinearProgress';
-import * as React from 'react';
-import { randomCreatedDate, randomUpdatedDate } from '@material-ui/x-grid-data-generator';
-
-function LoadingComponent() {
- return (
-
-
-
-
-
- );
-}
-
-export default function LoadingOverrideDemo() {
- const columns: Columns = [
- { field: 'id', hide: true },
- { field: 'name', type: 'string' },
- { field: 'age', type: 'number' },
- { field: 'dateCreated', type: 'date', width: 180 },
- { field: 'lastLogin', type: 'dateTime', width: 180 },
- ];
- const rows: RowsProp = [
- {
- id: 1,
- name: 'Damien',
- age: 25,
- dateCreated: randomCreatedDate(),
- lastLogin: randomUpdatedDate(),
- },
- {
- id: 2,
- name: 'Nicolas',
- age: 36,
- dateCreated: randomCreatedDate(),
- lastLogin: randomUpdatedDate(),
- },
- {
- id: 3,
- name: 'Kate',
- age: 19,
- dateCreated: randomCreatedDate(),
- lastLogin: randomUpdatedDate(),
- },
- ];
- return (
-
- );
-}