diff --git a/docs/data/data-grid/filtering/CustomFilterPanelPosition.js b/docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.js
similarity index 95%
rename from docs/data/data-grid/filtering/CustomFilterPanelPosition.js
rename to docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.js
index dfb4f68770c9d..022b087f60bf5 100644
--- a/docs/data/data-grid/filtering/CustomFilterPanelPosition.js
+++ b/docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.js
@@ -23,7 +23,7 @@ function CustomToolbar({ setFilterButtonEl }) {
);
}
-export default function CustomFilterPanelPosition() {
+export default function CustomFilterPanelPositionNoSnap() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
visibleFields: VISIBLE_FIELDS,
diff --git a/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx b/docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.tsx
similarity index 96%
rename from docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx
rename to docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.tsx
index a2ac5a8db49eb..ad2bb1b6ee132 100644
--- a/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx
+++ b/docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.tsx
@@ -32,7 +32,7 @@ function CustomToolbar({ setFilterButtonEl }: GridSlotProps['toolbar']) {
);
}
-export default function CustomFilterPanelPosition() {
+export default function CustomFilterPanelPositionNoSnap() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
visibleFields: VISIBLE_FIELDS,
diff --git a/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx.preview b/docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.tsx.preview
similarity index 100%
rename from docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx.preview
rename to docs/data/data-grid/filtering/CustomFilterPanelPositionNoSnap.tsx.preview
diff --git a/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.js b/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.js
new file mode 100644
index 0000000000000..bd2b7734264c6
--- /dev/null
+++ b/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.js
@@ -0,0 +1,34 @@
+import * as React from 'react';
+import { DataGrid } from '@mui/x-data-grid';
+import { useDemoData } from '@mui/x-data-grid-generator';
+
+const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin'];
+
+export default function FilterPanelPlacementColumnHeadersNoSnap() {
+ const { data, loading } = useDemoData({
+ dataSet: 'Employee',
+ visibleFields: VISIBLE_FIELDS,
+ rowLength: 100,
+ });
+
+ const columnHeadersRef = React.useRef(null);
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.tsx b/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.tsx
new file mode 100644
index 0000000000000..f6f0716d4984e
--- /dev/null
+++ b/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.tsx
@@ -0,0 +1,34 @@
+import * as React from 'react';
+import { DataGrid } from '@mui/x-data-grid';
+import { useDemoData } from '@mui/x-data-grid-generator';
+
+const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin'];
+
+export default function FilterPanelPlacementColumnHeadersNoSnap() {
+ const { data, loading } = useDemoData({
+ dataSet: 'Employee',
+ visibleFields: VISIBLE_FIELDS,
+ rowLength: 100,
+ });
+
+ const columnHeadersRef = React.useRef(null);
+
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.tsx.preview b/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.tsx.preview
new file mode 100644
index 0000000000000..bd1274aa277ff
--- /dev/null
+++ b/docs/data/data-grid/filtering/FilterPanelPlacementColumnHeadersNoSnap.tsx.preview
@@ -0,0 +1,14 @@
+
\ No newline at end of file
diff --git a/docs/data/data-grid/filtering/customization.md b/docs/data/data-grid/filtering/customization.md
index 1d4a676e5e535..081fd5a3ba97c 100644
--- a/docs/data/data-grid/filtering/customization.md
+++ b/docs/data/data-grid/filtering/customization.md
@@ -177,9 +177,17 @@ To pass props directly to the `InputComponent` and not its wrapper, you can use
### Customize the filter panel position
+#### Toolbar button anchor
+
The demo below shows how to anchor the filter panel to the toolbar button instead of the column header.
-{{"demo": "CustomFilterPanelPosition.js", "bg": "inline", "defaultCodeOpen": false}}
+{{"demo": "CustomFilterPanelPositionNoSnap.js", "bg": "inline", "defaultCodeOpen": false}}
+
+#### Column headers anchor
+
+The following demo shows how to make panels always appear on the bottom-left under the column headers mimicking the default behavior of Data Grid v7.
+
+{{"demo": "FilterPanelPlacementColumnHeadersNoSnap.js", "bg": "inline", "defaultCodeOpen": false}}
## API
diff --git a/packages/x-data-grid/src/components/panel/GridPanel.tsx b/packages/x-data-grid/src/components/panel/GridPanel.tsx
index acdbf781ad54c..404e88b308972 100644
--- a/packages/x-data-grid/src/components/panel/GridPanel.tsx
+++ b/packages/x-data-grid/src/components/panel/GridPanel.tsx
@@ -23,10 +23,7 @@ export interface GridPanelClasses {
paper: string;
}
-export interface GridPanelProps extends Pick<
- GridSlotProps['basePopper'],
- 'id' | 'className' | 'target' | 'flip'
-> {
+export interface GridPanelProps extends Omit {
ref?: React.Ref;
children?: React.ReactNode;
/**
@@ -134,11 +131,48 @@ GridPanel.propTypes = {
*/
classes: PropTypes.object,
className: PropTypes.string,
+ clickAwayMouseEvent: PropTypes.oneOf([
+ 'onClick',
+ 'onMouseDown',
+ 'onMouseUp',
+ 'onPointerDown',
+ 'onPointerUp',
+ false,
+ ]),
+ clickAwayTouchEvent: PropTypes.oneOf(['onTouchEnd', 'onTouchStart', false]),
flip: PropTypes.bool,
+ focusTrap: PropTypes.bool,
id: PropTypes.string,
+ onClickAway: PropTypes.func,
onClose: PropTypes.func,
+ onDidHide: PropTypes.func,
+ onDidShow: PropTypes.func,
+ onExited: PropTypes.func,
open: PropTypes.bool.isRequired,
+ /**
+ * @default 'bottom'
+ */
+ placement: PropTypes.oneOf([
+ 'auto-end',
+ 'auto-start',
+ 'auto',
+ 'bottom-end',
+ 'bottom-start',
+ 'bottom',
+ 'left-end',
+ 'left-start',
+ 'left',
+ 'right-end',
+ 'right-start',
+ 'right',
+ 'top-end',
+ 'top-start',
+ 'top',
+ ]),
+ role: PropTypes.string,
+ style: PropTypes.object,
target: PropTypes /* @typescript-to-proptypes-ignore */.any,
+ transition: PropTypes.bool,
} as any;
export { GridPanel };