From e14fb4cd4e60b45b538dce2d52e9d07a831a1a9f Mon Sep 17 00:00:00 2001 From: Tim Schnell Date: Wed, 30 Aug 2023 13:51:02 -0500 Subject: [PATCH 01/19] adding api for additional display controls on the datagrid --- .../src/views/datagrid/basics/datagrid.js | 21 +++++++++++++++++++ .../datagrid/controls/display_selector.tsx | 7 +++++++ src/components/datagrid/data_grid_types.ts | 4 ++++ 3 files changed, 32 insertions(+) diff --git a/src-docs/src/views/datagrid/basics/datagrid.js b/src-docs/src/views/datagrid/basics/datagrid.js index a8898bb14b7..3efb5211d04 100644 --- a/src-docs/src/views/datagrid/basics/datagrid.js +++ b/src-docs/src/views/datagrid/basics/datagrid.js @@ -23,6 +23,7 @@ import { EuiFlyoutBody, EuiFlyoutFooter, EuiFlyoutHeader, + EuiFormRow, EuiLink, EuiModal, EuiModalBody, @@ -30,6 +31,7 @@ import { EuiModalHeader, EuiModalHeaderTitle, EuiPopover, + EuiRange, EuiScreenReaderOnly, EuiText, EuiTitle, @@ -406,12 +408,31 @@ export default () => { console.log(eventData); }); + const customDisplaySetting = ( + + + + ); return ( )} + {additionalDisplaySettings} + {showResetButton && ( diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index 7bdf0d5ba8b..3b3cc5a1371 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -846,6 +846,10 @@ export interface EuiDataGridToolBarVisibilityDisplaySelectorOptions { * When `false`, removes the ability to change row height display through the UI */ allowRowHeight?: boolean; + /** + * If passed an object it will append the additional option to the bottom of the display settings + */ + additionalDisplaySettings?: ReactNode; } export interface EuiDataGridToolBarVisibilityOptions { From 488e365cc91961caea875162d8d267751c76e884 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Fri, 1 Sep 2023 23:39:55 +0200 Subject: [PATCH 02/19] [EuiDataGrid] Introduce a renderCustomToolbar render prop (#7150) --- .../datagrid/advanced/custom_toolbar.tsx | 170 +++++++++++++ .../advanced/datagrid_advanced_example.js | 24 ++ .../datagrid/controls/display_selector.tsx | 237 +++++++++--------- src/components/datagrid/data_grid.tsx | 67 +++-- src/components/datagrid/data_grid_types.ts | 15 ++ 5 files changed, 371 insertions(+), 142 deletions(-) create mode 100644 src-docs/src/views/datagrid/advanced/custom_toolbar.tsx diff --git a/src-docs/src/views/datagrid/advanced/custom_toolbar.tsx b/src-docs/src/views/datagrid/advanced/custom_toolbar.tsx new file mode 100644 index 00000000000..915391469b2 --- /dev/null +++ b/src-docs/src/views/datagrid/advanced/custom_toolbar.tsx @@ -0,0 +1,170 @@ +import React, { useCallback, useState } from 'react'; +import { faker } from '@faker-js/faker'; + +import { + EuiDataGrid, + EuiDataGridColumnCellActionProps, + EuiButtonIcon, + EuiDataGridPaginationProps, + EuiDataGridSorting, + EuiDataGridColumnSortingConfig, + EuiPopover, + EuiDataGridCustomToolbarProps, + EuiFormRow, + EuiRange, +} from '../../../../../src'; + +const raw_data: Array<{ [key: string]: string }> = []; +for (let i = 1; i < 100; i++) { + raw_data.push({ + name: `${faker.name.lastName()}, ${faker.name.firstName()}`, + email: faker.internet.email(), + location: `${faker.address.city()}, ${faker.address.country()}`, + date: `${faker.date.past()}`, + amount: faker.commerce.price(1, 1000, 2, '$'), + }); +} + +const columns = [ + { + id: 'name', + displayAsText: 'Name', + cellActions: [ + ({ Component }: EuiDataGridColumnCellActionProps) => ( + alert('action')} + iconType="faceHappy" + aria-label="Some action" + > + Some action + + ), + ], + }, + { + id: 'email', + displayAsText: 'Email address', + initialWidth: 130, + }, + { + id: 'location', + displayAsText: 'Location', + }, + { + id: 'date', + displayAsText: 'Date', + }, + { + id: 'amount', + displayAsText: 'Amount', + }, +]; + +export default () => { + // Column visibility + const [visibleColumns, setVisibleColumns] = useState(() => + columns.map(({ id }) => id) + ); + + // Pagination + const [pagination, setPagination] = useState({ pageIndex: 0 }); + const onChangePage = useCallback( + (pageIndex) => { + setPagination((pagination) => ({ ...pagination, pageIndex })); + }, + [] + ); + const onChangePageSize = useCallback< + EuiDataGridPaginationProps['onChangeItemsPerPage'] + >((pageSize) => { + setPagination((pagination) => ({ ...pagination, pageSize })); + }, []); + + // Sorting + const [sortingColumns, setSortingColumns] = useState< + EuiDataGridColumnSortingConfig[] + >([]); + const onSort = useCallback((sortingColumns) => { + setSortingColumns(sortingColumns); + }, []); + const [isDisplaySelectorOpen, setIsDisplaySelectorOpen] = useState(false); + + // Custom toolbar body renderer + const RenderCustomToolbar = ({ + fullScreenSelector, + keyboardShortcuts, + rowHeightsControls, + densityControls, + columnSelector, + columnSorting, + }: EuiDataGridCustomToolbarProps) => { + return ( +
+
+ Always look at the left side of grid! +
+
+ {fullScreenSelector} + {keyboardShortcuts} + setIsDisplaySelectorOpen(true)} + /> + } + isOpen={isDisplaySelectorOpen} + data-test-subj="dataGridDisplaySelectorPopover" + closePopover={() => setIsDisplaySelectorOpen(false)} + anchorPosition="downRight" + panelPaddingSize="s" + panelClassName="euiDataGrid__displayPopoverPanel" + > + {rowHeightsControls} + {densityControls} + + + + + + {columnSorting} + {columnSelector} +
+
+ ); + }; + + return ( + <> + + raw_data[rowIndex][columnId] + } + renderCustomToolbar={RenderCustomToolbar} + height={undefined} + gridStyle={{ border: 'none', header: 'underline' }} + /> + + ); +}; diff --git a/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js b/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js index ce49e6dda5a..861790a37d4 100644 --- a/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js +++ b/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js @@ -8,6 +8,7 @@ import { EuiCallOut, EuiTitle, EuiLink, + EuiDataGridCustomToolbarProps, } from '../../../../../src/components'; import { @@ -36,7 +37,9 @@ dataGridRef.current.closeCellPopover(); `; import CustomRenderer from './custom_renderer'; +import CustomToolbarRenderer from './custom_toolbar'; const customRendererSource = require('!!raw-loader!./custom_renderer'); +const customToolbarSource = require('!!raw-loader!./custom_toolbar'); const customRendererSnippet = `const CustomGridBody = ({ visibleColumns, visibleRowData, Cell }) => { const visibleRows = raw_data.slice( visibleRowData.startRow, @@ -253,5 +256,26 @@ export const DataGridAdvancedExample = { snippet: customRendererSnippet, props: { EuiDataGridCustomBodyProps }, }, + { + title: 'Custom toolbar renderer', + source: [ + { + type: GuideSectionTypes.TSX, + code: customToolbarSource, + }, + ], + text: ( + <> +

+ For advanced use cases, the renderCustomToolbar{' '} + prop may be used to take complete control over rendering the + toolbar. This may be useful where custom row layouts (e.g., all + button on the right side) are required. +

+ + ), + demo: , + props: { EuiDataGridCustomToolbarProps }, + }, ], }; diff --git a/src/components/datagrid/controls/display_selector.tsx b/src/components/datagrid/controls/display_selector.tsx index 2eab2cc5aab..339d0d37f36 100644 --- a/src/components/datagrid/controls/display_selector.tsx +++ b/src/components/datagrid/controls/display_selector.tsx @@ -95,7 +95,13 @@ export const useDataGridDisplaySelector = ( showDisplaySelector: EuiDataGridToolBarVisibilityOptions['showDisplaySelector'], initialStyles: EuiDataGridStyle, initialRowHeightsOptions?: EuiDataGridRowHeightsOptions -): [ReactNode, EuiDataGridStyle, EuiDataGridRowHeightsOptions] => { +): [ + ReactNode, + EuiDataGridStyle, + EuiDataGridRowHeightsOptions, + ReactNode, + ReactNode +] => { const [isOpen, setIsOpen] = useState(false); const showDensityControls = getNestedObjectOptions( @@ -108,11 +114,6 @@ export const useDataGridDisplaySelector = ( 'allowRowHeight' ); - const additionalDisplaySettings = - typeof showDisplaySelector === 'boolean' - ? null - : showDisplaySelector?.additionalDisplaySettings ?? null; - // Track styles specified by the user at run time const [userGridStyles, setUserGridStyles] = useState({}); const [userRowHeightsOptions, setUserRowHeightsOptions] = useState({}); @@ -221,6 +222,107 @@ export const useDataGridDisplaySelector = ( 'Reset to default' ); + const rowHeightsControls = ( + + {([ + rowHeightLabel, + labelSingle, + labelAuto, + labelCustom, + lineCountLabel, + ]: string[]) => ( + <> + + + + {rowHeightSelection === rowHeightButtonOptions[2] && ( + + + + )} + + )} + + ); + const densityControls = ( + + {([densityLabel, labelCompact, labelNormal, labelExpanded]: string[]) => ( + + + + )} + + ); + const displaySelector = showDensityControls || showRowHeightControls ? ( } > - {showDensityControls && ( - - {([ - densityLabel, - labelCompact, - labelNormal, - labelExpanded, - ]: string[]) => ( - - - - )} - - )} - {showRowHeightControls && ( - - {([ - rowHeightLabel, - labelSingle, - labelAuto, - labelCustom, - lineCountLabel, - ]: string[]) => ( - <> - - - - {rowHeightSelection === rowHeightButtonOptions[2] && ( - - - - )} - - )} - - )} - {additionalDisplaySettings} - + {showDensityControls && densityControls} + {showRowHeightControls && rowHeightsControls} {showResetButton && ( @@ -382,5 +373,11 @@ export const useDataGridDisplaySelector = ( ) : null; - return [displaySelector, gridStyles, rowHeightsOptions]; + return [ + displaySelector, + gridStyles, + rowHeightsOptions, + rowHeightsControls, + densityControls, + ]; }; diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 92b190a7565..1e64d8b9154 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -129,6 +129,7 @@ export const EuiDataGrid = forwardRef( rowHeightsOptions: _rowHeightsOptions, virtualizationOptions, renderCustomGridBody, + renderCustomToolbar, ...rest } = props; @@ -203,15 +204,20 @@ export const EuiDataGrid = forwardRef( ); }, [columns]); - const [displaySelector, gridStyles, rowHeightsOptions] = - useDataGridDisplaySelector( - checkOrDefaultToolBarDisplayOptions( - toolbarVisibility, - 'showDisplaySelector' - ), - gridStyleWithDefaults, - _rowHeightsOptions - ); + const [ + displaySelector, + gridStyles, + rowHeightsOptions, + rowHeightsControls, + densityControls, + ] = useDataGridDisplaySelector( + checkOrDefaultToolBarDisplayOptions( + toolbarVisibility, + 'showDisplaySelector' + ), + gridStyleWithDefaults, + _rowHeightsOptions + ); /** * Column order & visibility @@ -389,19 +395,36 @@ export const EuiDataGrid = forwardRef( ref={setResizeRef} {...rest} > - {showToolbar && ( - - )} + <> + {showToolbar && + renderCustomToolbar && + renderCustomToolbar({ + gridWidth, + minSizeForControls, + toolbarVisibility, + isFullScreen, + fullScreenSelector, + keyboardShortcuts, + displaySelector, + columnSelector, + columnSorting, + rowHeightsControls, + densityControls, + })} + {showToolbar && !renderCustomToolbar && ( + + )} + {inMemory ? ( ReactNode; + /** + * An optional function called to completely customize and control the rendering of + * EuiDataGrid's toolbar. This can be used to add custom buttons, reorder existing ones. + * + * Behind the scenes, this function is treated as a React component, + * allowing hooks, context, and other React concepts to be used. + * It receives #EuiDataGridCustomBodyProps as its only argument. + */ + renderCustomToolbar?: (args: EuiDataGridCustomToolbarProps) => ReactNode; /** * Defines the initial style of the grid. Accepts a partial #EuiDataGridStyle object. * Settings provided may be overwritten or merged with user defined preferences if `toolbarVisibility.showDisplaySelector.allowDensity = true` (which is the default). @@ -482,6 +491,12 @@ export interface EuiDataGridCustomBodyProps { */ setCustomGridBodyProps: (props: EuiDataGridSetCustomGridBodyProps) => void; } + +export interface EuiDataGridCustomToolbarProps extends EuiDataGridToolbarProps { + rowHeightsControls: ReactNode; + densityControls: ReactNode; +} + export type EuiDataGridSetCustomGridBodyProps = CommonProps & HTMLAttributes & { ref?: MutableRefObject | Ref; From d87d0617dc28c1810ef4a3554a7bdd6563b4be0a Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Thu, 14 Sep 2023 15:06:23 +0200 Subject: [PATCH 03/19] Refactor how `renderCustomToolbar` works --- .../advanced/datagrid_advanced_example.js | 24 -- .../datagrid_custom_toolbar.tsx} | 105 ++++--- .../toolbar/datagrid_toolbar_example.js | 28 +- .../datagrid/controls/data_grid_toolbar.tsx | 146 +++++++--- .../datagrid/controls/display_selector.tsx | 256 +++++++++--------- src/components/datagrid/data_grid.tsx | 67 ++--- src/components/datagrid/data_grid_types.ts | 44 ++- 7 files changed, 365 insertions(+), 305 deletions(-) rename src-docs/src/views/datagrid/{advanced/custom_toolbar.tsx => toolbar/datagrid_custom_toolbar.tsx} (60%) diff --git a/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js b/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js index 861790a37d4..ce49e6dda5a 100644 --- a/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js +++ b/src-docs/src/views/datagrid/advanced/datagrid_advanced_example.js @@ -8,7 +8,6 @@ import { EuiCallOut, EuiTitle, EuiLink, - EuiDataGridCustomToolbarProps, } from '../../../../../src/components'; import { @@ -37,9 +36,7 @@ dataGridRef.current.closeCellPopover(); `; import CustomRenderer from './custom_renderer'; -import CustomToolbarRenderer from './custom_toolbar'; const customRendererSource = require('!!raw-loader!./custom_renderer'); -const customToolbarSource = require('!!raw-loader!./custom_toolbar'); const customRendererSnippet = `const CustomGridBody = ({ visibleColumns, visibleRowData, Cell }) => { const visibleRows = raw_data.slice( visibleRowData.startRow, @@ -256,26 +253,5 @@ export const DataGridAdvancedExample = { snippet: customRendererSnippet, props: { EuiDataGridCustomBodyProps }, }, - { - title: 'Custom toolbar renderer', - source: [ - { - type: GuideSectionTypes.TSX, - code: customToolbarSource, - }, - ], - text: ( - <> -

- For advanced use cases, the renderCustomToolbar{' '} - prop may be used to take complete control over rendering the - toolbar. This may be useful where custom row layouts (e.g., all - button on the right side) are required. -

- - ), - demo: , - props: { EuiDataGridCustomToolbarProps }, - }, ], }; diff --git a/src-docs/src/views/datagrid/advanced/custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx similarity index 60% rename from src-docs/src/views/datagrid/advanced/custom_toolbar.tsx rename to src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx index 915391469b2..00910562550 100644 --- a/src-docs/src/views/datagrid/advanced/custom_toolbar.tsx +++ b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx @@ -4,17 +4,16 @@ import { faker } from '@faker-js/faker'; import { EuiDataGrid, EuiDataGridColumnCellActionProps, - EuiButtonIcon, EuiDataGridPaginationProps, EuiDataGridSorting, EuiDataGridColumnSortingConfig, - EuiPopover, - EuiDataGridCustomToolbarProps, + EuiDataGridToolbarProps, EuiFormRow, EuiRange, } from '../../../../../src'; const raw_data: Array<{ [key: string]: string }> = []; + for (let i = 1; i < 100; i++) { raw_data.push({ name: `${faker.name.lastName()}, ${faker.name.firstName()}`, @@ -87,61 +86,29 @@ export default () => { const onSort = useCallback((sortingColumns) => { setSortingColumns(sortingColumns); }, []); - const [isDisplaySelectorOpen, setIsDisplaySelectorOpen] = useState(false); - // Custom toolbar body renderer - const RenderCustomToolbar = ({ - fullScreenSelector, - keyboardShortcuts, - rowHeightsControls, - densityControls, - columnSelector, - columnSorting, - }: EuiDataGridCustomToolbarProps) => { - return ( -
-
- Always look at the left side of grid! -
-
- {fullScreenSelector} - {keyboardShortcuts} - setIsDisplaySelectorOpen(true)} - /> - } - isOpen={isDisplaySelectorOpen} - data-test-subj="dataGridDisplaySelectorPopover" - closePopover={() => setIsDisplaySelectorOpen(false)} - anchorPosition="downRight" - panelPaddingSize="s" - panelClassName="euiDataGrid__displayPopoverPanel" - > - {rowHeightsControls} - {densityControls} + const [exampleSettingValue, setExampleSettingValue] = useState(10); - - - - - {columnSorting} - {columnSelector} -
-
- ); + // Custom toolbar body renderer + const renderCustomToolbar: EuiDataGridToolbarProps['renderCustomToolbar'] = ({ + columnControl, + columnSortingControl, + displayControl, + fullScreenControl, + keyboardShortcutsControl, + }) => { + return { + leftControls: 'Always look at the left side of grid!', + rightControls: ( + <> + {fullScreenControl} + {keyboardShortcutsControl} + {displayControl} + {columnControl} + {columnSortingControl} + + ), + }; }; return ( @@ -161,9 +128,33 @@ export default () => { renderCellValue={({ rowIndex, columnId }) => raw_data[rowIndex][columnId] } - renderCustomToolbar={RenderCustomToolbar} + renderCustomToolbar={renderCustomToolbar} height={undefined} gridStyle={{ border: 'none', header: 'underline' }} + toolbarVisibility={{ + showDisplaySelector: { + additionalDisplaySettings: ( + + { + setExampleSettingValue(Number(event.currentTarget.value)); + }} + /> + + ), + }, + }} /> ); diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js index 1a36b21cc05..50708a86669 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js +++ b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js @@ -1,7 +1,7 @@ import React, { Fragment } from 'react'; import { GuideSectionTypes } from '../../../components'; -import { EuiCode } from '../../../../../src'; +import { EuiCode, EuiDataGridCustomToolbarProps } from '../../../../../src'; import DataGridToolbarVisibility from './visibility'; const dataGridToolbarVisibilitySource = require('!!raw-loader!./_grid'); @@ -9,6 +9,9 @@ const dataGridToolbarVisibilitySource = require('!!raw-loader!./_grid'); import DataGridControls from './additional_controls'; const dataGridControlsSource = require('!!raw-loader!./additional_controls'); +import DataGridCustomToolbar from './datagrid_custom_toolbar'; +const dataGridCustomToolbarSource = require('!!raw-loader!./datagrid_custom_toolbar'); + import ToolbarPropsTable from './_props'; import { @@ -185,6 +188,29 @@ export const DataGridToolbarExample = { }, demo: , }, + { + title: 'Custom toolbar controls placement', + source: [ + { + type: GuideSectionTypes.TSX, + code: dataGridCustomToolbarSource, + }, + ], + text: ( + <> +

+ For advanced use cases, the renderCustomToolbar{' '} + prop may be used to take complete control over the placement of the + toolbar controls or the whole toolbar element. This may be useful + where custom layout (e.g., all buttons on the right side) are + required. +

+ + ), + demo: , + props: { EuiDataGridCustomToolbarProps }, + // TODO: add a snippet + }, { title: 'Toolbar props', text: ( diff --git a/src/components/datagrid/controls/data_grid_toolbar.tsx b/src/components/datagrid/controls/data_grid_toolbar.tsx index ec043048c61..50a67a86cd0 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.tsx @@ -30,57 +30,119 @@ export const EuiDataGridToolbar = ({ displaySelector, columnSelector, columnSorting, + renderCustomToolbar, }: EuiDataGridToolbarProps) => { // Enables/disables grid controls based on available width const hasRoomForGridControls = IS_JEST_ENVIRONMENT ? true : gridWidth > minSizeForControls || isFullScreen; + const columnControl = checkOrDefaultToolBarDisplayOptions( + toolbarVisibility, + 'showColumnSelector' + ) + ? columnSelector + : null; + const columnSortingControl = checkOrDefaultToolBarDisplayOptions( + toolbarVisibility, + 'showSortSelector' + ) + ? columnSorting + : null; + const keyboardShortcutsControl = checkOrDefaultToolBarDisplayOptions( + toolbarVisibility, + 'showKeyboardShortcuts' + ) ? ( + keyboardShortcuts + ) : ( + + {keyboardShortcuts} + + ); + const displayControl = checkOrDefaultToolBarDisplayOptions( + toolbarVisibility, + 'showDisplaySelector' + ) + ? displaySelector + : null; + const fullScreenControl = checkOrDefaultToolBarDisplayOptions( + toolbarVisibility, + 'showFullScreenSelector' + ) + ? fullScreenSelector + : null; + + if (renderCustomToolbar) { + const customToolbar = renderCustomToolbar({ + gridWidth, + minSizeForControls, + toolbarVisibility, + isFullScreen, + hasRoomForGridControls, + columnControl, + columnSortingControl, + keyboardShortcutsControl, + displayControl, + fullScreenControl, + }); + + if ('leftControls' in customToolbar || 'rightControls' in customToolbar) { + return ( + + ); + } + + return customToolbar.replaceWith ?? null; + } + + return ( + + {renderAdditionalControls(toolbarVisibility, 'left.prepend')} + {columnControl} + {columnSortingControl} + {renderAdditionalControls(toolbarVisibility, 'left.append')} + + ) : null + } + rightControls={ + <> + {renderAdditionalControls(toolbarVisibility, 'right')} + {keyboardShortcutsControl} + {displayControl} + {fullScreenControl} + + } + /> + ); +}; + +/** + * Toolbar container component + * @param leftControls + * @param rightControls + * @constructor + */ +const EuiDataGridToolbarContainer = ({ + leftControls, + rightControls, +}: { + leftControls?: ReactNode; + rightControls?: ReactNode; +}) => { return (
- {hasRoomForGridControls && ( -
- {renderAdditionalControls(toolbarVisibility, 'left.prepend')} - {checkOrDefaultToolBarDisplayOptions( - toolbarVisibility, - 'showColumnSelector' - ) - ? columnSelector - : null} - {checkOrDefaultToolBarDisplayOptions( - toolbarVisibility, - 'showSortSelector' - ) - ? columnSorting - : null} - {renderAdditionalControls(toolbarVisibility, 'left.append')} -
+ {leftControls && ( +
{leftControls}
+ )} + {rightControls && ( +
{rightControls}
)} -
- {renderAdditionalControls(toolbarVisibility, 'right')} - {checkOrDefaultToolBarDisplayOptions( - toolbarVisibility, - 'showKeyboardShortcuts' - ) ? ( - keyboardShortcuts - ) : ( - - {keyboardShortcuts} - - )} - {checkOrDefaultToolBarDisplayOptions( - toolbarVisibility, - 'showDisplaySelector' - ) - ? displaySelector - : null} - {checkOrDefaultToolBarDisplayOptions( - toolbarVisibility, - 'showFullScreenSelector' - ) - ? fullScreenSelector - : null} -
); }; diff --git a/src/components/datagrid/controls/display_selector.tsx b/src/components/datagrid/controls/display_selector.tsx index 339d0d37f36..d282d66b086 100644 --- a/src/components/datagrid/controls/display_selector.tsx +++ b/src/components/datagrid/controls/display_selector.tsx @@ -66,9 +66,6 @@ const convertGridStylesToSelection = (gridStyles: EuiDataGridStyle) => { return ''; }; -// Used to correctly format the icon name for the grid density icon -const capitalizeDensityString = (s: string) => s[0].toUpperCase() + s.slice(1); - // Row height options and utilities const rowHeightButtonOptions: string[] = ['undefined', 'auto', 'lineCount']; const convertRowHeightsOptionsToSelection = ( @@ -95,13 +92,7 @@ export const useDataGridDisplaySelector = ( showDisplaySelector: EuiDataGridToolBarVisibilityOptions['showDisplaySelector'], initialStyles: EuiDataGridStyle, initialRowHeightsOptions?: EuiDataGridRowHeightsOptions -): [ - ReactNode, - EuiDataGridStyle, - EuiDataGridRowHeightsOptions, - ReactNode, - ReactNode -] => { +): [ReactNode, EuiDataGridStyle, EuiDataGridRowHeightsOptions] => { const [isOpen, setIsOpen] = useState(false); const showDensityControls = getNestedObjectOptions( @@ -114,6 +105,16 @@ export const useDataGridDisplaySelector = ( 'allowRowHeight' ); + const allowResetButton = getNestedObjectOptions( + showDisplaySelector, + 'allowResetButton' + ); + + const additionalDisplaySettings = + typeof showDisplaySelector === 'boolean' + ? null + : showDisplaySelector?.additionalDisplaySettings ?? null; + // Track styles specified by the user at run time const [userGridStyles, setUserGridStyles] = useState({}); const [userRowHeightsOptions, setUserRowHeightsOptions] = useState({}); @@ -222,109 +223,10 @@ export const useDataGridDisplaySelector = ( 'Reset to default' ); - const rowHeightsControls = ( - - {([ - rowHeightLabel, - labelSingle, - labelAuto, - labelCustom, - lineCountLabel, - ]: string[]) => ( - <> - - - - {rowHeightSelection === rowHeightButtonOptions[2] && ( - - - - )} - - )} - - ); - const densityControls = ( - - {([densityLabel, labelCompact, labelNormal, labelExpanded]: string[]) => ( - - - - )} - - ); - const displaySelector = - showDensityControls || showRowHeightControls ? ( + showDensityControls || + showRowHeightControls || + additionalDisplaySettings ? ( } > - {showDensityControls && densityControls} - {showRowHeightControls && rowHeightsControls} - {showResetButton && ( + {showDensityControls && ( + + {([ + densityLabel, + labelCompact, + labelNormal, + labelExpanded, + ]: string[]) => ( + + + + )} + + )} + {showRowHeightControls && ( + + {([ + rowHeightLabel, + labelSingle, + labelAuto, + labelCustom, + lineCountLabel, + ]: string[]) => ( + <> + + + + {rowHeightSelection === rowHeightButtonOptions[2] && ( + + + + )} + + )} + + )} + {additionalDisplaySettings} + {allowResetButton && showResetButton && ( @@ -373,11 +381,5 @@ export const useDataGridDisplaySelector = ( ) : null; - return [ - displaySelector, - gridStyles, - rowHeightsOptions, - rowHeightsControls, - densityControls, - ]; + return [displaySelector, gridStyles, rowHeightsOptions]; }; diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 1e64d8b9154..063daebfbf2 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -204,20 +204,15 @@ export const EuiDataGrid = forwardRef( ); }, [columns]); - const [ - displaySelector, - gridStyles, - rowHeightsOptions, - rowHeightsControls, - densityControls, - ] = useDataGridDisplaySelector( - checkOrDefaultToolBarDisplayOptions( - toolbarVisibility, - 'showDisplaySelector' - ), - gridStyleWithDefaults, - _rowHeightsOptions - ); + const [displaySelector, gridStyles, rowHeightsOptions] = + useDataGridDisplaySelector( + checkOrDefaultToolBarDisplayOptions( + toolbarVisibility, + 'showDisplaySelector' + ), + gridStyleWithDefaults, + _rowHeightsOptions + ); /** * Column order & visibility @@ -395,36 +390,20 @@ export const EuiDataGrid = forwardRef( ref={setResizeRef} {...rest} > - <> - {showToolbar && - renderCustomToolbar && - renderCustomToolbar({ - gridWidth, - minSizeForControls, - toolbarVisibility, - isFullScreen, - fullScreenSelector, - keyboardShortcuts, - displaySelector, - columnSelector, - columnSorting, - rowHeightsControls, - densityControls, - })} - {showToolbar && !renderCustomToolbar && ( - - )} - + {showToolbar && ( + + )} {inMemory ? ( ; +/** + * Data Grid Toolbar Props + */ export interface EuiDataGridToolbarProps { gridWidth: number; minSizeForControls?: number; @@ -47,8 +50,30 @@ export interface EuiDataGridToolbarProps { displaySelector: ReactNode; columnSelector: ReactNode; columnSorting: ReactNode; + renderCustomToolbar?: (props: EuiDataGridCustomToolbarProps) => { + // to replace only controls inside the toolbar, use `leftControls` and `rightControls` + leftControls?: ReactNode; + rightControls?: ReactNode; + // to return a completely custom toolbar, use `replaceWith` + replaceWith?: ReactElement; + }; } +/** + * Props which are available for a custom toolbar rendering + */ +export type EuiDataGridCustomToolbarProps = Pick< + EuiDataGridToolbarProps, + 'gridWidth' | 'minSizeForControls' | 'toolbarVisibility' | 'isFullScreen' +> & { + hasRoomForGridControls: boolean; + fullScreenControl: ReactNode; + keyboardShortcutsControl: ReactNode; + displayControl: ReactNode; + columnControl: ReactNode; + columnSortingControl: ReactNode; +}; + export interface EuiDataGridPaginationRendererProps extends EuiDataGridPaginationProps { rowCount: number; @@ -281,14 +306,14 @@ export type CommonGridProps = CommonProps & */ renderCustomGridBody?: (args: EuiDataGridCustomBodyProps) => ReactNode; /** - * An optional function called to completely customize and control the rendering of - * EuiDataGrid's toolbar. This can be used to add custom buttons, reorder existing ones. + * An optional function called to customize placement of controls in EuiDataGrid's toolbar. + * This can be used to add custom buttons, reorder existing ones. * * Behind the scenes, this function is treated as a React component, * allowing hooks, context, and other React concepts to be used. - * It receives #EuiDataGridCustomBodyProps as its only argument. + * It receives #EuiDataGridCustomToolbarProps as its only argument. */ - renderCustomToolbar?: (args: EuiDataGridCustomToolbarProps) => ReactNode; + renderCustomToolbar?: EuiDataGridToolbarProps['renderCustomToolbar']; /** * Defines the initial style of the grid. Accepts a partial #EuiDataGridStyle object. * Settings provided may be overwritten or merged with user defined preferences if `toolbarVisibility.showDisplaySelector.allowDensity = true` (which is the default). @@ -492,11 +517,6 @@ export interface EuiDataGridCustomBodyProps { setCustomGridBodyProps: (props: EuiDataGridSetCustomGridBodyProps) => void; } -export interface EuiDataGridCustomToolbarProps extends EuiDataGridToolbarProps { - rowHeightsControls: ReactNode; - densityControls: ReactNode; -} - export type EuiDataGridSetCustomGridBodyProps = CommonProps & HTMLAttributes & { ref?: MutableRefObject | Ref; @@ -862,7 +882,11 @@ export interface EuiDataGridToolBarVisibilityDisplaySelectorOptions { */ allowRowHeight?: boolean; /** - * If passed an object it will append the additional option to the bottom of the display settings + * When `false`, removes the ability to reset styles to default through the UI + */ + allowResetButton?: boolean; + /** + * If passed a React node it will append the additional option to the bottom of the display settings popover */ additionalDisplaySettings?: ReactNode; } From 8302ccdb4e256cc0d64f87b7a44555a152aae66c Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Thu, 14 Sep 2023 15:39:10 +0200 Subject: [PATCH 04/19] Update tests and docs --- src-docs/src/views/datagrid/toolbar/_grid.js | 9 +- .../src/views/datagrid/toolbar/_props.tsx | 2 + .../toolbar/datagrid_custom_toolbar.tsx | 55 ++++---- .../toolbar/datagrid_toolbar_example.js | 13 +- .../src/views/datagrid/toolbar/visibility.js | 11 ++ .../__snapshots__/data_grid.test.tsx.snap | 8 +- .../display_selector.test.tsx.snap | 2 +- .../controls/data_grid_toolbar.test.tsx | 131 ++++++++---------- .../datagrid/controls/data_grid_toolbar.tsx | 30 ++-- .../controls/display_selector.test.tsx | 7 - src/components/datagrid/data_grid_types.ts | 6 +- 11 files changed, 137 insertions(+), 137 deletions(-) diff --git a/src-docs/src/views/datagrid/toolbar/_grid.js b/src-docs/src/views/datagrid/toolbar/_grid.js index 0d6e8b5d3eb..7b1bf9edc37 100644 --- a/src-docs/src/views/datagrid/toolbar/_grid.js +++ b/src-docs/src/views/datagrid/toolbar/_grid.js @@ -52,6 +52,7 @@ const DataGridStyle = ({ showFullScreenSelector, allowDensity, allowRowHeight, + allowResetButton, allowHideColumns, allowOrderingColumns, }) => { @@ -98,13 +99,15 @@ const DataGridStyle = ({ const toggleDisplaySelector = useMemo(() => { if ( showDisplaySelector === true && - (allowDensity === false || allowRowHeight === false) + (allowDensity === false || + allowRowHeight === false || + allowResetButton === false) ) { - return { allowDensity, allowRowHeight }; + return { allowDensity, allowRowHeight, allowResetButton }; } else { return showDisplaySelector; } - }, [showDisplaySelector, allowDensity, allowRowHeight]); + }, [showDisplaySelector, allowDensity, allowRowHeight, allowResetButton]); const toolbarVisibilityOptions = { showColumnSelector: toggleColumnSelector, diff --git a/src-docs/src/views/datagrid/toolbar/_props.tsx b/src-docs/src/views/datagrid/toolbar/_props.tsx index 87671f9502c..77fc48346a7 100644 --- a/src-docs/src/views/datagrid/toolbar/_props.tsx +++ b/src-docs/src/views/datagrid/toolbar/_props.tsx @@ -13,6 +13,8 @@ const gridSnippets = { showDisplaySelector: `showDisplaySelector: { allowDensity: false; allowRowHeight: false; + allowResetButton: false; + additionalDisplaySettings: ; }`, showSortSelector: 'showSortSelector: false', showFullScreenSelector: 'showFullScreenSelector: false', diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx index 00910562550..58aa9419875 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx +++ b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx @@ -89,8 +89,28 @@ export default () => { const [exampleSettingValue, setExampleSettingValue] = useState(10); - // Custom toolbar body renderer + // Some additional custom settings to show in Display popover + const additionalDisplaySettings = ( + + { + setExampleSettingValue(Number(event.currentTarget.value)); + }} + /> + + ); + + // Custom toolbar renderer const renderCustomToolbar: EuiDataGridToolbarProps['renderCustomToolbar'] = ({ + hasRoomForGridControls, columnControl, columnSortingControl, displayControl, @@ -98,14 +118,16 @@ export default () => { keyboardShortcutsControl, }) => { return { - leftControls: 'Always look at the left side of grid!', - rightControls: ( + left: hasRoomForGridControls + ? 'Always look at the left side of grid!' + : null, + right: ( <> - {fullScreenControl} - {keyboardShortcutsControl} - {displayControl} {columnControl} {columnSortingControl} + {displayControl} + {keyboardShortcutsControl} + {fullScreenControl} ), }; @@ -133,26 +155,7 @@ export default () => { gridStyle={{ border: 'none', header: 'underline' }} toolbarVisibility={{ showDisplaySelector: { - additionalDisplaySettings: ( - - { - setExampleSettingValue(Number(event.currentTarget.value)); - }} - /> - - ), + additionalDisplaySettings, }, }} /> diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js index 50708a86669..dd862e85e04 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js +++ b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js @@ -189,7 +189,7 @@ export const DataGridToolbarExample = { demo: , }, { - title: 'Custom toolbar controls placement', + title: 'Custom toolbar layout', source: [ { type: GuideSectionTypes.TSX, @@ -200,10 +200,13 @@ export const DataGridToolbarExample = { <>

For advanced use cases, the renderCustomToolbar{' '} - prop may be used to take complete control over the placement of the - toolbar controls or the whole toolbar element. This may be useful - where custom layout (e.g., all buttons on the right side) are - required. + prop for EuiDataGrid may be used to take complete + control over the placement of the toolbar controls (by returning{' '} + left and right) or the whole + toolbar element (by returning replaceWith). This + may be useful where custom layout (e.g., all buttons on the right + side) are required. The default individual controls will be + available as function parameters.

), diff --git a/src-docs/src/views/datagrid/toolbar/visibility.js b/src-docs/src/views/datagrid/toolbar/visibility.js index f885a69099e..7f7bf994031 100644 --- a/src-docs/src/views/datagrid/toolbar/visibility.js +++ b/src-docs/src/views/datagrid/toolbar/visibility.js @@ -46,6 +46,7 @@ const DataGrid = () => { const [showDisplaySelector, setShowDisplaySelector] = useState(true); const [allowDensity, setAllowDensity] = useState(true); const [allowRowHeight, setAllowRowHeight] = useState(true); + const [allowResetButton, setAllowResetButton] = useState(true); const [showColumnSelector, setShowColumnSelector] = useState(true); const [allowHideColumns, setAllowHideColumns] = useState(true); const [allowOrderingColumns, setAllowOrderingColumns] = useState(true); @@ -76,6 +77,9 @@ const DataGrid = () => { const onAllowRowHeightChange = (optionId) => { setAllowRowHeight(optionId === 'true'); }; + const onAllowResetButtonChange = (optionId) => { + setAllowResetButton(optionId === 'true'); + }; const onShowKeyboardShortcutsChange = (optionId) => { setShowKeyboardShortcuts(optionId === 'true'); @@ -234,6 +238,12 @@ const DataGrid = () => { onChange: onAllowRowHeightChange, })} +
  • + {createItem('Show reset button', { + idSelected: allowResetButton.toString(), + onChange: onAllowResetButtonChange, + })} +
  • )} @@ -266,6 +276,7 @@ const DataGrid = () => { showFullScreenSelector={showFullScreenSelector} allowDensity={allowDensity} allowRowHeight={allowRowHeight} + allowResetButton={allowResetButton} allowHideColumns={allowHideColumns} allowOrderingColumns={allowOrderingColumns} /> diff --git a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap index b9eacc989f8..85841317fe0 100644 --- a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap +++ b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap @@ -556,7 +556,7 @@ exports[`EuiDataGrid rendering renders additional toolbar controls 1`] = ` aria-hidden="true" class="euiButtonIcon__icon" color="inherit" - data-euiicon-type="tableDensityNormal" + data-euiicon-type="controlsHorizontal" /> @@ -1037,7 +1037,7 @@ exports[`EuiDataGrid rendering renders control columns 1`] = ` aria-hidden="true" class="euiButtonIcon__icon" color="inherit" - data-euiicon-type="tableDensityNormal" + data-euiicon-type="controlsHorizontal" /> @@ -1841,7 +1841,7 @@ exports[`EuiDataGrid rendering renders custom column headers 1`] = ` aria-hidden="true" class="euiButtonIcon__icon" color="inherit" - data-euiicon-type="tableDensityNormal" + data-euiicon-type="controlsHorizontal" /> @@ -2321,7 +2321,7 @@ exports[`EuiDataGrid rendering renders with common and div attributes 1`] = ` aria-hidden="true" class="euiButtonIcon__icon" color="inherit" - data-euiicon-type="tableDensityNormal" + data-euiicon-type="controlsHorizontal" /> diff --git a/src/components/datagrid/controls/__snapshots__/display_selector.test.tsx.snap b/src/components/datagrid/controls/__snapshots__/display_selector.test.tsx.snap index 7666868ca11..d0f36cb5027 100644 --- a/src/components/datagrid/controls/__snapshots__/display_selector.test.tsx.snap +++ b/src/components/datagrid/controls/__snapshots__/display_selector.test.tsx.snap @@ -16,7 +16,7 @@ exports[`useDataGridDisplaySelector displaySelector renders a toolbar button/pop className="euiDataGrid__controlBtn" color="text" data-test-subj="dataGridDisplaySelectorButton" - iconType="tableDensityNormal" + iconType="controlsHorizontal" onClick={[Function]} size="xs" /> diff --git a/src/components/datagrid/controls/data_grid_toolbar.test.tsx b/src/components/datagrid/controls/data_grid_toolbar.test.tsx index 2d7bfa9299f..606f64962c0 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.test.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.test.tsx @@ -32,34 +32,31 @@ describe('EuiDataGridToolbar', () => { const component = shallow(); expect(component).toMatchInlineSnapshot(` -
    -
    -
    - mock column selector -
    -
    - mock column sorting -
    -
    -
    -
    - mock keyboard shortcuts -
    -
    - mock style selector -
    -
    - mock fullscreen selector -
    -
    -
    + +
    + mock column selector +
    +
    + mock column sorting +
    + + } + right={ + +
    + mock keyboard shortcuts +
    +
    + mock style selector +
    +
    + mock fullscreen selector +
    +
    + } + /> `); }); @@ -69,27 +66,22 @@ describe('EuiDataGridToolbar', () => { ); expect(component).toMatchInlineSnapshot(` -
    -
    -
    - - -
    - mock keyboard shortcuts -
    -
    -
    -
    -
    + } + right={ + + + +
    + mock keyboard shortcuts +
    +
    +
    +
    + } + /> `); }); @@ -111,28 +103,25 @@ describe('EuiDataGridToolbar', () => { ); expect(component).toMatchInlineSnapshot(` -
    -
    -
    - hello -
    -
    -
    -
    - world -
    -
    - mock keyboard shortcuts -
    -
    -
    + +
    + hello +
    + + } + right={ + +
    + world +
    +
    + mock keyboard shortcuts +
    +
    + } + /> `); }); }); diff --git a/src/components/datagrid/controls/data_grid_toolbar.tsx b/src/components/datagrid/controls/data_grid_toolbar.tsx index 50a67a86cd0..b1c533489d3 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.tsx @@ -86,11 +86,11 @@ export const EuiDataGridToolbar = ({ fullScreenControl, }); - if ('leftControls' in customToolbar || 'rightControls' in customToolbar) { + if (customToolbar.left || customToolbar.right) { return ( ); } @@ -100,7 +100,7 @@ export const EuiDataGridToolbar = ({ return ( {renderAdditionalControls(toolbarVisibility, 'left.prepend')} @@ -110,7 +110,7 @@ export const EuiDataGridToolbar = ({ ) : null } - rightControls={ + right={ <> {renderAdditionalControls(toolbarVisibility, 'right')} {keyboardShortcutsControl} @@ -124,25 +124,21 @@ export const EuiDataGridToolbar = ({ /** * Toolbar container component - * @param leftControls - * @param rightControls + * @param left + * @param right * @constructor */ const EuiDataGridToolbarContainer = ({ - leftControls, - rightControls, + left, + right, }: { - leftControls?: ReactNode; - rightControls?: ReactNode; + left?: ReactNode; + right?: ReactNode; }) => { return (
    - {leftControls && ( -
    {leftControls}
    - )} - {rightControls && ( -
    {rightControls}
    - )} + {left &&
    {left}
    } + {right &&
    {right}
    }
    ); }; diff --git a/src/components/datagrid/controls/display_selector.test.tsx b/src/components/datagrid/controls/display_selector.test.tsx index dbb3629c83e..cb3ef4cb03b 100644 --- a/src/components/datagrid/controls/display_selector.test.tsx +++ b/src/components/datagrid/controls/display_selector.test.tsx @@ -85,14 +85,7 @@ describe('useDataGridDisplaySelector', () => { component.find('[data-test-subj="compact"]').simulate('change'); expect(getSelection(component)).toEqual('compact'); - // Should have changed the main toolbar icon accordingly closePopover(component); - expect( - component - .find('[data-test-subj="dataGridDisplaySelectorButton"]') - .first() - .prop('iconType') - ).toEqual('tableDensityCompact'); }); it('calls the gridStyles.onDensityChange callback on user change', () => { diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index ca506b7ad19..e724b41c394 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -51,9 +51,9 @@ export interface EuiDataGridToolbarProps { columnSelector: ReactNode; columnSorting: ReactNode; renderCustomToolbar?: (props: EuiDataGridCustomToolbarProps) => { - // to replace only controls inside the toolbar, use `leftControls` and `rightControls` - leftControls?: ReactNode; - rightControls?: ReactNode; + // to replace only controls inside the toolbar, use `left` and `right` + left?: ReactNode; + right?: ReactNode; // to return a completely custom toolbar, use `replaceWith` replaceWith?: ReactElement; }; From f81e2269078884459d8b8ae02913faacb5c9e403 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Thu, 14 Sep 2023 16:25:21 +0200 Subject: [PATCH 05/19] Update example and docs --- .../toolbar/datagrid_custom_toolbar.tsx | 6 ++--- .../toolbar/datagrid_toolbar_example.js | 17 +++++++----- .../datagrid/controls/data_grid_toolbar.tsx | 16 +++++------ src/components/datagrid/data_grid_types.ts | 27 ++++++++++--------- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx index 58aa9419875..711eae3e023 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx +++ b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx @@ -118,15 +118,13 @@ export default () => { keyboardShortcutsControl, }) => { return { - left: hasRoomForGridControls - ? 'Always look at the left side of grid!' - : null, + left: hasRoomForGridControls ? 'Custom left side' : null, right: ( <> {columnControl} {columnSortingControl} - {displayControl} {keyboardShortcutsControl} + {displayControl} {fullScreenControl} ), diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js index dd862e85e04..3af699ecb39 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js +++ b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js @@ -1,7 +1,7 @@ import React, { Fragment } from 'react'; import { GuideSectionTypes } from '../../../components'; -import { EuiCode, EuiDataGridCustomToolbarProps } from '../../../../../src'; +import { EuiCode } from '../../../../../src'; import DataGridToolbarVisibility from './visibility'; const dataGridToolbarVisibilitySource = require('!!raw-loader!./_grid'); @@ -20,6 +20,8 @@ import { EuiDataGridToolBarVisibilityColumnSelectorOptions, EuiDataGridToolBarVisibilityDisplaySelectorOptions, EuiDataGridToolBarAdditionalControlsLeftOptions, + EuiDataGridToolbarProps, + EuiDataGridCustomToolbarOptions, } from '!!prop-loader!../../../../../src/components/datagrid/data_grid_types'; /* eslint-disable local/css-logical-properties */ @@ -203,15 +205,18 @@ export const DataGridToolbarExample = { prop for EuiDataGrid may be used to take complete control over the placement of the toolbar controls (by returning{' '} left and right) or the whole - toolbar element (by returning replaceWith). This - may be useful where custom layout (e.g., all buttons on the right - side) are required. The default individual controls will be - available as function parameters. + toolbar element (by returning a react element). This may be useful + where custom layout (e.g., all buttons on the right side) are + required. The default individual controls will be available as + function parameters.

    ), demo: , - props: { EuiDataGridCustomToolbarProps }, + props: { + EuiDataGridToolbarProps, + EuiDataGridCustomToolbarOptions, + }, // TODO: add a snippet }, { diff --git a/src/components/datagrid/controls/data_grid_toolbar.tsx b/src/components/datagrid/controls/data_grid_toolbar.tsx index b1c533489d3..b554b6d5e93 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.tsx @@ -86,16 +86,16 @@ export const EuiDataGridToolbar = ({ fullScreenControl, }); - if (customToolbar.left || customToolbar.right) { - return ( - - ); + if (isValidElement(customToolbar)) { + return customToolbar; } - return customToolbar.replaceWith ?? null; + return ( + + ); } return ( diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index e724b41c394..517ae6e15f1 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -50,29 +50,30 @@ export interface EuiDataGridToolbarProps { displaySelector: ReactNode; columnSelector: ReactNode; columnSorting: ReactNode; - renderCustomToolbar?: (props: EuiDataGridCustomToolbarProps) => { - // to replace only controls inside the toolbar, use `left` and `right` - left?: ReactNode; - right?: ReactNode; - // to return a completely custom toolbar, use `replaceWith` - replaceWith?: ReactElement; - }; + renderCustomToolbar?: (props: EuiDataGridCustomToolbarOptions) => + | { + // to replace only controls inside the toolbar, use `left` and `right` + left?: ReactNode; + right?: ReactNode; + } + | ReactElement; // to replace the whole toolbar } /** * Props which are available for a custom toolbar rendering */ -export type EuiDataGridCustomToolbarProps = Pick< - EuiDataGridToolbarProps, - 'gridWidth' | 'minSizeForControls' | 'toolbarVisibility' | 'isFullScreen' -> & { +export interface EuiDataGridCustomToolbarOptions { + gridWidth: EuiDataGridToolbarProps['gridWidth']; + toolbarVisibility: EuiDataGridToolbarProps['toolbarVisibility']; + isFullScreen: EuiDataGridToolbarProps['isFullScreen']; + minSizeForControls: number; hasRoomForGridControls: boolean; fullScreenControl: ReactNode; keyboardShortcutsControl: ReactNode; displayControl: ReactNode; columnControl: ReactNode; columnSortingControl: ReactNode; -}; +} export interface EuiDataGridPaginationRendererProps extends EuiDataGridPaginationProps { @@ -311,7 +312,7 @@ export type CommonGridProps = CommonProps & * * Behind the scenes, this function is treated as a React component, * allowing hooks, context, and other React concepts to be used. - * It receives #EuiDataGridCustomToolbarProps as its only argument. + * It receives #EuiDataGridCustomToolbarOptions as its only argument. */ renderCustomToolbar?: EuiDataGridToolbarProps['renderCustomToolbar']; /** From 3061aefce307f58698cbb391da7459598b43742b Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Thu, 14 Sep 2023 17:37:36 +0200 Subject: [PATCH 06/19] Add a changelog --- .../src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx | 1 + upcoming_changelogs/7190.md | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 upcoming_changelogs/7190.md diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx index 711eae3e023..71a4f29e864 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx +++ b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx @@ -153,6 +153,7 @@ export default () => { gridStyle={{ border: 'none', header: 'underline' }} toolbarVisibility={{ showDisplaySelector: { + allowResetButton: false, additionalDisplaySettings, }, }} diff --git a/upcoming_changelogs/7190.md b/upcoming_changelogs/7190.md new file mode 100644 index 00000000000..af02e8640e1 --- /dev/null +++ b/upcoming_changelogs/7190.md @@ -0,0 +1,3 @@ +- Added a new `renderCustomToolbar` prop to `EuiDataGrid`, which allows custom rendering of the toolbar or a custom placement of the default toolbar controls. +- Added a new `allowResetButton` prop to `toolbarVisibility.showDisplaySelector`, which allows to hide "Reset to default" button from the display settings popover. +- Added a new `additionalDisplaySettings` prop to `toolbarVisibility.showDisplaySelector`, which allows render extra settings inside the display settings popover. From 809a2294f18369c866ef8a96c0b768e492cd3cac Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 19 Sep 2023 10:51:33 +0200 Subject: [PATCH 07/19] Update changelog --- upcoming_changelogs/7190.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/upcoming_changelogs/7190.md b/upcoming_changelogs/7190.md index af02e8640e1..eaccad03f5c 100644 --- a/upcoming_changelogs/7190.md +++ b/upcoming_changelogs/7190.md @@ -1,3 +1,4 @@ - Added a new `renderCustomToolbar` prop to `EuiDataGrid`, which allows custom rendering of the toolbar or a custom placement of the default toolbar controls. -- Added a new `allowResetButton` prop to `toolbarVisibility.showDisplaySelector`, which allows to hide "Reset to default" button from the display settings popover. -- Added a new `additionalDisplaySettings` prop to `toolbarVisibility.showDisplaySelector`, which allows render extra settings inside the display settings popover. +- Added a new `allowResetButton` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows to hide "Reset to default" button from the display settings popover. +- Added a new `additionalDisplaySettings` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows to render extra settings inside the display settings popover. +- Replaced the display setting popover icon in `EuiDataGrid` toolbar from `tableDensityCompact`/`tableDensityExpanded`/`tableDensityNormal` with `controlsHorizontal`. From bae0d2ef7211ad172f6b311bad4da15155a443ea Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 19 Sep 2023 10:56:24 +0200 Subject: [PATCH 08/19] Update allowResetButton logic --- .../datagrid/controls/display_selector.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/datagrid/controls/display_selector.tsx b/src/components/datagrid/controls/display_selector.tsx index d282d66b086..4504d61159f 100644 --- a/src/components/datagrid/controls/display_selector.tsx +++ b/src/components/datagrid/controls/display_selector.tsx @@ -192,20 +192,24 @@ export const useDataGridDisplaySelector = ( const [showResetButton, setShowResetButton] = useState(false); useUpdateEffect(() => { - const hasUserChanges = Object.keys(userGridStyles).length > 0; - if (hasUserChanges) setShowResetButton(true); + if (allowResetButton) { + const hasUserChanges = Object.keys(userGridStyles).length > 0; + if (hasUserChanges) setShowResetButton(true); + } const { onChange, ...currentGridStyles } = gridStyles; initialStyles?.onChange?.(currentGridStyles); - }, [userGridStyles]); + }, [userGridStyles, allowResetButton]); useUpdateEffect(() => { - const hasUserChanges = Object.keys(userRowHeightsOptions).length > 0; - if (hasUserChanges) setShowResetButton(true); + if (allowResetButton) { + const hasUserChanges = Object.keys(userRowHeightsOptions).length > 0; + if (hasUserChanges) setShowResetButton(true); + } const { onChange, ...currentRowHeightsOptions } = rowHeightsOptions; initialRowHeightsOptions?.onChange?.(currentRowHeightsOptions); - }, [userRowHeightsOptions]); + }, [userRowHeightsOptions, allowResetButton]); // Allow resetting to initial developer-specified configurations const resetToInitialState = useCallback(() => { @@ -360,7 +364,7 @@ export const useDataGridDisplaySelector = ( )} {additionalDisplaySettings} - {allowResetButton && showResetButton && ( + {showResetButton && ( From 9d93d366634727e8d1b7c0f361167834bd3cf73e Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 19 Sep 2023 10:57:03 +0200 Subject: [PATCH 09/19] Update src/components/datagrid/data_grid_types.ts Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com> --- src/components/datagrid/data_grid_types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index 517ae6e15f1..eff07c2aaff 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -887,7 +887,7 @@ export interface EuiDataGridToolBarVisibilityDisplaySelectorOptions { */ allowResetButton?: boolean; /** - * If passed a React node it will append the additional option to the bottom of the display settings popover + * Allows appending additional content to the bottom of the display settings popover */ additionalDisplaySettings?: ReactNode; } From 315cdca17bed643e0e1399a738e03fda2282f36a Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 19 Sep 2023 10:58:21 +0200 Subject: [PATCH 10/19] Update src/components/datagrid/data_grid_types.ts Co-authored-by: Cee Chen <549407+cee-chen@users.noreply.github.com> --- src/components/datagrid/data_grid_types.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index eff07c2aaff..99049cb12e5 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -37,9 +37,6 @@ import { EuiPopoverProps } from '../popover'; // use this to omit the react-specific class component methods export type ImperativeGridApi = Omit; -/** - * Data Grid Toolbar Props - */ export interface EuiDataGridToolbarProps { gridWidth: number; minSizeForControls?: number; From bbf2d184cba32b2dff36d512a4087bb18ac6add5 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 19 Sep 2023 11:00:04 +0200 Subject: [PATCH 11/19] Rename to `EuiDataGridCustomToolbarProps` --- .../views/datagrid/toolbar/datagrid_toolbar_example.js | 4 ++-- src/components/datagrid/data_grid_types.ts | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js index 3af699ecb39..6b8f172a8b1 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js +++ b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js @@ -21,7 +21,7 @@ import { EuiDataGridToolBarVisibilityDisplaySelectorOptions, EuiDataGridToolBarAdditionalControlsLeftOptions, EuiDataGridToolbarProps, - EuiDataGridCustomToolbarOptions, + EuiDataGridCustomToolbarProps, } from '!!prop-loader!../../../../../src/components/datagrid/data_grid_types'; /* eslint-disable local/css-logical-properties */ @@ -215,7 +215,7 @@ export const DataGridToolbarExample = { demo: , props: { EuiDataGridToolbarProps, - EuiDataGridCustomToolbarOptions, + EuiDataGridCustomToolbarProps, }, // TODO: add a snippet }, diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index 517ae6e15f1..6bf069f4ade 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -37,9 +37,6 @@ import { EuiPopoverProps } from '../popover'; // use this to omit the react-specific class component methods export type ImperativeGridApi = Omit; -/** - * Data Grid Toolbar Props - */ export interface EuiDataGridToolbarProps { gridWidth: number; minSizeForControls?: number; @@ -50,7 +47,7 @@ export interface EuiDataGridToolbarProps { displaySelector: ReactNode; columnSelector: ReactNode; columnSorting: ReactNode; - renderCustomToolbar?: (props: EuiDataGridCustomToolbarOptions) => + renderCustomToolbar?: (props: EuiDataGridCustomToolbarProps) => | { // to replace only controls inside the toolbar, use `left` and `right` left?: ReactNode; @@ -62,7 +59,7 @@ export interface EuiDataGridToolbarProps { /** * Props which are available for a custom toolbar rendering */ -export interface EuiDataGridCustomToolbarOptions { +export interface EuiDataGridCustomToolbarProps { gridWidth: EuiDataGridToolbarProps['gridWidth']; toolbarVisibility: EuiDataGridToolbarProps['toolbarVisibility']; isFullScreen: EuiDataGridToolbarProps['isFullScreen']; @@ -312,7 +309,7 @@ export type CommonGridProps = CommonProps & * * Behind the scenes, this function is treated as a React component, * allowing hooks, context, and other React concepts to be used. - * It receives #EuiDataGridCustomToolbarOptions as its only argument. + * It receives #EuiDataGridCustomToolbarProps as its only argument. */ renderCustomToolbar?: EuiDataGridToolbarProps['renderCustomToolbar']; /** From 67d6eed53c42d99b453f255bfd2729cdc1e9d0e5 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 19 Sep 2023 11:02:42 +0200 Subject: [PATCH 12/19] Reduce the number of available custom toolbar props --- src/components/datagrid/controls/data_grid_toolbar.tsx | 4 ---- src/components/datagrid/data_grid_types.ts | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/components/datagrid/controls/data_grid_toolbar.tsx b/src/components/datagrid/controls/data_grid_toolbar.tsx index b554b6d5e93..31c70206f80 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.tsx @@ -74,10 +74,6 @@ export const EuiDataGridToolbar = ({ if (renderCustomToolbar) { const customToolbar = renderCustomToolbar({ - gridWidth, - minSizeForControls, - toolbarVisibility, - isFullScreen, hasRoomForGridControls, columnControl, columnSortingControl, diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index 6bf069f4ade..7ff3f808b0d 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -60,10 +60,6 @@ export interface EuiDataGridToolbarProps { * Props which are available for a custom toolbar rendering */ export interface EuiDataGridCustomToolbarProps { - gridWidth: EuiDataGridToolbarProps['gridWidth']; - toolbarVisibility: EuiDataGridToolbarProps['toolbarVisibility']; - isFullScreen: EuiDataGridToolbarProps['isFullScreen']; - minSizeForControls: number; hasRoomForGridControls: boolean; fullScreenControl: ReactNode; keyboardShortcutsControl: ReactNode; From 84eb5fd0dac7b3b1896febcf9ec09980563af9f8 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 19 Sep 2023 19:21:10 +0200 Subject: [PATCH 13/19] Simplify return type of `renderCustomToolbar` --- .../toolbar/datagrid_custom_toolbar.tsx | 36 +++-- .../toolbar/datagrid_toolbar_example.js | 12 +- .../controls/data_grid_toolbar.test.tsx | 131 ++++++++++-------- .../datagrid/controls/data_grid_toolbar.tsx | 66 ++------- src/components/datagrid/data_grid_types.ts | 8 +- upcoming_changelogs/7190.md | 2 +- 6 files changed, 117 insertions(+), 138 deletions(-) diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx index 71a4f29e864..29b3d27ce48 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx +++ b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx @@ -10,6 +10,8 @@ import { EuiDataGridToolbarProps, EuiFormRow, EuiRange, + EuiFlexGroup, + EuiFlexItem, } from '../../../../../src'; const raw_data: Array<{ [key: string]: string }> = []; @@ -117,18 +119,28 @@ export default () => { fullScreenControl, keyboardShortcutsControl, }) => { - return { - left: hasRoomForGridControls ? 'Custom left side' : null, - right: ( - <> - {columnControl} - {columnSortingControl} - {keyboardShortcutsControl} - {displayControl} - {fullScreenControl} - - ), - }; + return ( + + + {hasRoomForGridControls && `Custom left side`} + + + + + {columnControl} + {columnSortingControl} + {keyboardShortcutsControl} + {displayControl} + {fullScreenControl} + + + + ); }; return ( diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js index 6b8f172a8b1..50589378441 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js +++ b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js @@ -201,14 +201,12 @@ export const DataGridToolbarExample = { text: ( <>

    - For advanced use cases, the renderCustomToolbar{' '} + For advanced use cases, the renderCustomToolbar prop for EuiDataGrid may be used to take complete - control over the placement of the toolbar controls (by returning{' '} - left and right) or the whole - toolbar element (by returning a react element). This may be useful - where custom layout (e.g., all buttons on the right side) are - required. The default individual controls will be available as - function parameters. + control over the whole toolbar element (by returning a react + element). This may be useful where a custom layout (e.g., all + buttons on the right side) is required. The default individual + controls will be available as function parameters.

    ), diff --git a/src/components/datagrid/controls/data_grid_toolbar.test.tsx b/src/components/datagrid/controls/data_grid_toolbar.test.tsx index 606f64962c0..2d7bfa9299f 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.test.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.test.tsx @@ -32,31 +32,34 @@ describe('EuiDataGridToolbar', () => { const component = shallow(); expect(component).toMatchInlineSnapshot(` - -
    - mock column selector -
    -
    - mock column sorting -
    - - } - right={ - -
    - mock keyboard shortcuts -
    -
    - mock style selector -
    -
    - mock fullscreen selector -
    -
    - } - /> +
    +
    +
    + mock column selector +
    +
    + mock column sorting +
    +
    +
    +
    + mock keyboard shortcuts +
    +
    + mock style selector +
    +
    + mock fullscreen selector +
    +
    +
    `); }); @@ -66,22 +69,27 @@ describe('EuiDataGridToolbar', () => { ); expect(component).toMatchInlineSnapshot(` - } - right={ - - - -
    - mock keyboard shortcuts -
    -
    -
    -
    - } - /> +
    +
    +
    + + +
    + mock keyboard shortcuts +
    +
    +
    +
    +
    `); }); @@ -103,25 +111,28 @@ describe('EuiDataGridToolbar', () => { ); expect(component).toMatchInlineSnapshot(` - -
    - hello -
    - - } - right={ - -
    - world -
    -
    - mock keyboard shortcuts -
    -
    - } - /> +
    +
    +
    + hello +
    +
    +
    +
    + world +
    +
    + mock keyboard shortcuts +
    +
    +
    `); }); }); diff --git a/src/components/datagrid/controls/data_grid_toolbar.tsx b/src/components/datagrid/controls/data_grid_toolbar.tsx index 31c70206f80..f00722d1014 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.tsx @@ -73,7 +73,7 @@ export const EuiDataGridToolbar = ({ : null; if (renderCustomToolbar) { - const customToolbar = renderCustomToolbar({ + return renderCustomToolbar({ hasRoomForGridControls, columnControl, columnSortingControl, @@ -81,60 +81,24 @@ export const EuiDataGridToolbar = ({ displayControl, fullScreenControl, }); - - if (isValidElement(customToolbar)) { - return customToolbar; - } - - return ( - - ); } - return ( - - {renderAdditionalControls(toolbarVisibility, 'left.prepend')} - {columnControl} - {columnSortingControl} - {renderAdditionalControls(toolbarVisibility, 'left.append')} - - ) : null - } - right={ - <> - {renderAdditionalControls(toolbarVisibility, 'right')} - {keyboardShortcutsControl} - {displayControl} - {fullScreenControl} - - } - /> - ); -}; - -/** - * Toolbar container component - * @param left - * @param right - * @constructor - */ -const EuiDataGridToolbarContainer = ({ - left, - right, -}: { - left?: ReactNode; - right?: ReactNode; -}) => { return (
    - {left &&
    {left}
    } - {right &&
    {right}
    } + {hasRoomForGridControls && ( +
    + {renderAdditionalControls(toolbarVisibility, 'left.prepend')} + {columnControl} + {columnSortingControl} + {renderAdditionalControls(toolbarVisibility, 'left.append')} +
    + )} +
    + {renderAdditionalControls(toolbarVisibility, 'right')} + {keyboardShortcutsControl} + {displayControl} + {fullScreenControl} +
    ); }; diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index 71bb7b9a257..340eb8f2780 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -47,13 +47,7 @@ export interface EuiDataGridToolbarProps { displaySelector: ReactNode; columnSelector: ReactNode; columnSorting: ReactNode; - renderCustomToolbar?: (props: EuiDataGridCustomToolbarProps) => - | { - // to replace only controls inside the toolbar, use `left` and `right` - left?: ReactNode; - right?: ReactNode; - } - | ReactElement; // to replace the whole toolbar + renderCustomToolbar?: (props: EuiDataGridCustomToolbarProps) => ReactElement; } /** diff --git a/upcoming_changelogs/7190.md b/upcoming_changelogs/7190.md index eaccad03f5c..d2e715b0ed7 100644 --- a/upcoming_changelogs/7190.md +++ b/upcoming_changelogs/7190.md @@ -1,4 +1,4 @@ -- Added a new `renderCustomToolbar` prop to `EuiDataGrid`, which allows custom rendering of the toolbar or a custom placement of the default toolbar controls. +- Added a new `renderCustomToolbar` prop to `EuiDataGrid`, which allows custom rendering of the toolbar. - Added a new `allowResetButton` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows to hide "Reset to default" button from the display settings popover. - Added a new `additionalDisplaySettings` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows to render extra settings inside the display settings popover. - Replaced the display setting popover icon in `EuiDataGrid` toolbar from `tableDensityCompact`/`tableDensityExpanded`/`tableDensityNormal` with `controlsHorizontal`. From 8500388139dfbf6e0260375bc347d8e90f939293 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Wed, 20 Sep 2023 11:56:44 +0200 Subject: [PATCH 14/19] Add tests --- .../controls/data_grid_toolbar.test.tsx | 30 +++++ .../controls/display_selector.test.tsx | 114 +++++++++++++++--- 2 files changed, 124 insertions(+), 20 deletions(-) diff --git a/src/components/datagrid/controls/data_grid_toolbar.test.tsx b/src/components/datagrid/controls/data_grid_toolbar.test.tsx index 2d7bfa9299f..6299871343e 100644 --- a/src/components/datagrid/controls/data_grid_toolbar.test.tsx +++ b/src/components/datagrid/controls/data_grid_toolbar.test.tsx @@ -135,6 +135,36 @@ describe('EuiDataGridToolbar', () => {
    `); }); + + it('renders custom content if renderCustomToolbar is defined', () => { + const mockRenderCustomToolbar = jest.fn(() => ( +
    Custom
    + )); + const component = shallow( + + ); + + expect(component).toMatchInlineSnapshot(` +
    + Custom +
    + `); + expect(mockRenderCustomToolbar).toHaveBeenCalledWith( + expect.objectContaining({ + hasRoomForGridControls: true, + fullScreenControl: requiredProps.fullScreenSelector, + keyboardShortcutsControl: requiredProps.keyboardShortcuts, + displayControl: requiredProps.displaySelector, + columnControl: requiredProps.columnSelector, + columnSortingControl: requiredProps.columnSorting, + }) + ); + }); }); describe('checkOrDefaultToolBarDisplayOptions', () => { diff --git a/src/components/datagrid/controls/display_selector.test.tsx b/src/components/datagrid/controls/display_selector.test.tsx index cb3ef4cb03b..9ec5e5e800d 100644 --- a/src/components/datagrid/controls/display_selector.test.tsx +++ b/src/components/datagrid/controls/display_selector.test.tsx @@ -402,26 +402,100 @@ describe('useDataGridDisplaySelector', () => { }); }); - it('renders a reset button only when the user changes from the current settings', () => { - const component = mount(); - openPopover(component); - expect( - component.find('[data-test-subj="resetDisplaySelector"]').exists() - ).toBe(false); - - component.find('[data-test-subj="expanded"]').simulate('change'); - component.find('[data-test-subj="auto"]').simulate('change'); - expect( - component.find('[data-test-subj="resetDisplaySelector"]').exists() - ).toBe(true); - - // Should hide the reset button again after it's been clicked - component - .find('button[data-test-subj="resetDisplaySelector"]') - .simulate('click'); - expect( - component.find('[data-test-subj="resetDisplaySelector"]').exists() - ).toBe(false); + describe('reset button', () => { + it('renders a reset button only when the user changes from the current settings', () => { + const component = mount(); + openPopover(component); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(false); + + component.find('[data-test-subj="expanded"]').simulate('change'); + component.find('[data-test-subj="auto"]').simulate('change'); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(true); + + // Should hide the reset button again after it's been clicked + component + .find('button[data-test-subj="resetDisplaySelector"]') + .simulate('click'); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(false); + }); + + it('renders the reset button after the user changed from the current settings and reopened popover', () => { + const component = mount(); + openPopover(component); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(false); + + component.find('[data-test-subj="expanded"]').simulate('change'); + component.find('[data-test-subj="auto"]').simulate('change'); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(true); + + // Should show the reset button again after the popover was reopened + closePopover(component); + openPopover(component); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(true); + }); + + it('hides the reset button even after changes if allowResetButton is false', () => { + const component = mount( + + ); + openPopover(component); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(false); + + component.find('[data-test-subj="expanded"]').simulate('change'); + component.find('[data-test-subj="auto"]').simulate('change'); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(false); + + // Should hide the reset button again after the popover was reopened + closePopover(component); + openPopover(component); + expect( + component.find('[data-test-subj="resetDisplaySelector"]').exists() + ).toBe(false); + }); + }); + + describe('additionalDisplaySettings', () => { + it('renders custom content if additionalDisplaySettings is defined', () => { + const component = mount( + Custom content
    + ), + }} + /> + ); + openPopover(component); + expect(component.find('[data-test-subj="test-custom"]')) + .toMatchInlineSnapshot(` +
    + Custom content +
    + `); + }); }); }); From 747577a82f5a616d9d0882b6781bc32a72d7da9f Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Wed, 20 Sep 2023 14:02:19 +0200 Subject: [PATCH 15/19] Update docs --- .../datagrid/toolbar/datagrid_custom_toolbar.tsx | 4 ++-- .../datagrid/toolbar/datagrid_toolbar_example.js | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx index 29b3d27ce48..ab0bc1824fa 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx +++ b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx @@ -146,7 +146,7 @@ export default () => { return ( <> { renderCellValue={({ rowIndex, columnId }) => raw_data[rowIndex][columnId] } - renderCustomToolbar={renderCustomToolbar} height={undefined} gridStyle={{ border: 'none', header: 'underline' }} + renderCustomToolbar={renderCustomToolbar} toolbarVisibility={{ showDisplaySelector: { allowResetButton: false, diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js index 50589378441..52938c8deef 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js +++ b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js @@ -215,7 +215,19 @@ export const DataGridToolbarExample = { EuiDataGridToolbarProps, EuiDataGridCustomToolbarProps, }, - // TODO: add a snippet + snippet: `
    Custom toolbar content {displayControl}
    } + toolbarVisibility={{ + showDisplaySelector: { + allowResetButton: false, + additionalDisplaySettings:
    Custom settings content
    + } +}} +/>`, }, { title: 'Toolbar props', From 47f061c49c59a3d7256697fcfe2924b340b8763a Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sun, 24 Sep 2023 14:55:16 -0700 Subject: [PATCH 16/19] [PR feedback] very minor copy tweaks --- src/components/datagrid/data_grid_types.ts | 2 +- upcoming_changelogs/7190.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index 340eb8f2780..3935a7c47b8 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -295,7 +295,7 @@ export type CommonGridProps = CommonProps & renderCustomGridBody?: (args: EuiDataGridCustomBodyProps) => ReactNode; /** * An optional function called to customize placement of controls in EuiDataGrid's toolbar. - * This can be used to add custom buttons, reorder existing ones. + * This can be used to add custom buttons or reorder existing ones. * * Behind the scenes, this function is treated as a React component, * allowing hooks, context, and other React concepts to be used. diff --git a/upcoming_changelogs/7190.md b/upcoming_changelogs/7190.md index d2e715b0ed7..2df5c499765 100644 --- a/upcoming_changelogs/7190.md +++ b/upcoming_changelogs/7190.md @@ -1,4 +1,4 @@ - Added a new `renderCustomToolbar` prop to `EuiDataGrid`, which allows custom rendering of the toolbar. -- Added a new `allowResetButton` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows to hide "Reset to default" button from the display settings popover. -- Added a new `additionalDisplaySettings` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows to render extra settings inside the display settings popover. -- Replaced the display setting popover icon in `EuiDataGrid` toolbar from `tableDensityCompact`/`tableDensityExpanded`/`tableDensityNormal` with `controlsHorizontal`. +- Added a new `allowResetButton` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows hiding the "Reset to default" button from the display settings popover. +- Added a new `additionalDisplaySettings` prop to `toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows rendering extra settings inside the display settings popover. +- Updated `EuiDataGrid`'s toolbar display settings button icon From 664377430b3be91dec72507711b5596481dbfb0a Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sun, 24 Sep 2023 15:00:43 -0700 Subject: [PATCH 17/19] [display_selector] Minor test cleanup - Remove now-unnecessary `closePopover()` call - Remove separate reset button test that can be combined with the first test --- .../controls/display_selector.test.tsx | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/components/datagrid/controls/display_selector.test.tsx b/src/components/datagrid/controls/display_selector.test.tsx index 9ec5e5e800d..40dd9910e5c 100644 --- a/src/components/datagrid/controls/display_selector.test.tsx +++ b/src/components/datagrid/controls/display_selector.test.tsx @@ -84,8 +84,6 @@ describe('useDataGridDisplaySelector', () => { expect(getSelection(component)).toEqual('normal'); component.find('[data-test-subj="compact"]').simulate('change'); expect(getSelection(component)).toEqual('compact'); - - closePopover(component); }); it('calls the gridStyles.onDensityChange callback on user change', () => { @@ -416,34 +414,20 @@ describe('useDataGridDisplaySelector', () => { component.find('[data-test-subj="resetDisplaySelector"]').exists() ).toBe(true); - // Should hide the reset button again after it's been clicked - component - .find('button[data-test-subj="resetDisplaySelector"]') - .simulate('click'); - expect( - component.find('[data-test-subj="resetDisplaySelector"]').exists() - ).toBe(false); - }); - - it('renders the reset button after the user changed from the current settings and reopened popover', () => { - const component = mount(); + // Should show the reset button again after the popover was reopened + closePopover(component); openPopover(component); - expect( - component.find('[data-test-subj="resetDisplaySelector"]').exists() - ).toBe(false); - - component.find('[data-test-subj="expanded"]').simulate('change'); - component.find('[data-test-subj="auto"]').simulate('change'); expect( component.find('[data-test-subj="resetDisplaySelector"]').exists() ).toBe(true); - // Should show the reset button again after the popover was reopened - closePopover(component); - openPopover(component); + // Should hide the reset button again after it's been clicked + component + .find('button[data-test-subj="resetDisplaySelector"]') + .simulate('click'); expect( component.find('[data-test-subj="resetDisplaySelector"]').exists() - ).toBe(true); + ).toBe(false); }); it('hides the reset button even after changes if allowResetButton is false', () => { From 2fa8e086597cfc15ff51a21f1426f3eed1765260 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sun, 24 Sep 2023 15:23:40 -0700 Subject: [PATCH 18/19] [PR feedback] Move `additionalDisplaySettings` docs example from main grid example to toolbar docs --- .../src/views/datagrid/basics/datagrid.js | 21 ---------- src-docs/src/views/datagrid/toolbar/_grid.js | 40 +++++++++++++++++-- .../src/views/datagrid/toolbar/visibility.js | 32 +++++++++++++-- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src-docs/src/views/datagrid/basics/datagrid.js b/src-docs/src/views/datagrid/basics/datagrid.js index 70df9dfe53d..9da9bc14ffb 100644 --- a/src-docs/src/views/datagrid/basics/datagrid.js +++ b/src-docs/src/views/datagrid/basics/datagrid.js @@ -23,7 +23,6 @@ import { EuiFlyoutBody, EuiFlyoutFooter, EuiFlyoutHeader, - EuiFormRow, EuiLink, EuiModal, EuiModalBody, @@ -31,7 +30,6 @@ import { EuiModalHeader, EuiModalHeaderTitle, EuiPopover, - EuiRange, EuiScreenReaderOnly, EuiText, EuiTitle, @@ -408,31 +406,12 @@ export default () => { console.log(eventData); }); - const customDisplaySetting = ( - - - - ); return ( { @@ -101,13 +107,39 @@ const DataGridStyle = ({ showDisplaySelector === true && (allowDensity === false || allowRowHeight === false || - allowResetButton === false) + allowResetButton === false || + additionalDisplaySettings) ) { - return { allowDensity, allowRowHeight, allowResetButton }; + const customDisplaySetting = additionalDisplaySettings && ( + + + + ); + return { + allowDensity, + allowRowHeight, + allowResetButton, + additionalDisplaySettings: customDisplaySetting, + }; } else { return showDisplaySelector; } - }, [showDisplaySelector, allowDensity, allowRowHeight, allowResetButton]); + }, [ + showDisplaySelector, + allowDensity, + allowRowHeight, + allowResetButton, + additionalDisplaySettings, + ]); const toolbarVisibilityOptions = { showColumnSelector: toggleColumnSelector, diff --git a/src-docs/src/views/datagrid/toolbar/visibility.js b/src-docs/src/views/datagrid/toolbar/visibility.js index 7f7bf994031..ccbc141e832 100644 --- a/src-docs/src/views/datagrid/toolbar/visibility.js +++ b/src-docs/src/views/datagrid/toolbar/visibility.js @@ -47,6 +47,8 @@ const DataGrid = () => { const [allowDensity, setAllowDensity] = useState(true); const [allowRowHeight, setAllowRowHeight] = useState(true); const [allowResetButton, setAllowResetButton] = useState(true); + const [additionalDisplaySettings, setAdditionalDisplaySettings] = + useState(false); const [showColumnSelector, setShowColumnSelector] = useState(true); const [allowHideColumns, setAllowHideColumns] = useState(true); const [allowOrderingColumns, setAllowOrderingColumns] = useState(true); @@ -80,6 +82,9 @@ const DataGrid = () => { const onAllowResetButtonChange = (optionId) => { setAllowResetButton(optionId === 'true'); }; + const onAdditionalDisplaySettingsChange = (optionId) => { + setAdditionalDisplaySettings(optionId === 'true'); + }; const onShowKeyboardShortcutsChange = (optionId) => { setShowKeyboardShortcuts(optionId === 'true'); @@ -129,13 +134,27 @@ const DataGrid = () => { const toggleDisplaySelector = useMemo(() => { if ( showDisplaySelector === true && - (allowDensity === false || allowRowHeight === false) + (allowDensity === false || + allowRowHeight === false || + allowResetButton === false || + additionalDisplaySettings) ) { - return { allowDensity, allowRowHeight }; + return { + allowDensity, + allowRowHeight, + allowResetButton, + additionalDisplaySettings, + }; } else { return showDisplaySelector; } - }, [showDisplaySelector, allowDensity, allowRowHeight]); + }, [ + showDisplaySelector, + allowDensity, + allowRowHeight, + allowResetButton, + additionalDisplaySettings, + ]); const createItem = (name, buttonProps = {}) => { return ( @@ -244,6 +263,12 @@ const DataGrid = () => { onChange: onAllowResetButtonChange, })} +
  • + {createItem('Additional display settings', { + idSelected: additionalDisplaySettings.toString(), + onChange: onAdditionalDisplaySettingsChange, + })} +
  • )} @@ -277,6 +302,7 @@ const DataGrid = () => { allowDensity={allowDensity} allowRowHeight={allowRowHeight} allowResetButton={allowResetButton} + additionalDisplaySettings={additionalDisplaySettings} allowHideColumns={allowHideColumns} allowOrderingColumns={allowOrderingColumns} /> From ab6e55330f3bcbd58d653d12cf93467df27c21ab Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Sun, 24 Sep 2023 15:59:59 -0700 Subject: [PATCH 19/19] Final docs pass - more docs copy - rename file with prop name - promote caching the various custom elements by pulling them out to top-level `const`s - remove props/extra demo details that aren't relevant to the toolbar --- .../toolbar/datagrid_custom_toolbar.tsx | 175 ------------------ .../toolbar/datagrid_toolbar_example.js | 33 ++-- .../toolbar/render_custom_toolbar.tsx | 136 ++++++++++++++ 3 files changed, 157 insertions(+), 187 deletions(-) delete mode 100644 src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx create mode 100644 src-docs/src/views/datagrid/toolbar/render_custom_toolbar.tsx diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx deleted file mode 100644 index ab0bc1824fa..00000000000 --- a/src-docs/src/views/datagrid/toolbar/datagrid_custom_toolbar.tsx +++ /dev/null @@ -1,175 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import { faker } from '@faker-js/faker'; - -import { - EuiDataGrid, - EuiDataGridColumnCellActionProps, - EuiDataGridPaginationProps, - EuiDataGridSorting, - EuiDataGridColumnSortingConfig, - EuiDataGridToolbarProps, - EuiFormRow, - EuiRange, - EuiFlexGroup, - EuiFlexItem, -} from '../../../../../src'; - -const raw_data: Array<{ [key: string]: string }> = []; - -for (let i = 1; i < 100; i++) { - raw_data.push({ - name: `${faker.name.lastName()}, ${faker.name.firstName()}`, - email: faker.internet.email(), - location: `${faker.address.city()}, ${faker.address.country()}`, - date: `${faker.date.past()}`, - amount: faker.commerce.price(1, 1000, 2, '$'), - }); -} - -const columns = [ - { - id: 'name', - displayAsText: 'Name', - cellActions: [ - ({ Component }: EuiDataGridColumnCellActionProps) => ( - alert('action')} - iconType="faceHappy" - aria-label="Some action" - > - Some action - - ), - ], - }, - { - id: 'email', - displayAsText: 'Email address', - initialWidth: 130, - }, - { - id: 'location', - displayAsText: 'Location', - }, - { - id: 'date', - displayAsText: 'Date', - }, - { - id: 'amount', - displayAsText: 'Amount', - }, -]; - -export default () => { - // Column visibility - const [visibleColumns, setVisibleColumns] = useState(() => - columns.map(({ id }) => id) - ); - - // Pagination - const [pagination, setPagination] = useState({ pageIndex: 0 }); - const onChangePage = useCallback( - (pageIndex) => { - setPagination((pagination) => ({ ...pagination, pageIndex })); - }, - [] - ); - const onChangePageSize = useCallback< - EuiDataGridPaginationProps['onChangeItemsPerPage'] - >((pageSize) => { - setPagination((pagination) => ({ ...pagination, pageSize })); - }, []); - - // Sorting - const [sortingColumns, setSortingColumns] = useState< - EuiDataGridColumnSortingConfig[] - >([]); - const onSort = useCallback((sortingColumns) => { - setSortingColumns(sortingColumns); - }, []); - - const [exampleSettingValue, setExampleSettingValue] = useState(10); - - // Some additional custom settings to show in Display popover - const additionalDisplaySettings = ( - - { - setExampleSettingValue(Number(event.currentTarget.value)); - }} - /> - - ); - - // Custom toolbar renderer - const renderCustomToolbar: EuiDataGridToolbarProps['renderCustomToolbar'] = ({ - hasRoomForGridControls, - columnControl, - columnSortingControl, - displayControl, - fullScreenControl, - keyboardShortcutsControl, - }) => { - return ( - - - {hasRoomForGridControls && `Custom left side`} - - - - - {columnControl} - {columnSortingControl} - {keyboardShortcutsControl} - {displayControl} - {fullScreenControl} - - - - ); - }; - - return ( - <> - - raw_data[rowIndex][columnId] - } - height={undefined} - gridStyle={{ border: 'none', header: 'underline' }} - renderCustomToolbar={renderCustomToolbar} - toolbarVisibility={{ - showDisplaySelector: { - allowResetButton: false, - additionalDisplaySettings, - }, - }} - /> - - ); -}; diff --git a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js index 52938c8deef..9998f094434 100644 --- a/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js +++ b/src-docs/src/views/datagrid/toolbar/datagrid_toolbar_example.js @@ -9,8 +9,8 @@ const dataGridToolbarVisibilitySource = require('!!raw-loader!./_grid'); import DataGridControls from './additional_controls'; const dataGridControlsSource = require('!!raw-loader!./additional_controls'); -import DataGridCustomToolbar from './datagrid_custom_toolbar'; -const dataGridCustomToolbarSource = require('!!raw-loader!./datagrid_custom_toolbar'); +import DataGridCustomToolbar from './render_custom_toolbar'; +const dataGridCustomToolbarSource = require('!!raw-loader!./render_custom_toolbar'); import ToolbarPropsTable from './_props'; @@ -20,7 +20,6 @@ import { EuiDataGridToolBarVisibilityColumnSelectorOptions, EuiDataGridToolBarVisibilityDisplaySelectorOptions, EuiDataGridToolBarAdditionalControlsLeftOptions, - EuiDataGridToolbarProps, EuiDataGridCustomToolbarProps, } from '!!prop-loader!../../../../../src/components/datagrid/data_grid_types'; @@ -191,7 +190,7 @@ export const DataGridToolbarExample = { demo: , }, { - title: 'Custom toolbar layout', + title: 'Completely custom toolbar rendering', source: [ { type: GuideSectionTypes.TSX, @@ -201,18 +200,28 @@ export const DataGridToolbarExample = { text: ( <>

    - For advanced use cases, the renderCustomToolbar - prop for EuiDataGrid may be used to take complete - control over the whole toolbar element (by returning a react - element). This may be useful where a custom layout (e.g., all - buttons on the right side) is required. The default individual - controls will be available as function parameters. + If more customized control over the toolbar is required than{' '} + toolbarVisibility or{' '} + additionalControls allows, you can use the{' '} + renderCustomToolbar prop to pass a component. The + default datagrid controls are passed back as parameters for optional + usage. +

    +

    + renderCustomToolbar should only be used when a + very custom layout (e.g. moving default buttons between sides, + interspering custom controls between default controls, custom + responsive behavior, etc.) is required. We would caution you to keep + consistency in mind also when customizing the toolbar: if using + multiple datagrid instances across your app, users will typically + want to reach for the same controls for each grid. Changing the + available controls inconsistently across your app may result in user + frustration.

    ), demo: , props: { - EuiDataGridToolbarProps, EuiDataGridCustomToolbarProps, }, snippet: `Custom settings content } -}} + }} />`, }, { diff --git a/src-docs/src/views/datagrid/toolbar/render_custom_toolbar.tsx b/src-docs/src/views/datagrid/toolbar/render_custom_toolbar.tsx new file mode 100644 index 00000000000..6f32b3a895a --- /dev/null +++ b/src-docs/src/views/datagrid/toolbar/render_custom_toolbar.tsx @@ -0,0 +1,136 @@ +import React, { useCallback, useState } from 'react'; +import { css } from '@emotion/react'; +import { faker } from '@faker-js/faker'; + +import { + EuiDataGrid, + EuiDataGridSorting, + EuiDataGridColumnSortingConfig, + EuiDataGridToolbarProps, + EuiButtonEmpty, + EuiFormRow, + EuiRange, + EuiFlexGroup, + EuiFlexItem, + euiScreenReaderOnly, +} from '../../../../../src'; + +const raw_data: Array<{ [key: string]: string }> = []; +for (let i = 0; i < 5; i++) { + raw_data.push({ + name: `${faker.person.lastName()}, ${faker.person.firstName()}`, + email: faker.internet.email(), + location: `${faker.location.city()}, ${faker.location.country()}`, + date: `${faker.date.past()}`, + amount: faker.commerce.price({ min: 1, max: 1000, dec: 2, symbol: '$' }), + }); +} +const columns = [ + { id: 'name', displayAsText: 'Name' }, + { id: 'email', displayAsText: 'Email address' }, + { id: 'location', displayAsText: 'Location' }, + { id: 'date', displayAsText: 'Date' }, + { id: 'amount', displayAsText: 'Amount' }, +]; + +// Custom toolbar renderer +const renderCustomToolbar: EuiDataGridToolbarProps['renderCustomToolbar'] = ({ + hasRoomForGridControls, + columnControl, + columnSortingControl, + displayControl, + fullScreenControl, + keyboardShortcutsControl, +}) => { + const mobileStyles = + !hasRoomForGridControls && + css` + .euiDataGrid__controlBtn .euiButtonEmpty__text { + ${euiScreenReaderOnly()} + } + `; + return ( + + + {hasRoomForGridControls && ( + + Custom left side + + )} + + + + + {columnControl} + {columnSortingControl} + {keyboardShortcutsControl} + {displayControl} + {fullScreenControl} + + + + ); +}; + +// Some additional custom settings to show in the Display popover +const AdditionalDisplaySettings = () => { + const [exampleSettingValue, setExampleSettingValue] = useState(10); + + return ( + + { + setExampleSettingValue(Number(event.currentTarget.value)); + }} + /> + + ); +}; + +export default () => { + // Column visibility + const [visibleColumns, setVisibleColumns] = useState(() => + columns.map(({ id }) => id) + ); + + // Sorting + const [sortingColumns, setSortingColumns] = useState< + EuiDataGridColumnSortingConfig[] + >([]); + const onSort = useCallback((sortingColumns) => { + setSortingColumns(sortingColumns); + }, []); + + return ( + raw_data[rowIndex][columnId]} + gridStyle={{ border: 'none', header: 'underline' }} + renderCustomToolbar={renderCustomToolbar} + toolbarVisibility={{ + showDisplaySelector: { + allowResetButton: false, + additionalDisplaySettings: , + }, + }} + /> + ); +};