Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: elastic/eui
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 489e4686b9ed042a4a21126325af1a30f6f08a7d
Choose a base ref
..
head repository: elastic/eui
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1372f28926865e262aee35a6314fb7e0bec6fb37
Choose a head ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { useMemo, FC, ReactNode } from 'react';
import {
EuiBasicTable,
EuiBasicTableColumn,
EuiMarkdownFormat,
getDefaultEuiMarkdownPlugins,
EuiCodeBlock,
EuiLink,
EuiSpacer,
} from '@elastic/eui';
import { ProcessedComponent } from '@elastic/eui-docgen';

type DataGridPropSnippetTableProps = {
propSnippetMap: Record<string, string | ReactNode>;
linksMap?: Record<string, string>;
docgen: ProcessedComponent;
};

const { processingPlugins, parsingPlugins } = getDefaultEuiMarkdownPlugins({
exclude: ['lineBreaks'],
});

const columns: Array<EuiBasicTableColumn<{}>> = [
{
name: 'Prop',
render: ({ propName, propDescription }) => (
<>
{propName}
{propDescription && (
<>
<EuiSpacer size="s" />
<EuiMarkdownFormat
textSize="s"
processingPluginList={processingPlugins}
parsingPluginList={parsingPlugins}
>
{propDescription}
</EuiMarkdownFormat>
</>
)}
</>
),
textOnly: true,
valign: 'top',
},
{
field: 'snippet',
name: 'Sample snippet',
render: (snippet: string | ReactNode) =>
typeof snippet === 'string' ? (
<EuiCodeBlock
fontSize="s"
paddingSize="s"
className="eui-fullWidth"
isCopyable
language="tsx"
>
{snippet}
</EuiCodeBlock>
) : (
snippet
),
valign: 'top',
},
];

export const DataGridPropSnippetTable: FC<DataGridPropSnippetTableProps> = ({
propSnippetMap,
linksMap,
docgen,
}) => {
const items = useMemo(
() =>
Object.entries(propSnippetMap).map(([prop, snippet]) => {
const propLink = linksMap?.[prop];
const propName = propLink ? (
<EuiLink href={propLink}>
<strong>{prop}</strong>
</EuiLink>
) : (
<strong>{prop}</strong>
);
const propDescription = docgen.props[prop]?.description;

return { propName, propDescription, snippet };
}),
[propSnippetMap]
);

return <EuiBasicTable items={items} columns={columns} />;
};
Original file line number Diff line number Diff line change
@@ -448,10 +448,10 @@ export default () => {

## Top level props

Please check the [props section](#props) below for more explanation on the lower level object types. The majority of the types are defined in the [/datagrid/data\_grid\_types.ts](https://github.com/elastic/eui/tree/main/packages/eui/src/components/datagrid/data_grid_types.ts) file.
The below table contains a list of all top level **EuiDataGrid** props and sample snippets used to configure or customize them.

## Props
For a full list of all data grid types, including lower level configurations, please see the [/datagrid/data\_grid\_types.ts](https://github.com/elastic/eui/tree/main/packages/eui/src/components/datagrid/data_grid_types.ts) definition file.

import docgen from '@elastic/eui-docgen/dist/components/datagrid/data_grid.json';
import TopLevelProps from './data_grid_props';

<PropTable definition={docgen.EuiDataGrid} />
<TopLevelProps />
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import { EuiDataGrid } from '@elastic/eui-docgen/dist/components/datagrid/data_grid.json';

import { DataGridPropSnippetTable } from './_prop_snippet_table';

export const topLevelPropSnippets = {
rowCount: 'rowCount={200}',
columns: `columns={[
{
id: 'A', // required
display: <>Column A <EuiIcon type="dot" /></>, // optional column header rendering
displayAsText: 'Column A', // column header as plain text
displayHeaderCellProps: { className: 'eui-textCenter' }, // optional column header cell props
initialWidth: 150, // starting width of 150px
isResizable: false, // prevents the user from resizing width
isExpandable: false, // doesn't allow clicking in to see the content in a popup
isSortable: false, // prevents the user from sorting the data grid by this column
defaultSortDirection: 'asc', // sets the default sort direction
schema: 'franchise', // custom schema later defined under schemaDetectors
actions: false, // no column header actions are displayed
actions: { showMoveLeft: false, showMoveRight: false }, // doesn't show move actions in column header
cellActions: [ // provides one additional cell action that triggers an alert once clicked
({ Component }) => <Component iconType="heart" onClick={() => alert('test')}>Custom action</Component>,
],
visibleCellActions: 2, // configures the number of cell action buttons immediately visible on a cell
},
]}`,
leadingControlColumns: `leadingControlColumns={[
{
id: 'selection',
width: 31,
headerCellRender: () => <span>Select a row</span>,
headerCellProps: { className: 'eui-textCenter' },
rowCellRender: () => <div><EuiCheckbox ... /></div>,
footerCellRender: () => <span>Select a row</span>,
footerCellProps: { className: 'eui-textCenter' },
},
]}`,
trailingControlColumns: `trailingControlColumns={[
{
id: 'actions',
width: 40,
headerCellRender: () => 'Actions',
headerCellProps: { className: 'euiScreenReaderOnly' },
rowCellRender: MyGridActionsComponent,
footerCellRender: () => null,
footerCellProps: { data-test-subj: 'emptyFooterCell' },
},
]}`,
columnVisibility: `columnVisibility={{
visibleColumns: ['A'],
setVisibleColumns: () => {},
canDragAndDropColumns: true,
}}`,
onColumnResize: 'onColumnResize={({columnId, width}) => {}}',
schemaDetectors: (
<a href="../data-grid/schema-and-columns#schemas">
See Schemas & columns for full details.
</a>
),
renderCellValue: 'renderCellValue={({ rowIndex, columnId }) => {}}',
cellContext: `cellContext={{
// Will be passed to your \`renderCellValue\` function/component as a prop
yourData,
}}
renderCellValue={({ rowIndex, columnId, yourData }) => {}}`,
renderCellPopover: `renderCellPopover={({ children, cellActions }) => (
<>
<EuiPopoverTitle>I'm a custom popover!</EuiPopoverTitle>
{children}
{cellActions}
</>
)}`,
renderFooterCellValue:
'renderFooterCellValue={({ rowIndex, columnId }) => {}}',
renderCustomToolbar:
'renderCustomToolbar={({ displayControl }) => <div>Custom toolbar content {displayControl}</div>}',
renderCustomGridBody: `// Optional; advanced usage only. This render function is an escape hatch for consumers who need to opt out of virtualization or otherwise need total custom control over how data grid cells are rendered.
renderCustomGridBody={({ visibleColumns, visibleRowData, Cell }) => (
<Cell colIndex={mappedFromVisibleColumns} visibleRowIndex={mappedFromVisibleRowData} />
)}`,
pagination: `pagination={{
pageIndex: 1,
pageSize: 100, // If not specified, defaults to EuiTablePagination.itemsPerPage
pageSizeOptions: [50, 100, 200], // If not specified, defaults to EuiTablePagination.itemsPerPageOptions
onChangePage: () => {},
onChangeItemsPerPage: () => {},
}}`,
sorting: `sorting={{
columns: [{ id: 'A', direction: 'asc' }],
onSort: () => {},
}}`,
inMemory: `// Will try to autodectect schemas and do sorting and pagination in memory.
inMemory={{ level: 'sorting' }}`,
toolbarVisibility: `toolbarVisibility={{
showColumnSelector: false,
showDisplaySelector: false,
showSortSelector: false,
showKeyboardShortcuts: false,
showFullScreenSelector: false,
additionalControls: {
left: <EuiButtonEmpty size="xs" />,
right: <EuiButtonIcon size="xs" />,
},
}}`,
gridStyle: `gridStyle={{
border: 'none',
stripes: true,
rowHover: 'highlight',
header: 'underline',
// If showDisplaySelector.allowDensity={true} from toolbarVisibility, fontSize and cellPadding will be superceded by what the user decides.
cellPadding: 'm',
fontSize: 'm',
footer: 'overline'
}}`,
rowHeightsOptions: `rowHeightsOptions={{
defaultHeight: {
lineCount: 3 // default every row to 3 lines of text
},
lineHeight: '2em', // default every cell line-height to 2em
rowHeights: {
1: {
lineCount: 5, // row at index 1 will show 5 lines
},
4: 200, // row at index 4 will adjust the height to 200px
6: 'auto', // row at index 6 will automatically adjust the height
},
scrollAnchorRow: 'start', // compensate for layout shift when auto-sized rows are scrolled into view
}}`,
ref: `// Optional. For advanced control of internal data grid state, passes back an object of imperative API methods
ref={dataGridRef}`,
virtualizationOptions: `// Optional. For advanced control of the underlying react-window virtualization grid.
virtualizationOptions={{
className: 'virtualizedGridClass',
style: {},
direction: 'ltr',
estimatedRowHeight: 50,
overscanColumnCount: 1,
overscanRowCount: 1,
initialScrollLeft: 0,
initialScrollTop: 0,
onScroll: () => {},
onItemsRendered: () => {},
itemKey: () => {},
outerElementType: 'div',
}}
// Properties not listed above are used by EuiDataGrid internals and cannot be overridden.
`,
};

const propLinks = {
schemaDetectors: '../data-grid/schema-and-columns#schemas',
onColumnResize: '../data-grid/schema-and-columns/#column-widths',
leadingControlColumns: '../data-grid/schema-and-columns#control-columns',
trailingControlColumns: '../data-grid/schema-and-columns#control-columns',
renderFooterCellValue: '../data-grid/schema-and-columns#footer-row',
renderCellPopover:
'../data-grid/cells-and-popovers#completely-customizing-cell-popover-rendering',
cellContext: '../data-grid/cells-and-popovers#cell-context',
rowHeightsOptions: '../data-grid/style-and-display#row-heights-options',
gridStyle: '../data-grid/style-and-display#grid-style',
inMemory: '../data-grid/advanced#data-grid-in-memory',
ref: '../data-grid/advanced#ref-methods',
renderCustomGridBody: '../data-grid/advanced#custom-body-renderer',
renderCustomToolbar:
'../data-grid/toolbar#completely-custom-toolbar-rendering',
toolbarVisibility: '../data-grid/toolbar#toolbar-visibility',
};

export default () => (
<DataGridPropSnippetTable
propSnippetMap={topLevelPropSnippets}
linksMap={propLinks}
docgen={EuiDataGrid}
/>
);
Original file line number Diff line number Diff line change
@@ -362,6 +362,100 @@ export default () => {
};
```

## Draggable columns

To reorder columns directly instead of via the actions menu popover, you can enable draggable **EuiDataGrid** header columns via the `columnVisibility.canDragAndDropColumns` prop. This will allow you to reorder the column by dragging them.

```tsx interactive
import React, { useState, useCallback } from 'react';
import { EuiDataGrid, EuiAvatar } from '@elastic/eui';
import { faker } from '@faker-js/faker';

const columns = [
{
id: 'avatar',
initialWidth: 40,
isResizable: false,
},
{
id: 'name',
initialWidth: 100,
},
{
id: 'email',
},
{
id: 'city',
},
{
id: 'country',
},
{
id: 'account',
},
];

const data = [];

for (let i = 1; i < 5; i++) {
data.push({
avatar: (
<EuiAvatar
size="s"
name={`${faker.person.lastName()}, ${faker.person.firstName()}`}
/>
),
name: `${faker.person.lastName()}, ${faker.person.firstName()} ${faker.person.suffix()}`,
email: faker.internet.email(),
city: faker.location.city(),
country: faker.location.country(),
account: faker.finance.accountNumber(),
});
}

export default () => {
const [pagination, setPagination] = useState({ pageIndex: 0 });

const [visibleColumns, setVisibleColumns] = useState(
columns.map(({ id }) => id)
);

const setPageIndex = useCallback(
(pageIndex) =>
setPagination((pagination) => ({ ...pagination, pageIndex })),
[]
);
const setPageSize = useCallback(
(pageSize) =>
setPagination((pagination) => ({
...pagination,
pageSize,
pageIndex: 0,
})),
[]
);

return (
<EuiDataGrid
aria-label="DataGrid demonstrating draggable column headers"
columns={columns}
columnVisibility={{
visibleColumns: visibleColumns,
setVisibleColumns: setVisibleColumns,
canDragAndDropColumns: true,
}}
rowCount={data.length}
renderCellValue={({ rowIndex, columnId }) => data[rowIndex][columnId]}
pagination={{
...pagination,
onChangeItemsPerPage: setPageSize,
onChangePage: setPageIndex,
}}
/>
);
};
```

## Control columns

Control columns can be used to include ancillary cells not based on the dataset, such as row selection checkboxes or action buttons. These columns can be placed at either side of the data grid, and users are unable to resize, sort, or rearrange them.
Original file line number Diff line number Diff line change
@@ -580,95 +580,6 @@ export default () => {

## Toolbar props

### `EuiDataGridToolBarVisibilityOptions`
import ToolbarProps from './data_grid_toolbar_props';

This table contains 6 rows.
|
Prop

|

Sample snippet

|
| --- | --- |
|

**showSortSelector**

Allows the ability for the user to sort rows based upon column values

|
```
showSortSelector: false
```

|
|

**additionalControls**

If passed a `ReactNode`, appends the passed custom control into the left side of the toolbar, after the column & sort controls. Or use **EuiDataGridToolBarAdditionalControlsOptions** to customize the location of your control.

|
```
additionalControls: {
left: <EuiButtonEmpty size="xs" />,
right: <EuiButtonIcon size="xs" />,
}
```

|
|

**showColumnSelector**

Allows the ability for the user to hide fields and sort columns, boolean or a **EuiDataGridToolBarVisibilityColumnSelectorOptions**

|
```
showColumnSelector: {
allowHide: false;
allowReorder: false;
}
```

|
|

**showDisplaySelector**

Allows the ability for the user to customize display settings such as grid density and row heights. User changes will override what is provided in **EuiDataGridStyle** and **EuiDataGridRowHeightsOptions**

|
```
showDisplaySelector: {
allowDensity: false;
allowRowHeight: false;
allowResetButton: false;
additionalDisplaySettings: <EuiButtonEmpty size="xs" />;
}
```

|
|

**showFullScreenSelector**

Allows user to be able to fullscreen the data grid. If set to `false` make sure your grid fits within a large enough panel to still show the other controls.

|
```
showFullScreenSelector: false
```

|
|

**showKeyboardShortcuts**

Displays a popover listing all keyboard controls and shortcuts for the data grid. If set to `false`, the toggle will be visually hidden, but still focusable by keyboard and screen reader users.

|

|
<ToolbarProps />
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { EuiCode } from '@elastic/eui';
import { EuiDataGridToolbarPropsComponent } from '@elastic/eui-docgen/dist/components/datagrid/data_grid.stories.utils.json';

import { DataGridPropSnippetTable } from './_prop_snippet_table';

const toolbarVisibilitySnippets = {
showColumnSelector: `showColumnSelector: {
allowHide: false,
allowReorder: false,
}`,
showSortSelector: 'showSortSelector: false',
showKeyboardShortcuts: 'showKeyboardShortcuts: false',
showDisplaySelector: `showDisplaySelector: {
allowDensity: false,
allowRowHeight: false,
allowResetButton: false,
additionalDisplaySettings: <EuiButtonEmpty size="xs" />,
customRender: ({ densityControl, rowHeightControl, resetButton, additionalDisplaySettings }) => (
<>Completely custom display settings</>
),
}`,
showFullScreenSelector: 'showFullScreenSelector: false',
additionalControls: `additionalControls: {
left: <EuiButtonEmpty size="xs" />,
right: <EuiButtonIcon size="xs" />,
}`,
};

export default () => (
<>
<h3>
<EuiCode>EuiDataGridToolBarVisibilityOptions</EuiCode>
</h3>
<DataGridPropSnippetTable
propSnippetMap={toolbarVisibilitySnippets}
docgen={EuiDataGridToolbarPropsComponent}
/>
</>
);