diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99a907b60bf..0150fcadd80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
## [`main`](https://github.com/elastic/eui/tree/main)
+- Added the ability to control internal `EuiDataGrid` fullscreen, cell focus, and cell popover state via the `ref` prop ([#5590](https://github.com/elastic/eui/pull/5590))
+
**Bug fixes**
- Fixed `EuiInMemoryTable`'s `onTableChange` callback not returning the correct `sort.field` value on pagination ([#5588](https://github.com/elastic/eui/pull/5588))
diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js
index 11d3ff15f0a..23c7d8366e5 100644
--- a/src-docs/src/routes.js
+++ b/src-docs/src/routes.js
@@ -89,6 +89,7 @@ import { DataGridControlColumnsExample } from './views/datagrid/datagrid_control
import { DataGridFooterRowExample } from './views/datagrid/datagrid_footer_row_example';
import { DataGridVirtualizationExample } from './views/datagrid/datagrid_virtualization_example';
import { DataGridRowHeightOptionsExample } from './views/datagrid/datagrid_height_options_example';
+import { DataGridRefExample } from './views/datagrid/datagrid_ref_example';
import { DatePickerExample } from './views/date_picker/date_picker_example';
@@ -489,6 +490,7 @@ const navigation = [
DataGridFooterRowExample,
DataGridVirtualizationExample,
DataGridRowHeightOptionsExample,
+ DataGridRefExample,
TableExample,
TableInMemoryExample,
].map((example) => createExample(example)),
diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js
index a23052743aa..70e0c508fd0 100644
--- a/src-docs/src/views/datagrid/datagrid.js
+++ b/src-docs/src/views/datagrid/datagrid.js
@@ -6,6 +6,7 @@ import React, {
createContext,
useContext,
useRef,
+ createRef,
} from 'react';
import { Link } from 'react-router-dom';
import { fake } from 'faker';
@@ -29,11 +30,13 @@ import {
EuiModalHeader,
EuiModalHeaderTitle,
EuiPopover,
+ EuiScreenReaderOnly,
EuiText,
EuiTitle,
} from '../../../../src/components/';
-const DataContext = createContext();
+const gridRef = createRef();
+const DataContext = createContext();
const raw_data = [];
for (let i = 1; i < 100; i++) {
@@ -216,13 +219,20 @@ const trailingControlColumns = [
{
id: 'actions',
width: 40,
- headerCellRender: () => null,
- rowCellRender: function RowCellRender() {
+ headerCellRender: () => (
+
+ Controls
+
+ ),
+ rowCellRender: function RowCellRender({ rowIndex, colIndex }) {
const [isPopoverVisible, setIsPopoverVisible] = useState(false);
const closePopover = () => setIsPopoverVisible(false);
const [isModalVisible, setIsModalVisible] = useState(false);
- const closeModal = () => setIsModalVisible(false);
+ const closeModal = () => {
+ setIsModalVisible(false);
+ gridRef.current.setFocusedCell({ rowIndex, colIndex });
+ };
const showModal = () => {
closePopover();
setIsModalVisible(true);
@@ -263,7 +273,10 @@ const trailingControlColumns = [
}
const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
- const closeFlyout = () => setIsFlyoutVisible(false);
+ const closeFlyout = () => {
+ setIsFlyoutVisible(false);
+ gridRef.current.setFocusedCell({ rowIndex, colIndex });
+ };
const showFlyout = () => {
closePopover();
setIsFlyoutVisible(true);
@@ -415,6 +428,7 @@ export default () => {
onChangePage: onChangePage,
}}
onColumnResize={onColumnResize.current}
+ ref={gridRef}
/>
);
diff --git a/src-docs/src/views/datagrid/datagrid_example.js b/src-docs/src/views/datagrid/datagrid_example.js
index 47a606c471c..3ecd3c20e5b 100644
--- a/src-docs/src/views/datagrid/datagrid_example.js
+++ b/src-docs/src/views/datagrid/datagrid_example.js
@@ -33,6 +33,7 @@ import {
EuiDataGridRowHeightsOptions,
EuiDataGridCellValueElementProps,
EuiDataGridSchemaDetector,
+ EuiDataGridRefProps,
} from '!!prop-loader!../../../../src/components/datagrid/data_grid_types';
const gridSnippet = `
@@ -164,6 +165,8 @@ const gridSnippet = `
);
},
}}
+ // Optional. For advanced control of internal data grid popover/focus state, passes back an object of API methods
+ ref={dataGridRef}
/>
`;
@@ -323,6 +326,19 @@ const gridConcepts = [
),
},
+ {
+ title: 'ref',
+ description: (
+
+ Passes back an object of internal EuiDataGridRefProps{' '}
+ methods for advanced control of data grid popover/focus state. See{' '}
+
+ Data grid ref methods
+ {' '}
+ for more details and examples.
+
+ ),
+ },
];
export const DataGridExample = {
@@ -414,6 +430,7 @@ export const DataGridExample = {
EuiDataGridToolBarAdditionalControlsLeftOptions,
EuiDataGridPopoverContentProps,
EuiDataGridRowHeightsOptions,
+ EuiDataGridRefProps,
},
demo: (
diff --git a/src-docs/src/views/datagrid/datagrid_ref_example.js b/src-docs/src/views/datagrid/datagrid_ref_example.js
new file mode 100644
index 00000000000..66795c4e25b
--- /dev/null
+++ b/src-docs/src/views/datagrid/datagrid_ref_example.js
@@ -0,0 +1,117 @@
+import React from 'react';
+
+import { GuideSectionTypes } from '../../components';
+import { EuiCode, EuiSpacer, EuiCallOut } from '../../../../src/components';
+
+import { EuiDataGridRefProps } from '!!prop-loader!../../../../src/components/datagrid/data_grid_types';
+import DataGridRef from './ref';
+const dataGridRefSource = require('!!raw-loader!./ref');
+const dataGridRefSnippet = `const dataGridRef = useRef();
+
+
+// Mnaually toggle the data grid's full screen state
+dataGridRef.current.setIsFullScreen(true);
+
+// Mnaually focus a specific cell within the data grid
+dataGridRef.current.setFocusedCell({ rowIndex, colIndex });
+
+// Manually opens the popover of a specified cell within the data grid
+dataGridRef.current.openCellPopover({ rowIndex, colIndex });
+
+// Close any open cell popover
+dataGridRef.current.closeCellPopover();
+`;
+
+export const DataGridRefExample = {
+ title: 'Data grid ref methods',
+ sections: [
+ {
+ source: [
+ {
+ type: GuideSectionTypes.TSX,
+ code: dataGridRefSource,
+ },
+ ],
+ text: (
+ <>
+
+ For advanced use cases, and particularly for data grids that manage
+ associated modals/flyouts and need to manually control their grid
+ cell popovers & focus states, we expose certain internal methods via
+ the ref prop of EuiDataGrid.
+ These methods are:
+
+
+
+
+ setIsFullScreen(isFullScreen) - controls the
+ full screen state of the data grid. Accepts a true/false boolean
+ flag.
+
+
+
+ setFocusedCell({'{ rowIndex, colIndex }'}) -
+ focuses the specified cell in the grid.
+
+
+ Your modal or flyout should restore focus into the grid on close
+ to prevent keyboard or screen reader users from being stranded.
+
+
+