diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec90aef2999..605be3b0a17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
- Updated `EuiRangeLevel` `color` property to accept CSS color values ([#5171](https://github.com/elastic/eui/pull/5171))
- Added optional visual line highlighting to `EuiCodeBlock` ([#5207](https://github.com/elastic/eui/pull/5207))
- Added `popoverProps` to `EuiSuperSelect` and deprecated `popoverClassName` & `repositionOnScroll` ([#5214](https://github.com/elastic/eui/pull/5214))
+- Added `lineHeight` configuration to `rowHeightsOptions` in `EuiDataGrid` ([#5221](https://github.com/elastic/eui/pull/5221))
**Bug fixes**
diff --git a/src-docs/src/views/datagrid/datagrid_example.js b/src-docs/src/views/datagrid/datagrid_example.js
index 0084d15f759..5e6123c2446 100644
--- a/src-docs/src/views/datagrid/datagrid_example.js
+++ b/src-docs/src/views/datagrid/datagrid_example.js
@@ -9,6 +9,7 @@ import {
EuiDescriptionList,
EuiCodeBlock,
EuiText,
+ EuiLink,
EuiSpacer,
} from '../../../../src/components';
@@ -107,6 +108,14 @@ const gridSnippet = `
rowHover: 'highlight',
header: 'shade',
}}
+ // Optional. Allows configuring the heights of grid rows
+ rowHeightsOptions={{
+ defaultHeight: 34,
+ rowHeights: {
+ 0: auto
+ },
+ lineHeight: '1em',
+ }}
// Optional. Provide additional schemas to use in the grid.
// This schema 'franchise' essentially acts like a boolean, looking for Star Wars or Star Trek in a column.
schemaDetectors={[
@@ -222,6 +231,20 @@ const gridConcepts = [
description:
'The total number of rows in the dataset (used by e.g. pagination to know how many pages to list).',
},
+ {
+ title: 'rowHeightsOptions',
+ description: (
+
+ Allows configuring both default and specific heights of grid rows.
+ Accepts a partial EuiDataGridRowHeightsOptions object.
+ See{' '}
+
+ Data grid row heights options
+ {' '}
+ for more details and examples.
+
+ ),
+ },
{
title: 'gridStyle',
description: (
diff --git a/src-docs/src/views/datagrid/datagrid_height_options_example.js b/src-docs/src/views/datagrid/datagrid_height_options_example.js
index 4799ab28685..596d9d2afd9 100644
--- a/src-docs/src/views/datagrid/datagrid_height_options_example.js
+++ b/src-docs/src/views/datagrid/datagrid_height_options_example.js
@@ -12,26 +12,55 @@ import {
import { EuiDataGridRowHeightsOptions } from '!!prop-loader!../../../../src/components/datagrid/data_grid_types';
+import DataGridRowLineHeight from './row_line_height';
+const dataGridRowLineHeightSource = require('!!raw-loader!./row_height_auto');
import DataGridRowHeightOptions from './row_height_fixed';
const dataGridRowHeightOptionsSource = require('!!raw-loader!./row_height_fixed');
import DataGridRowAutoHeight from './row_height_auto';
const dataGridRowAutoHeightSource = require('!!raw-loader!./row_height_auto');
+const lineHeightSnippet = `rowHeightsOptions = {
+ defaultHeight: {
+ lineCount: 3 // default every row to 3 lines of text
+ },
+ lineHeight: '2em', // default every cell line-height to 2em
+}`;
+
+const lineHeightFullSnippet = `const rowHeightsOptions = useMemo(
+ () => ({
+ defaultHeight: {
+ lineCount: 3,
+ },
+ lineHeight: '2em';
+ }),
+ []
+);
+
+
+`;
+
const rowHeightsSnippet = `rowHeightsOptions = {
defaultHeight: 140, // default every row to 140px
rowHeights: {
1: {
- lineCount: 5, // for row which have index 1 we allow to show 5 lines after that we truncate
+ lineCount: 5, // row at index 1 will show 5 lines
},
- 4: 200, // for row which have index 4 we set 140 pixel
+ 4: 200, // row at index 4 will adjust the height to 200px
5: 80,
},
}`;
const rowHeightsFullSnippet = `const rowHeightsOptions = useMemo(
() => ({
- defaultHeight: {
- lineCount: 2,
+ defaultHeight: 140,
}),
[]
);
@@ -110,24 +139,44 @@ export const DataGridRowHeightOptionsExample = {
By default, all rows get a height of 34 pixels, but
there are scenarios where you might want to adjust the height to fit
more content. To do that, you can pass an object to the{' '}
- rowHeightsOptions prop. This object accepts two
+ rowHeightsOptions prop. This object accepts three
properties:
-
- defaultHeight - defines the default size for all
- rows
+ defaultHeight
+
+ - Defines the default size for all rows
+ -
+ Can be configured with an exact pixel height, a line count, or{' '}
+ "auto" to fit all content
+
+
+
+ -
+ rowHeights
+
+ - Overrides the height for a specific row
+ -
+ Can be configured with an exact pixel height, a line count, or{' '}
+ "auto" to fit all content
+
+
-
- rowHeights - overrides the height for a specific
- row
+ lineHeight
+
+ -
+ Sets a default line height for all cells, which is used to
+ calculate row height
+
+ -
+ Accepts any value that the line-height CSS
+ property normally takes (e.g. px, ems, rems, or unitless)
+
+
-
- Each of these can be configured with an exact pixel height, a line
- count, or "auto" to fit all of the
- content. See the examples below for more details.
-
@@ -145,19 +194,55 @@ export const DataGridRowHeightOptionsExample = {
source: [
{
type: GuideSectionTypes.JS,
- code: dataGridRowHeightOptionsSource,
+ code: dataGridRowLineHeightSource,
},
],
- title: 'Fixed heights for rows',
+ title: 'Setting a default height and line height for rows',
text: (
You can change the default height for all rows by passing a line
count or pixel value to the defaultHeight{' '}
- property.
+ property, and customize the line height of all cells with the{' '}
+ lineHeight property.
+
+ {lineHeightSnippet}
+
+
+
+ If you wrap your cell content with CSS that overrides/sets
+ line-height (e.g. in an EuiText), your row
+ heights will not be calculated correctly! Make sure to match or
+ inherit the passed lineHeight property to the
+ actual cell content line height.
+
+
+
+ ),
+ components: { DataGridRowLineHeight },
+ props: {
+ EuiDataGrid,
+ EuiDataGridRowHeightsOptions,
+ },
+ demo: ,
+ snippet: lineHeightFullSnippet,
+ },
+ {
+ source: [
+ {
+ type: GuideSectionTypes.JS,
+ code: dataGridRowHeightOptionsSource,
+ },
+ ],
+ title: 'Overriding specific row heights',
+ text: (
+
- You can also override the height of a specific row by passing a
+ You can override the default height of a specific row by passing a
rowHeights object associating the row's
index with a specific height configuration.
diff --git a/src-docs/src/views/datagrid/row_height_auto.tsx b/src-docs/src/views/datagrid/row_height_auto.tsx
index 5771102da0d..0951408c859 100644
--- a/src-docs/src/views/datagrid/row_height_auto.tsx
+++ b/src-docs/src/views/datagrid/row_height_auto.tsx
@@ -136,7 +136,7 @@ const RenderCellValue: EuiDataGridProps['renderCellValue'] = ({
content = {item.body ?? ''};
} else {
// a full issue description is a *lot* to shove into a cell
- content = content = (
+ content = (
{(item.body ?? '').slice(0, 300)}
diff --git a/src-docs/src/views/datagrid/row_height_fixed.tsx b/src-docs/src/views/datagrid/row_height_fixed.tsx
index d2f0f330cae..91df500a1ca 100644
--- a/src-docs/src/views/datagrid/row_height_fixed.tsx
+++ b/src-docs/src/views/datagrid/row_height_fixed.tsx
@@ -136,7 +136,7 @@ const RenderCellValue: EuiDataGridProps['renderCellValue'] = ({
content = {item.body ?? ''};
} else {
// a full issue description is a *lot* to shove into a cell
- content = content = (
+ content = (
{(item.body ?? '').slice(0, 300)}
diff --git a/src-docs/src/views/datagrid/row_line_height.tsx b/src-docs/src/views/datagrid/row_line_height.tsx
new file mode 100644
index 00000000000..d79b9b86326
--- /dev/null
+++ b/src-docs/src/views/datagrid/row_line_height.tsx
@@ -0,0 +1,182 @@
+import React, {
+ useCallback,
+ useState,
+ createContext,
+ useContext,
+ useMemo,
+ ReactNode,
+} from 'react';
+// @ts-ignore not configured to import json
+import githubData from './row_auto_height_data.json';
+
+import { formatDate } from '../../../../src/services';
+
+import {
+ EuiDataGrid,
+ EuiDataGridProps,
+} from '../../../../src/components/datagrid';
+
+interface DataShape {
+ html_url: string;
+ title: string;
+ user: {
+ login: string;
+ avatar_url: string;
+ };
+ labels: Array<{
+ name: string;
+ color: string;
+ }>;
+ comments: number;
+ created_at: string;
+ body?: string;
+}
+
+// convert strings to Date objects
+for (let i = 0; i < githubData.length; i++) {
+ githubData[i].created_at = new Date(githubData[i].created_at);
+}
+
+type DataContextShape =
+ | undefined
+ | {
+ data: DataShape[];
+ };
+const DataContext = createContext(undefined);
+
+const columns = [
+ {
+ id: 'index',
+ displayAsText: 'Index',
+ isExpandable: false,
+ initialWidth: 80,
+ },
+ {
+ id: 'issue',
+ displayAsText: 'Issue',
+ isExpandable: false,
+ },
+ {
+ id: 'body',
+ displayAsText: 'Description',
+ },
+];
+
+// it is expensive to compute 10000 rows of fake data
+// instead of loading up front, generate entries on the fly
+const raw_data: DataShape[] = githubData;
+
+const RenderCellValue: EuiDataGridProps['renderCellValue'] = ({
+ rowIndex,
+ columnId,
+ isDetails,
+}) => {
+ const { data } = useContext(DataContext)!;
+
+ const item = data[rowIndex];
+ let content: ReactNode = '';
+
+ if (columnId === 'index') {
+ content = <>{rowIndex}>;
+ } else if (columnId === 'issue') {
+ content = (
+ <>
+ {item.title}
+
+ Opened by {item.user.login} on {formatDate(item.created_at, 'dobLong')}
+
+ {item.comments} comment{item.comments !== 1 ? 's' : ''}
+ >
+ );
+ } else if (columnId === 'body') {
+ if (isDetails) {
+ // expanded in a popover
+ content = item.body;
+ } else {
+ // a full issue description is a *lot* to shove into a cell
+ content = (item.body ?? '').slice(0, 300);
+ }
+ }
+
+ return content;
+};
+
+export default () => {
+ // ** Pagination config
+ const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 50 });
+
+ // ** Sorting config
+ const [sortingColumns, setSortingColumns] = useState([]);
+ const onSort = useCallback(
+ (sortingColumns) => {
+ setSortingColumns(sortingColumns);
+ },
+ [setSortingColumns]
+ );
+
+ const onChangeItemsPerPage = useCallback(
+ (pageSize) =>
+ setPagination((pagination) => ({
+ ...pagination,
+ pageSize,
+ pageIndex: 0,
+ })),
+ [setPagination]
+ );
+
+ const onChangePage = useCallback(
+ (pageIndex) =>
+ setPagination((pagination) => ({ ...pagination, pageIndex })),
+ [setPagination]
+ );
+
+ // Column visibility
+ const [visibleColumns, setVisibleColumns] = useState(() =>
+ columns.map(({ id }) => id)
+ ); // initialize to the full set of columns
+
+ // matches the snippet example
+ const rowHeightsOptions = useMemo(
+ () => ({
+ defaultHeight: {
+ lineCount: 3,
+ },
+ lineHeight: '2em',
+ }),
+ []
+ );
+
+ const dataContext = useMemo(
+ () => ({
+ data: raw_data,
+ }),
+ []
+ );
+
+ return (
+
+
+
+ );
+};
diff --git a/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap b/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap
index f9378b7c4dc..6293227a1cb 100644
--- a/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap
+++ b/src/components/datagrid/body/__snapshots__/data_grid_cell.test.tsx.snap
@@ -38,6 +38,7 @@ exports[`EuiDataGridCell renders 1`] = `
role="gridcell"
style={
Object {
+ "lineHeight": undefined,
"width": undefined,
}
}
diff --git a/src/components/datagrid/body/data_grid_cell.tsx b/src/components/datagrid/body/data_grid_cell.tsx
index f5eca7ff69e..0260120b12f 100644
--- a/src/components/datagrid/body/data_grid_cell.tsx
+++ b/src/components/datagrid/body/data_grid_cell.tsx
@@ -406,7 +406,7 @@ export class EuiDataGridCell extends Component<
style,
...rest
} = this.props;
- const { rowIndex } = rest;
+ const { rowIndex, rowHeightsOptions } = rest;
const showCellButtons =
this.state.isFocused ||
@@ -432,7 +432,12 @@ export class EuiDataGridCell extends Component<
className: classNames(cellClasses, this.state.cellProps.className),
};
- cellProps.style = { ...style, width, ...cellProps.style };
+ cellProps.style = {
+ ...style, // from react-window
+ width, // column width, can be undefined
+ lineHeight: rowHeightsOptions?.lineHeight ?? undefined, // lineHeight configuration
+ ...cellProps.style, // apply anything from setCellProps({style})
+ };
const handleCellKeyDown = (event: KeyboardEvent) => {
if (isExpandable) {
diff --git a/src/components/datagrid/data_grid.test.tsx b/src/components/datagrid/data_grid.test.tsx
index 18966b6046d..3c8e019537f 100644
--- a/src/components/datagrid/data_grid.test.tsx
+++ b/src/components/datagrid/data_grid.test.tsx
@@ -545,6 +545,7 @@ describe('EuiDataGrid', () => {
"color": "red",
"height": 34,
"left": 0,
+ "lineHeight": undefined,
"position": "absolute",
"top": "100px",
"width": 100,
@@ -564,6 +565,7 @@ describe('EuiDataGrid', () => {
"color": "blue",
"height": 34,
"left": 100,
+ "lineHeight": undefined,
"position": "absolute",
"top": "100px",
"width": 100,
@@ -583,6 +585,7 @@ describe('EuiDataGrid', () => {
"color": "red",
"height": 34,
"left": 0,
+ "lineHeight": undefined,
"position": "absolute",
"top": "134px",
"width": 100,
@@ -602,6 +605,7 @@ describe('EuiDataGrid', () => {
"color": "blue",
"height": 34,
"left": 100,
+ "lineHeight": undefined,
"position": "absolute",
"top": "134px",
"width": 100,
diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx
index b41984e7079..09e959c19d9 100644
--- a/src/components/datagrid/data_grid.tsx
+++ b/src/components/datagrid/data_grid.tsx
@@ -693,11 +693,19 @@ export const EuiDataGrid: FunctionComponent = (props) => {
}, [focusedCell, contentRef]);
useEffect(() => {
- rowHeightUtils.computeStylesForGridCell({
- cellPadding: gridStyles.cellPadding,
- fontSize: gridStyles.fontSize,
- });
- }, [gridStyles.cellPadding, gridStyles.fontSize, rowHeightUtils]);
+ rowHeightUtils.computeStylesForGridCell(
+ {
+ cellPadding: gridStyles.cellPadding,
+ fontSize: gridStyles.fontSize,
+ },
+ rowHeightsOptions?.lineHeight
+ );
+ }, [
+ gridStyles.cellPadding,
+ gridStyles.fontSize,
+ rowHeightsOptions?.lineHeight,
+ rowHeightUtils,
+ ]);
const classes = classNames(
'euiDataGrid',
diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts
index 3ab5c00d620..cd367e31372 100644
--- a/src/components/datagrid/data_grid_types.ts
+++ b/src/components/datagrid/data_grid_types.ts
@@ -719,4 +719,8 @@ export interface EuiDataGridRowHeightsOptions {
* Defines the height for a specific row. It can be line count or just height.
*/
rowHeights?: Record;
+ /**
+ * Defines a global lineHeight style to apply to all cells
+ */
+ lineHeight?: string;
}
diff --git a/src/components/datagrid/row_height_utils.ts b/src/components/datagrid/row_height_utils.ts
index 862eb9355ff..8ade9c469b4 100644
--- a/src/components/datagrid/row_height_utils.ts
+++ b/src/components/datagrid/row_height_utils.ts
@@ -136,12 +136,19 @@ export class RowHeightUtils {
return false;
}
- computeStylesForGridCell(gridStyles: EuiDataGridStyle) {
+ computeStylesForGridCell(
+ gridStyles: EuiDataGridStyle,
+ lineHeight: string | undefined
+ ) {
this.fakeCell.className = `
euiDataGridRowCell
${cellPaddingsToClassMap[gridStyles.cellPadding!]}
${fontSizesToClassMap[gridStyles.fontSize!]}
`;
+
+ // @ts-ignore it is valid to set `lineHeight` to undefined
+ this.fakeCell.style.lineHeight = lineHeight;
+
document.body.appendChild(this.fakeCell);
const allStyles = getComputedStyle(this.fakeCell);
this.styles = {