diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Custom_Row_Heights.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Custom_Row_Heights.png deleted file mode 100644 index c47421ba06f..00000000000 Binary files a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Custom_Row_Heights.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Height_Line_Count.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Height_Line_Count.png deleted file mode 100644 index 17b889f1a9b..00000000000 Binary files a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Height_Line_Count.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Row_Height.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Row_Height.png deleted file mode 100644 index 9543bc4e2f4..00000000000 Binary files a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Row_Height.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Additional_Controls.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Additional_Controls.png deleted file mode 100644 index 1626f0bfd50..00000000000 Binary files a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Additional_Controls.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Render_Custom_Toolbar.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Render_Custom_Toolbar.png deleted file mode 100644 index 639e1b020ab..00000000000 Binary files a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Render_Custom_Toolbar.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Compact.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Compact.png new file mode 100644 index 00000000000..b8f595ce4d5 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Compact.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Expanded.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Expanded.png new file mode 100644 index 00000000000..a12ed9f8ff6 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Expanded.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Horizontal_Lines.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Horizontal_Lines.png new file mode 100644 index 00000000000..7f0f6167c70 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Horizontal_Lines.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Minimal.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Minimal.png new file mode 100644 index 00000000000..57cebef1779 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Minimal.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Playground.png new file mode 100644 index 00000000000..eaca7f7d40e Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_gridStyle_prop_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Auto.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Auto.png new file mode 100644 index 00000000000..519a711cdb0 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Auto.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Line_Height.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Line_Height.png new file mode 100644 index 00000000000..acfa299bcaf Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Line_Height.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Row_Heights.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Row_Heights.png new file mode 100644 index 00000000000..709c3af0c56 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Row_Heights.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Line_Count.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Line_Count.png new file mode 100644 index 00000000000..8dbb2989928 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Line_Count.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Static_Height.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Static_Height.png new file mode 100644 index 00000000000..d50be883a62 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Static_Height.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Additional_Controls_Options.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Additional_Controls_Options.png new file mode 100644 index 00000000000..7e6ea43cd60 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Additional_Controls_Options.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Selector.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Selector.png similarity index 100% rename from packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Selector.png rename to packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Selector.png diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Sorting.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Sorting.png similarity index 100% rename from packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Sorting.png rename to packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Sorting.png diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Display_Selector.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Display_Selector.png similarity index 100% rename from packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Display_Selector.png rename to packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Display_Selector.png diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Full_Screen_Toggle.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Full_Screen_Toggle.png similarity index 100% rename from packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Full_Screen_Toggle.png rename to packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Full_Screen_Toggle.png diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Keyboard_Shortcuts.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Keyboard_Shortcuts.png similarity index 100% rename from packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_Toolbar_Controls_Keyboard_Shortcuts.png rename to packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Keyboard_Shortcuts.png diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_No_Toolbar.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_No_Toolbar.png new file mode 100644 index 00000000000..8a644dcca6d Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_No_Toolbar.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Render_Custom_Toolbar.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Render_Custom_Toolbar.png new file mode 100644 index 00000000000..e38564eaaea Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Render_Custom_Toolbar.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Toolbar_Visibility_Options.png b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Toolbar_Visibility_Options.png new file mode 100644 index 00000000000..74ac8382e85 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Toolbar_Visibility_Options.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Custom_Row_Heights.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Custom_Row_Heights.png deleted file mode 100644 index 766b45e81a8..00000000000 Binary files a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Custom_Row_Heights.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Height_Line_Count.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Height_Line_Count.png deleted file mode 100644 index 9cdaa3ee10a..00000000000 Binary files a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Height_Line_Count.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Row_Height.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Row_Height.png deleted file mode 100644 index b4bdb81c1e3..00000000000 Binary files a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Row_Height.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Additional_Controls.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Additional_Controls.png deleted file mode 100644 index a36901faeaa..00000000000 Binary files a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Additional_Controls.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Render_Custom_Toolbar.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Render_Custom_Toolbar.png deleted file mode 100644 index b05d01c489b..00000000000 Binary files a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Render_Custom_Toolbar.png and /dev/null differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Virtualization.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Virtualization.png index 13780c65549..c9131c140d6 100644 Binary files a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Virtualization.png and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Virtualization.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Compact.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Compact.png new file mode 100644 index 00000000000..abf53f03899 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Compact.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Expanded.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Expanded.png new file mode 100644 index 00000000000..fec1775e3c1 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Expanded.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Horizontal_Lines.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Horizontal_Lines.png new file mode 100644 index 00000000000..6f895cd7908 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Horizontal_Lines.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Minimal.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Minimal.png new file mode 100644 index 00000000000..a75c43c328f Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Minimal.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Playground.png new file mode 100644 index 00000000000..9514e96ba46 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_gridStyle_prop_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Auto.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Auto.png new file mode 100644 index 00000000000..fc30b4d1935 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Auto.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Line_Height.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Line_Height.png new file mode 100644 index 00000000000..897d9acac4e Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Line_Height.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Row_Heights.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Row_Heights.png new file mode 100644 index 00000000000..be44c79b2f9 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Custom_Row_Heights.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Line_Count.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Line_Count.png new file mode 100644 index 00000000000..c114eb435da Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Line_Count.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Static_Height.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Static_Height.png new file mode 100644 index 00000000000..211b81490ed Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_rowHeightsOptions_prop_Static_Height.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Additional_Controls_Options.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Additional_Controls_Options.png new file mode 100644 index 00000000000..f8161979187 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Additional_Controls_Options.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Selector.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Selector.png similarity index 100% rename from packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Selector.png rename to packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Selector.png diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Sorting.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Sorting.png similarity index 100% rename from packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Column_Sorting.png rename to packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Column_Sorting.png diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Display_Selector.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Display_Selector.png similarity index 100% rename from packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Display_Selector.png rename to packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Display_Selector.png diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Full_Screen_Toggle.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Full_Screen_Toggle.png similarity index 100% rename from packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Full_Screen_Toggle.png rename to packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Full_Screen_Toggle.png diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Keyboard_Shortcuts.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Keyboard_Shortcuts.png similarity index 100% rename from packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_Toolbar_Controls_Keyboard_Shortcuts.png rename to packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Keyboard_Shortcuts.png diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_No_Toolbar.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_No_Toolbar.png new file mode 100644 index 00000000000..d726f673d2c Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_No_Toolbar.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Render_Custom_Toolbar.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Render_Custom_Toolbar.png new file mode 100644 index 00000000000..3ba4b007c46 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Render_Custom_Toolbar.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Toolbar_Visibility_Options.png b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Toolbar_Visibility_Options.png new file mode 100644 index 00000000000..bd3e3f70dfb Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Tabular_Content_EuiDataGrid_toolbarVisibility_prop_Toolbar_Visibility_Options.png differ diff --git a/packages/eui/.storybook/addons/code-snippet/constants.ts b/packages/eui/.storybook/addons/code-snippet/constants.ts index 3b1f8c4b8db..a9bdb921cb2 100644 --- a/packages/eui/.storybook/addons/code-snippet/constants.ts +++ b/packages/eui/.storybook/addons/code-snippet/constants.ts @@ -38,8 +38,6 @@ export const EXCLUDED_PROPS = new Set([ EMOTION_LABEL_KEY, 'key', ]); -// props with 'false' value that should not be removed but shown in the code snippet -export const PRESERVED_FALSE_VALUE_PROPS = new Set(['grow']); /** ERRORS */ export const ADDON_ERROR = diff --git a/packages/eui/.storybook/addons/code-snippet/decorators/jsx_decorator.tsx b/packages/eui/.storybook/addons/code-snippet/decorators/jsx_decorator.tsx index fb36bddfc01..f05addfca80 100644 --- a/packages/eui/.storybook/addons/code-snippet/decorators/jsx_decorator.tsx +++ b/packages/eui/.storybook/addons/code-snippet/decorators/jsx_decorator.tsx @@ -126,11 +126,11 @@ export const customJsxDecorator = ( for (const key of Object.keys(context.args)) { // checks story args for: - // - remove if no value - // - remove if `chidlren` + // - remove if no value (but allow `false`) + // - remove if `children` // - remove if arg is a default prop if ( - !context.args[key] || + context.args[key] == null || key === 'children' || defaultProps?.includes(key) ) { diff --git a/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx b/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx index 6a9c8225792..2ba41fef6fb 100644 --- a/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx +++ b/packages/eui/.storybook/addons/code-snippet/decorators/render_jsx.tsx @@ -20,11 +20,7 @@ import { getDocgenSection } from '@storybook/docs-tools'; import { logger } from '@storybook/client-logger'; import { UseEuiTheme } from '../../../../src/services'; -import { - ADDON_PARAMETER_KEY, - EXCLUDED_PROPS, - PRESERVED_FALSE_VALUE_PROPS, -} from '../constants'; +import { ADDON_PARAMETER_KEY, EXCLUDED_PROPS } from '../constants'; import { getStoryComponentDisplayName, getEmotionComponentDisplayName, @@ -135,6 +131,7 @@ export const renderJsx = ( sortProps: true, // using any type here as component props can have any type filterProps: (value: any, key: string) => { + // Note that false values should be allowed, and handled by `removeDefaultProps` if ( EXCLUDED_PROPS.has(key) || value == null || @@ -145,12 +142,6 @@ export const renderJsx = ( return false; } - // manually filter props with `false` values as this allows us to preserve - // `false` values where required e.g. grow={false} - if (value === false && !PRESERVED_FALSE_VALUE_PROPS.has(key)) { - return false; - } - return true; }, }; diff --git a/packages/eui/changelogs/upcoming/8006.md b/packages/eui/changelogs/upcoming/8006.md new file mode 100644 index 00000000000..15f5b0dd142 --- /dev/null +++ b/packages/eui/changelogs/upcoming/8006.md @@ -0,0 +1,11 @@ +**CSS-in-JS conversions** + +- Converted `EuiDataGrid`'s `gridStyle`s to Emotion; Removed the following Sass variables and mixins: + - `$euiDataGridCellPaddingS` + - `$euiDataGridCellPaddingM` + - `$euiDataGridCellPaddingL` + - `$euiDataGridVerticalBorder` + - `$euiDataGridPrefix` + - `$euiDataGridStyles` + - `@euiDataGridSelector` + - `@euiDataGridStyles` diff --git a/packages/eui/scripts/compile-eui.js b/packages/eui/scripts/compile-eui.js index cda2d448953..6d37b257731 100755 --- a/packages/eui/scripts/compile-eui.js +++ b/packages/eui/scripts/compile-eui.js @@ -14,6 +14,8 @@ const IGNORE_TESTS = [ '**/*.spec.tsx', '**/*.stories.ts', '**/*.stories.tsx', + '**/**.stories.utils.ts', + '**/**.stories.utils.tsx', '**/*.mdx', '**/test/internal/**/*.ts', '**/test/internal/**/*.tsx', @@ -24,9 +26,7 @@ const IGNORE_TESTENV = [ '**/*.testenv.tsx', '**/*.testenv.ts', ]; -const IGNORE_PACKAGES = [ - '**/react-datepicker/test/**/*.js', -]; +const IGNORE_PACKAGES = ['**/react-datepicker/test/**/*.js']; function compileLib() { shell.mkdir('-p', 'lib/services', 'lib/test'); diff --git a/packages/eui/src-docs/src/views/datagrid/schema_columns/footer_row.js b/packages/eui/src-docs/src/views/datagrid/schema_columns/footer_row.js index fa99d4af307..ba09441a03c 100644 --- a/packages/eui/src-docs/src/views/datagrid/schema_columns/footer_row.js +++ b/packages/eui/src-docs/src/views/datagrid/schema_columns/footer_row.js @@ -6,8 +6,7 @@ import { EuiCheckbox, EuiButtonIcon, EuiSwitch, - EuiFlexGroup, - EuiFlexItem, + EuiSpacer, } from '../../../../../src'; const raw_data = []; @@ -151,44 +150,41 @@ export default () => { ); // Footer row - const [showFooterRow, setShowFooterRow] = useState(true); + const [stickyFooter, setStickyFooter] = useState(true); return ( - - - setShowFooterRow(e.target.checked)} - /> - - - { - console.log(eventData); - }} - gridStyle={{ - border: 'horizontal', - rowHover: 'highlight', - header: 'underline', - }} - /> - - + <> + setStickyFooter(e.target.checked)} + /> + + { + console.log(eventData); + }} + gridStyle={{ + stickyFooter, + border: 'none', + rowHover: 'highlight', + header: 'underline', + }} + /> + ); }; diff --git a/packages/eui/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/packages/eui/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap index c094a70d194..f8c9392d33e 100644 --- a/packages/eui/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap +++ b/packages/eui/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap @@ -461,7 +461,7 @@ exports[`EuiDataGrid rendering renders additional toolbar controls 1`] = ` data-focus-lock-disabled="disabled" >
@@ -870,7 +870,7 @@ exports[`EuiDataGrid rendering renders control columns 1`] = ` data-focus-lock-disabled="disabled" >
@@ -1473,7 +1473,7 @@ exports[`EuiDataGrid rendering renders custom column headers 1`] = ` data-focus-lock-disabled="disabled" >
@@ -1881,7 +1881,7 @@ exports[`EuiDataGrid rendering renders with common and div attributes 1`] = ` data-focus-lock-disabled="disabled" >
diff --git a/packages/eui/src/components/datagrid/_data_grid_data_row.scss b/packages/eui/src/components/datagrid/_data_grid_data_row.scss index 944527dda01..fb332b7cbfa 100644 --- a/packages/eui/src/components/datagrid/_data_grid_data_row.scss +++ b/packages/eui/src/components/datagrid/_data_grid_data_row.scss @@ -1,27 +1,13 @@ -.euiDataGridRow { - background-color: $euiColorEmptyShade; -} - @include euiDataGridRowCell { position: relative; // Needed for .euiDataGridRowCell__actions - border-right: $euiDataGridVerticalBorder; - border-bottom: $euiBorderThin; .euiDataGridRowCell__content { - @include euiFontSizeS; - padding: $euiDataGridCellPaddingM; height: 100%; overflow: hidden; &--autoHeight { height: auto; } - - // Workaround to trim line-clamp and padding - @see https://github.com/elastic/eui/issues/7780 - &--lineCountHeight { - padding-bottom: 0; - border-bottom: $euiDataGridCellPaddingM solid transparent; - } } // Hack to allow focus trap to still stretch to full row height on defined heights @@ -29,14 +15,6 @@ height: 100%; } - &.euiDataGridRowCell--firstColumn { - border-left: $euiBorderThin; - } - - &.euiDataGridRowCell--lastColumn { - border-right-color: $euiBorderColor; - } - --euiDataGridCellOutlineColor: #{$euiColorPrimary}; &:hover, @@ -220,78 +198,6 @@ } } -// Row stripes -@include euiDataGridStyles(stripes) { - .euiDataGridRow--striped { - background-color: $euiColorLightestShade; - } -} - -// Row highlights -@include euiDataGridStyles(rowHoverHighlight) { - .euiDataGridRow:hover { - background-color: $euiColorHighlight; - } -} - -// Border alternates -@include euiDataGridStyles(bordersNone) { - @include euiDataGridRowCell { - border-color: transparent !important; // stylelint-disable-line declaration-no-important - } -} - -@include euiDataGridStyles(bordersHorizontal) { - @include euiDataGridRowCell { - border-right-color: transparent; - border-left-color: transparent; - } -} - -// Font alternates -@include euiDataGridStyles(fontSizeSmall) { - @include euiDataGridRowCell { - .euiDataGridRowCell__content { - @include euiFontSizeXS; - } - } -} - -@include euiDataGridStyles(fontSizeLarge) { - @include euiDataGridRowCell { - .euiDataGridRowCell__content { - @include euiFontSize; - } - } -} - -// Padding alternates -@include euiDataGridStyles(paddingSmall) { - @include euiDataGridRowCell { - .euiDataGridRowCell__content { - padding: $euiDataGridCellPaddingS; - - &--lineCountHeight { - padding-bottom: 0; - border-bottom: $euiDataGridCellPaddingS solid transparent; - } - } - } -} - -@include euiDataGridStyles(paddingLarge) { - @include euiDataGridRowCell { - .euiDataGridRowCell__content { - padding: $euiDataGridCellPaddingL; - - &--lineCountHeight { - padding-bottom: 0; - border-bottom: $euiDataGridCellPaddingL solid transparent; - } - } - } -} - @keyframes euiDataGridCellActionsSlideIn { from { transform: scaleY(0); } to { transform: scaleY(1); } diff --git a/packages/eui/src/components/datagrid/_mixins.scss b/packages/eui/src/components/datagrid/_mixins.scss index 8952750a738..072c317cb84 100644 --- a/packages/eui/src/components/datagrid/_mixins.scss +++ b/packages/eui/src/components/datagrid/_mixins.scss @@ -1,49 +1,3 @@ -$euiDataGridPrefix: '.euiDataGrid--'; - -// Things can get nesty so it's nice to have an approved list that match our typings -$euiDataGridStyles: ( - 'bordersAll' - 'bordersNone' - 'bordersHorizontal' - 'paddingSmall' - 'paddingMedium' - 'paddingLarge' - 'stripes' - 'rowHoverNone' - 'rowHoverHighlight' - 'headerShade' - 'headerUnderline' - 'footerShade' - 'footerOverline' - 'fontSizeSmall' - 'fontSizeLarge' - 'noControls' - 'stickyFooter' -); - -// All this does is take some of the above and make a sibling selector -// selector(headerShade, fontSizeLarge) -// will produce `.euiDataGrid--headerShade.euiDataGrid--fontSizeLarge -@function euiDataGridSelector($selectorKeys...) { - $selectorList: ''; - @each $selector in $selectorKeys { - // Spit out warnings when you make typos! - @if (index($euiDataGridStyles, $selector != true)) { - @error '#{$selector} is not an allowed value in the euiDataGridStyles() mixin'; - } - $selctorValue: #{$euiDataGridPrefix}#{$selector}; - $selectorList: str-insert($selectorList, $selctorValue, 1000); - } - - @return $selectorList; -} - -@mixin euiDataGridStyles($selectorKeys...) { - #{euiDataGridSelector($selectorKeys...)} { - @content; - } -} - @mixin euiDataGridHeaderCell { .euiDataGridHeaderCell { @content; diff --git a/packages/eui/src/components/datagrid/_variables.scss b/packages/eui/src/components/datagrid/_variables.scss index 58c1358b59e..d7cfaa343a1 100644 --- a/packages/eui/src/components/datagrid/_variables.scss +++ b/packages/eui/src/components/datagrid/_variables.scss @@ -1,8 +1,3 @@ $euiZDataGridCellPopover: $euiZHeader; // Same z-index as EuiFlyout mask overlays - cell popovers should be under both modal and flyout overlays $euiDataGridColumnResizerWidth: 3px; // Odd number because it straddles a border - -$euiDataGridCellPaddingS: $euiSizeXS; -$euiDataGridCellPaddingM: $euiSizeM / 2; -$euiDataGridCellPaddingL: $euiSizeS; -$euiDataGridVerticalBorder: solid 1px tintOrShade($euiBorderColor, 60%, 30%); diff --git a/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap b/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap index 323f16ab4d3..269852fce17 100644 --- a/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap +++ b/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_custom.test.tsx.snap @@ -5,7 +5,7 @@ exports[`EuiDataGridBodyCustomRender treats \`renderCustomGridBody\` as a render class="euiDataGrid__customRenderBody" >
diff --git a/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_virtualized.test.tsx.snap b/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_virtualized.test.tsx.snap index 376e3b6c95d..8c086c03922 100644 --- a/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_virtualized.test.tsx.snap +++ b/packages/eui/src/components/datagrid/body/__snapshots__/data_grid_body_virtualized.test.tsx.snap @@ -9,7 +9,7 @@ exports[`EuiDataGridBodyVirtualized renders 1`] = ` style="height: 34px; width: 200px;" >
diff --git a/packages/eui/src/components/datagrid/body/data_grid_body_custom.tsx b/packages/eui/src/components/datagrid/body/data_grid_body_custom.tsx index 0100c23dfcf..6937f064173 100644 --- a/packages/eui/src/components/datagrid/body/data_grid_body_custom.tsx +++ b/packages/eui/src/components/datagrid/body/data_grid_body_custom.tsx @@ -104,6 +104,7 @@ export const EuiDataGridBodyCustomRender: FunctionComponent< sorting, schema, schemaDetectors, + gridStyles, }); const { footerRow } = useDataGridFooter({ @@ -118,6 +119,7 @@ export const EuiDataGridBodyCustomRender: FunctionComponent< columnWidths, defaultColumnWidth, schema, + gridStyles, }); /** diff --git a/packages/eui/src/components/datagrid/body/data_grid_body_virtualized.tsx b/packages/eui/src/components/datagrid/body/data_grid_body_virtualized.tsx index fdca0eea89c..4030afb2250 100644 --- a/packages/eui/src/components/datagrid/body/data_grid_body_virtualized.tsx +++ b/packages/eui/src/components/datagrid/body/data_grid_body_virtualized.tsx @@ -199,6 +199,7 @@ export const EuiDataGridBodyVirtualized: FunctionComponent sorting, schema, schemaDetectors, + gridStyles, }); const { footerRow, footerRowHeight } = useDataGridFooter({ @@ -213,6 +214,7 @@ export const EuiDataGridBodyVirtualized: FunctionComponent columnWidths, defaultColumnWidth, schema, + gridStyles, }); /** diff --git a/packages/eui/src/components/datagrid/body/footer/_data_grid_footer_row.scss b/packages/eui/src/components/datagrid/body/footer/_data_grid_footer_row.scss index 5eddd8647f3..568b157ab2f 100644 --- a/packages/eui/src/components/datagrid/body/footer/_data_grid_footer_row.scss +++ b/packages/eui/src/components/datagrid/body/footer/_data_grid_footer_row.scss @@ -1,47 +1,5 @@ -.euiDataGridFooter { - display: flex; - width: fit-content; -} - @include euiDataGridFooterCell { flex: 0 0 auto; position: relative; font-weight: $euiFontWeightBold; } - -@include euiDataGridStyles(stickyFooter) { - .euiDataGridFooter { - position: sticky; - bottom: 0; - } -} - -@include euiDataGridStyles(footerOverline) { - @include euiDataGridFooterCell { - border-top: $euiBorderThick; - // stylelint-disable declaration-no-important - border-top-color: $euiTextColor !important; - background: $euiColorEmptyShade !important; - // stylelint-enable declaration-no-important - } -} - -@include euiDataGridStyles(bordersNone) { - @include euiDataGridFooterCell { - border-left: none; - border-right: none; - } -} - -@include euiDataGridStyles(bordersHorizontal) { - @include euiDataGridFooterCell { - border-left: none; - border-right: none; - } -} - -@include euiDataGridStyles(footerShade) { - @include euiDataGridFooterCell { - background: tintOrShade($euiColorLightestShade, 0%, 10%); - } -} diff --git a/packages/eui/src/components/datagrid/body/footer/data_grid_footer.styles.ts b/packages/eui/src/components/datagrid/body/footer/data_grid_footer.styles.ts new file mode 100644 index 00000000000..ac38024056c --- /dev/null +++ b/packages/eui/src/components/datagrid/body/footer/data_grid_footer.styles.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { css } from '@emotion/react'; + +import { UseEuiTheme } from '../../../../services'; +import { logicalCSS } from '../../../../global_styling'; + +import { euiDataGridVariables } from '../../data_grid.styles'; + +export const euiDataGridFooterStyles = (euiThemeContext: UseEuiTheme) => { + const { euiTheme } = euiThemeContext; + const { levels } = euiDataGridVariables(euiThemeContext); + + return { + euiDataGridFooter: css` + display: flex; + ${logicalCSS('width', 'fit-content')} + background-color: ${euiTheme.colors.emptyShade}; + `, + sticky: css` + z-index: ${levels.stickyHeader}; /* Should sit above content and cell actions */ + position: sticky; + ${logicalCSS('bottom', 0)} + `, + overline: css` + ${logicalCSS( + 'border-top', + `${euiTheme.border.width.thick} solid ${euiTheme.colors.text}` + )} + `, + shade: css` + background-color: ${euiTheme.colors.lightestShade}; + `, + striped: css` + .euiDataGrid--stripes & { + background-color: ${euiTheme.colors.lightestShade}; + } + `, + }; +}; diff --git a/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.test.tsx b/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.test.tsx index 869478ec4c4..6a246575f66 100644 --- a/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.test.tsx +++ b/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.test.tsx @@ -7,7 +7,6 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; import { render } from '../../../../test/rtl'; import { EuiDataGridFooterRow } from './data_grid_footer_row'; @@ -22,72 +21,69 @@ describe('EuiDataGridFooterRow', () => { columnWidths: { someColumn: 30 }, renderCellValue: () =>
, interactiveCellId: 'someId', + gridStyles: { stickyFooter: false, footer: 'striped' as const }, }; it('renders columns', () => { - const component = shallow(); + const { container } = render(); - expect(component).toMatchInlineSnapshot(` + expect(container.firstChild).toMatchInlineSnapshot(`
- - +
+
+
+
+ +
+
+
+
+
+ +
`); }); @@ -100,7 +96,7 @@ describe('EuiDataGridFooterRow', () => { }; it('renders leading control columns as null/empty by default', () => { - const component = shallow( + const { container } = render( { /> ); - expect(component).toMatchInlineSnapshot(` -
- -
- `); - - const renderCellValue: Function = component - .find('EuiDataGridCell') - .prop('renderCellValue'); - expect(renderCellValue()).toEqual(null); + expect( + container.querySelector('.euiDataGridRowCell__content') + ).toBeEmptyDOMElement(); }); it('renders trailing control columns as null/empty by default', () => { - const component = shallow( + const { container } = render( { /> ); - expect(component).toMatchInlineSnapshot(` -
- -
- `); - - const renderCellValue: Function = component - .find('EuiDataGridCell') - .prop('renderCellValue'); - expect(renderCellValue()).toEqual(null); + expect( + container.querySelector('.euiDataGridRowCell__content') + ).toBeEmptyDOMElement(); }); it('renders control column `footerCellRender`s and `footerCellProps` if passed', () => { @@ -250,9 +172,9 @@ describe('EuiDataGridFooterRow', () => { }); it('renders striped styling if the footer row is odd', () => { - const component = shallow( + const { container } = render( ); - expect(component.hasClass('euiDataGridRow--striped')).toBe(true); + expect(container.firstElementChild!.className).toContain('striped'); }); }); diff --git a/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.tsx b/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.tsx index 10b7e3a5b10..99f76a3bd2f 100644 --- a/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.tsx +++ b/packages/eui/src/components/datagrid/body/footer/data_grid_footer_row.tsx @@ -6,10 +6,13 @@ * Side Public License, v 1. */ -import classnames from 'classnames'; import React, { forwardRef, memo, useContext } from 'react'; -import { EuiDataGridCell, DataGridCellPopoverContext } from '../cell'; +import classnames from 'classnames'; + +import { useEuiMemoizedStyles } from '../../../../services'; import { EuiDataGridFooterRowProps } from '../../data_grid_types'; +import { EuiDataGridCell, DataGridCellPopoverContext } from '../cell'; +import { euiDataGridFooterStyles } from './data_grid_footer.styles'; const renderEmpty = () => null; @@ -30,16 +33,21 @@ const EuiDataGridFooterRow = memo( interactiveCellId, 'data-test-subj': _dataTestSubj, visibleRowIndex = rowIndex, + gridStyles, ...rest }, ref ) => { - const classes = classnames( - 'euiDataGridRow', - { 'euiDataGridRow--striped': visibleRowIndex % 2 !== 0 }, - 'euiDataGridFooter', - className - ); + const styles = useEuiMemoizedStyles(euiDataGridFooterStyles); + const cssStyles = [ + styles.euiDataGridFooter, + gridStyles.stickyFooter && styles.sticky, + gridStyles.footer === 'striped' + ? visibleRowIndex % 2 !== 0 && styles.striped + : styles[gridStyles.footer!], + ]; + + const classes = classnames('euiDataGridFooter', className); const dataTestSubj = classnames( 'dataGridRow', 'dataGridFooterRow', @@ -58,6 +66,7 @@ const EuiDataGridFooterRow = memo(
{ + const { euiTheme } = euiThemeContext; + const { levels } = euiDataGridVariables(euiThemeContext); + + return { + euiDataGridHeader: css` + z-index: ${levels.stickyHeader}; + position: sticky; + ${logicalCSS('top', 0)} + ${logicalCSS('width', 'fit-content')} + display: flex; + `, + underline: css` + background-color: ${euiTheme.colors.emptyShade}; + ${logicalCSS( + 'border-bottom', + `${euiTheme.border.width.thick} solid ${euiTheme.colors.text}` + )} + `, + shade: css` + background-color: ${euiTheme.colors.lightestShade}; + `, + }; +}; diff --git a/packages/eui/src/components/datagrid/body/header/data_grid_header_row.test.tsx b/packages/eui/src/components/datagrid/body/header/data_grid_header_row.test.tsx index e8ed3dcd9c3..0dfe8a25775 100644 --- a/packages/eui/src/components/datagrid/body/header/data_grid_header_row.test.tsx +++ b/packages/eui/src/components/datagrid/body/header/data_grid_header_row.test.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '../../../../test/rtl'; import { EuiDataGridHeaderRow } from './data_grid_header_row'; @@ -20,14 +20,15 @@ describe('EuiDataGridHeaderRow', () => { setColumnWidth: jest.fn(), setVisibleColumns: jest.fn(), switchColumnPos: jest.fn(), + gridStyles: { header: 'shade' as const }, }; it('renders', () => { - const component = shallow(); + const { container } = render(); - expect(component).toMatchInlineSnapshot(` + expect(container.firstChild).toMatchInlineSnapshot(`
@@ -35,7 +36,7 @@ describe('EuiDataGridHeaderRow', () => { }); it('renders columns', () => { - const component = shallow( + const { container } = render( { defaultColumnWidth={20} /> ); - expect(component).toMatchInlineSnapshot(` + expect(container.firstChild).toMatchInlineSnapshot(`
- +
+
+
+ someColumn +
+
+ +
+
`); }); it('renders leading control columns', () => { - const component = shallow( + const { container } = render( { /> ); - expect(component).toMatchInlineSnapshot(` -
- -
- `); + expect( + container.querySelector('.euiDataGridHeaderCell--controlColumn') + ).toBeInTheDocument(); }); it('renders trailing control columns', () => { - const component = shallow( + const { container } = render( { /> ); - expect(component).toMatchInlineSnapshot(` -
- -
- `); + expect( + container.querySelector('.euiDataGridHeaderCell--controlColumn') + ).toBeInTheDocument(); }); }); diff --git a/packages/eui/src/components/datagrid/body/header/data_grid_header_row.tsx b/packages/eui/src/components/datagrid/body/header/data_grid_header_row.tsx index 83ccce4aa90..8efbde58646 100644 --- a/packages/eui/src/components/datagrid/body/header/data_grid_header_row.tsx +++ b/packages/eui/src/components/datagrid/body/header/data_grid_header_row.tsx @@ -8,12 +8,15 @@ import classnames from 'classnames'; import React, { forwardRef, memo } from 'react'; -import { EuiDataGridControlHeaderCell } from './data_grid_control_header_cell'; -import { EuiDataGridHeaderCell } from './data_grid_header_cell'; + +import { useEuiMemoizedStyles } from '../../../../services'; import { emptyControlColumns, EuiDataGridHeaderRowProps, } from '../../data_grid_types'; +import { EuiDataGridControlHeaderCell } from './data_grid_control_header_cell'; +import { EuiDataGridHeaderCell } from './data_grid_header_cell'; +import { euiDataGridHeaderStyles } from './data_grid_header_row.styles'; const EuiDataGridHeaderRow = memo( forwardRef((props, ref) => { @@ -31,9 +34,13 @@ const EuiDataGridHeaderRow = memo( sorting, schema, schemaDetectors, + gridStyles, ...rest } = props; + const styles = useEuiMemoizedStyles(euiDataGridHeaderStyles); + const cssStyles = [styles.euiDataGridHeader, styles[gridStyles.header!]]; + const classes = classnames('euiDataGridHeader', className); const dataTestSubj = classnames('dataGridHeader', _dataTestSubj); @@ -41,6 +48,7 @@ const EuiDataGridHeaderRow = memo(
= { - title: 'Tabular Content/EuiDataGrid/Toolbar Controls', - component: EuiDataGrid, +const meta: Meta = { + title: 'Tabular Content/EuiDataGrid/toolbarVisibility (prop)', + component: EuiDataGridToolbarPropsComponent, }; export default meta; type Story = StoryObj; -export const AdditionalControls: Story = { - parameters: { - controls: { include: ['toolbarVisibility'] }, - }, - args: { - toolbarVisibility: { +export const NoToolbar: StoryObj> = + { + parameters: { + codeSnippet: { + snippet: ``, + }, + controls: { include: ['toolbarVisibility'] }, + }, + argTypes: { + toolbarVisibility: { control: { type: 'boolean' } }, + }, + args: { + toolbarVisibility: false, + }, + render: (args: Pick) => ( + + ), + }; + +export const ToolbarVisibilityOptions: StoryObj = + { + parameters: { + codeSnippet: { + snippet: ``, + removeDefaultProps: false, + }, + controls: { + include: [ + 'showColumnSelector', + 'showSortSelector', + 'showDisplaySelector', + 'showFullScreenSelector', + 'showKeyboardShortcuts', + 'additionalControls', + ], + sort: 'none', + }, + }, + argTypes: { additionalControls: { - left: { - prepend: ( - - 12 results - - ), - append: ( - - Download - - ), + control: { type: 'boolean' }, + mapping: { + true: Additional control, + false: undefined, }, - right: ( - <> - - - - - - - + }, + }, + args: { + showColumnSelector: { + allowHide: true, + allowReorder: true, + }, + showSortSelector: true, + showDisplaySelector: { + allowDensity: true, + allowRowHeight: true, + allowResetButton: true, + additionalDisplaySettings: '', + }, + showFullScreenSelector: false, + showKeyboardShortcuts: false, + additionalControls: false, + }, + render: (toolbarVisibility: EuiDataGridToolBarVisibilityOptions) => ( + + ), + }; + +export const AdditionalControlsOptions: StoryObj = + { + parameters: { + controls: { include: ['left', 'right'] }, + codeSnippet: { + /* eslint-disable local/css-logical-properties */ + snippet: `, + append: , + }, + right: ( + + + + ), + }, + }} +/>`, + }, + }, + args: { + left: { + prepend: ( + + 12 results + + ), + append: ( + + Download + ), }, + right: ( + <> + + + + + + + + ), }, - }, - render: (args: EuiDataGridProps) => , -}; + render: ( + additionalControls: EuiDataGridToolBarAdditionalControlsOptions + ) => ( + + ), + }; -export const RenderCustomToolbar: Story = { +export const RenderCustomToolbar: StoryObj< + Pick +> = { parameters: { controls: { include: ['renderCustomToolbar'] }, + codeSnippet: { + snippet: ` <>...} />`, + }, }, args: { renderCustomToolbar: ({ @@ -123,19 +240,32 @@ export const RenderCustomToolbar: Story = { ); }, }, - render: (args: EuiDataGridProps) => , + render: (args: Pick) => ( + + ), }; /** * VRT tests only */ +const vrtProps = { + 'aria-label': 'VRT only', + columns: [{ id: 'Test' }], + columnVisibility: { + visibleColumns: ['Test'], + setVisibleColumns: () => {}, + }, + renderCellValue: () => 'Test', + rowCount: 2, +}; + export const ColumnSelector: Story = { tags: ['vrt-only'], parameters: { loki: { chromeSelector: LOKI_SELECTORS.portal }, }, - render: () => , // Column sorting is hidden on mobile otherwise + render: () => , // Column sorting is hidden on mobile otherwise play: async ({ canvasElement, step }: PlayFunctionContext) => { const canvas = within(canvasElement); @@ -156,7 +286,7 @@ export const ColumnSorting: Story = { parameters: { loki: { chromeSelector: LOKI_SELECTORS.portal }, }, - render: () => , // Column sorting is hidden on mobile otherwise + render: () => , // Column sorting is hidden on mobile otherwise play: async ({ canvasElement, step }: PlayFunctionContext) => { const canvas = within(canvasElement); @@ -182,7 +312,7 @@ export const KeyboardShortcuts: Story = { parameters: { loki: { chromeSelector: LOKI_SELECTORS.portal }, }, - render: () => , + render: () => , play: async ({ canvasElement }: PlayFunctionContext) => { const canvas = within(canvasElement); await canvas.waitForAndClick('dataGridKeyboardShortcutsButton'); @@ -194,7 +324,7 @@ export const DisplaySelector: Story = { parameters: { loki: { chromeSelector: LOKI_SELECTORS.portal }, }, - render: () => , + render: () => , play: async ({ canvasElement, step }: PlayFunctionContext) => { const canvas = within(canvasElement); @@ -214,34 +344,9 @@ export const FullScreenToggle: Story = { parameters: { loki: { chromeSelector: LOKI_SELECTORS.portal }, }, - render: () => , + render: () => , play: async ({ canvasElement }: PlayFunctionContext) => { const canvas = within(canvasElement); await canvas.waitForAndClick('dataGridFullScreenButton'); }, }; - -const StatefulDataGrid = ( - props: Partial> -) => { - const [visibleColumns, setVisibleColumns] = useState(['Test']); - const [sortingColumns, setSortingColumns] = useState([]); - - return ( - 'Test'} - rowCount={2} - columns={[{ id: 'Test' }]} - columnVisibility={{ visibleColumns, setVisibleColumns }} - sorting={{ - columns: sortingColumns, - onSort: (sortingColumns) => { - setSortingColumns(sortingColumns); - }, - }} - inMemory={{ level: 'sorting' }} - {...props} - /> - ); -}; diff --git a/packages/eui/src/components/datagrid/controls/data_grid_toolbar.styles.ts b/packages/eui/src/components/datagrid/controls/data_grid_toolbar.styles.ts index b52f087489c..0271e0396d4 100644 --- a/packages/eui/src/components/datagrid/controls/data_grid_toolbar.styles.ts +++ b/packages/eui/src/components/datagrid/controls/data_grid_toolbar.styles.ts @@ -22,15 +22,6 @@ export const euiDataGridToolbarStyles = ({ euiTheme }: UseEuiTheme) => { gap: ${euiTheme.size.base}; ${logicalCSS('padding-vertical', euiTheme.size.xs)} background-color: ${euiTheme.colors.emptyShade}; - - .euiDataGrid--bordersHorizontal & { - ${logicalCSS('border-bottom', euiTheme.border.thin)} - } - - .euiDataGrid--bordersAll & { - border: ${euiTheme.border.thin}; - background-color: ${euiTheme.colors.body}; - } `, euiDataGrid__rightControls: css` display: flex; diff --git a/packages/eui/src/components/datagrid/data_grid.stories.tsx b/packages/eui/src/components/datagrid/data_grid.stories.tsx index 8eca2c46a8b..6f374035da3 100644 --- a/packages/eui/src/components/datagrid/data_grid.stories.tsx +++ b/packages/eui/src/components/datagrid/data_grid.stories.tsx @@ -6,202 +6,23 @@ * Side Public License, v 1. */ -import React, { useCallback, useEffect, useState } from 'react'; +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; -import { faker } from '@faker-js/faker'; import { enableFunctionToggleControls } from '../../../.storybook/utils'; -import { EuiLink } from '../link'; -import { EuiScreenReaderOnly } from '../accessibility'; import { EuiButtonIcon } from '../button'; +import { EuiToolTip } from '../tool_tip'; -import { DEFAULT_ROW_HEIGHT } from './utils/row_heights'; -import { MINIMUM_WIDTH_FOR_GRID_CONTROLS } from './controls/data_grid_toolbar'; +import { + StatefulDataGrid, + defaultStorybookArgs, + raw_data, +} from './data_grid.stories.utils'; import type { - EuiDataGridCellValueElementProps, EuiDataGridColumnCellActionProps, - EuiDataGridColumnSortingConfig, EuiDataGridProps, } from './data_grid_types'; import { EuiDataGrid } from './data_grid'; -import { EuiToolTip } from '../tool_tip'; - -faker.seed(42); - -// NOTE: using faker.date.past() is not fully stable for VRT as the date is -// based on a years time distance (default 1 year) which updates with progressing time -// faker.seed() ensures the same date is output in the same time frame -// but after some time the time distance will generate a newer, closer date -// which then invalidates the VRT -const staticDates = [ - new Date('Tue Mar 19 2024 18:54:51 GMT+0100'), - new Date('Mon Mar 25 2024 19:27:35 GMT+0100'), - new Date('Sat Sep 09 2023 00:32:42 GMT+0200'), - new Date('Wed Jun 14 2023 06:48:29 GMT+0200'), - new Date('Mon Mar 04 2024 04:40:36 GMT+0100'), - new Date('Mon Feb 05 2024 10:51:48 GMT+0100'), - new Date('Mon Jun 19 2023 12:08:38 GMT+0200'), - new Date('Wed Jul 26 2023 01:15:02 GMT+0200'), - new Date('Wed Nov 08 2023 08:49:13 GMT+0100'), - new Date('Sun Nov 19 2023 01:49:12 GMT+0100'), -]; - -const dataKeys = [ - 'name', - 'email', - 'account', - 'location', - 'date', - 'version', -] as const; - -const raw_data = Array.from({ length: 10 }).map((_, i) => { - const email = faker.internet.email(); - const name = `${faker.person.lastName()}, ${faker.person.firstName()}`; - const date = staticDates[i].toDateString(); - const suffix = faker.person.suffix(); - return { - name: { - formatted: `${name} ${suffix}`, - raw: name, - }, - email: { - formatted: {faker.internet.email()}, - raw: email, - }, - location: ( - <> - {`${faker.location.city()}, `} - {faker.location.country()} - - ), - date: `${date}`, - account: faker.finance.accountNumber(), - version: faker.system.semver(), - }; -}); - -const columns = [ - { - id: 'name', - displayAsText: 'Name', - defaultSortDirection: 'asc' as const, - cellActions: [ - ({ rowIndex, Component }: EuiDataGridColumnCellActionProps) => { - const data = raw_data; - const value = data[rowIndex].name.raw; - return ( - alert(`Hi ${value}`)} - iconType="heart" - aria-label={`Say hi to ${value}!`} - > - Say hi - - ); - }, - ], - }, - { - id: 'email', - displayAsText: 'Email address', - initialWidth: 130, - cellActions: [ - ({ rowIndex, Component }: EuiDataGridColumnCellActionProps) => { - const data = raw_data; - const value = data[rowIndex].email.raw; - return ( - alert(value)} - iconType="email" - aria-label={`Send email to ${value}`} - > - Send email - - ); - }, - ], - }, - { - id: 'location', - displayAsText: 'Location', - }, - { - id: 'account', - displayAsText: 'Account', - actions: { - showHide: { label: 'Custom hide label' }, - showMoveLeft: false, - showMoveRight: false, - additional: [ - { - label: 'Custom action', - onClick: () => {}, - iconType: 'cheer', - size: 'xs' as const, - color: 'text' as const, - }, - ], - }, - cellActions: [ - ({ - rowIndex, - Component, - isExpanded, - }: EuiDataGridColumnCellActionProps) => { - const data = raw_data; - const value = data[rowIndex].account; - const onClick = isExpanded - ? () => alert(`Sent money to ${value} when expanded`) - : () => alert(`Sent money to ${value} when not expanded`); - return ( - - Send money - - ); - }, - ], - }, - { - id: 'date', - displayAsText: 'Date', - defaultSortDirection: 'desc' as const, - }, - { - id: 'version', - displayAsText: 'Version', - defaultSortDirection: 'desc' as const, - initialWidth: 70, - isResizable: false, - actions: false as const, - }, -]; - -const RenderCellValue = ({ - rowIndex, - columnId, -}: EuiDataGridCellValueElementProps) => { - const data = raw_data; - const row = data[rowIndex]; - const columnName = columnId as (typeof dataKeys)[number]; - const column = row[columnName]; - - const getFormatted = () => { - if (typeof column === 'object') { - const hasFormatted = 'formatted' in column; - - return hasFormatted ? column.formatted : column; - } - - return typeof column === 'string' ? column : null; - }; - - return data.hasOwnProperty(rowIndex) ? getFormatted() : null; -}; const meta: Meta = { title: 'Tabular Content/EuiDataGrid', @@ -216,258 +37,25 @@ const meta: Meta = { width: { control: 'text' }, height: { control: 'text' }, }, - args: { - minSizeForControls: MINIMUM_WIDTH_FOR_GRID_CONTROLS, - }, }; export default meta; type Story = StoryObj; export const Playground: Story = { - args: { - 'aria-label': 'EuiDataGrid', - columns, - rowCount: 10, - renderCellValue: RenderCellValue, - trailingControlColumns: [ - { - id: 'trailing-actions', - width: 40, - headerCellRender: () => ( - - Trailing actions - - ), - rowCellRender: () => , - }, - ], - leadingControlColumns: [ - { - id: 'leading-actions', - width: 40, - headerCellRender: () => ( - - Leading actions - - ), - rowCellRender: () => , - }, - ], - // setup for easier testing/QA - columnVisibility: { - visibleColumns: [ - 'name', - 'email', - 'account', - 'location', - 'date', - 'amount', - 'phone', - 'version', - ], - setVisibleColumns: () => {}, - }, - inMemory: { level: 'sorting' }, - pagination: { - pageIndex: 0, - pageSize: 10, - pageSizeOptions: [10, 20, 50], - onChangeItemsPerPage: () => {}, - onChangePage: () => {}, - }, - gridStyle: { - fontSize: 'm', - cellPadding: 'm', - border: 'all', - stripes: false, - header: 'shade', - footer: 'overline', - stickyFooter: true, - rowHover: 'highlight', - rowClasses: {}, - }, - width: '', - height: '', - toolbarVisibility: { - showColumnSelector: true, - showDisplaySelector: true, - showSortSelector: true, - showKeyboardShortcuts: true, - showFullScreenSelector: true, - additionalControls: null, - }, - rowHeightsOptions: { - defaultHeight: DEFAULT_ROW_HEIGHT, - rowHeights: {}, - lineHeight: undefined, - scrollAnchorRow: undefined, - }, - }, + args: defaultStorybookArgs, render: (args: EuiDataGridProps) => , }; enableFunctionToggleControls(Playground, ['onColumnResize']); export const Virtualization: Story = { - args: { - ...Playground.args, - width: 300, - height: 300, - }, - render: (args: EuiDataGridProps) => , -}; - -export const HeightLineCount: Story = { - parameters: { - controls: { - include: ['gridStyle', 'rowHeightsOptions', 'width', 'height'], - }, - }, - args: { - columns, - rowCount: 5, - renderCellValue: RenderCellValue, - // setup for easier testing/QA - columnVisibility: { - visibleColumns: [ - 'name', - 'email', - 'account', - 'location', - 'date', - 'amount', - 'phone', - 'version', - ], - setVisibleColumns: () => {}, - }, - gridStyle: { - fontSize: 's', - cellPadding: 'm', - border: 'all', - stripes: false, - header: 'shade', - footer: 'overline', - stickyFooter: true, - rowHover: 'highlight', - rowClasses: {}, - }, - width: '700px', - height: '', - toolbarVisibility: false, - rowHeightsOptions: { - defaultHeight: { - lineCount: 1, - }, - lineHeight: undefined, - scrollAnchorRow: undefined, - }, - }, - render: (args: EuiDataGridProps) => , -}; - -export const RowHeight: Story = { - parameters: { - controls: { - include: ['gridStyle', 'rowHeightsOptions', 'width', 'height'], - }, - }, - args: { - columns, - rowCount: 5, - renderCellValue: RenderCellValue, - // setup for easier testing/QA - columnVisibility: { - visibleColumns: [ - 'name', - 'email', - 'account', - 'location', - 'date', - 'amount', - 'phone', - 'version', - ], - setVisibleColumns: () => {}, - }, - gridStyle: { - fontSize: 's', - cellPadding: 'm', - border: 'all', - stripes: false, - header: 'shade', - footer: 'overline', - stickyFooter: true, - rowHover: 'highlight', - rowClasses: {}, - }, - width: '', - height: '', - toolbarVisibility: false, - rowHeightsOptions: { - defaultHeight: { - height: 48, - }, - rowHeights: {}, - lineHeight: undefined, - scrollAnchorRow: undefined, - }, - }, - render: (args: EuiDataGridProps) => , -}; - -export const CustomRowHeights: Story = { parameters: { - controls: { - include: ['gridStyle', 'rowHeightsOptions', 'width', 'height'], - }, + controls: { include: ['width', 'height', 'virtualizationOptions'] }, }, args: { - columns, - rowCount: 5, - renderCellValue: RenderCellValue, - // setup for easier testing/QA - columnVisibility: { - visibleColumns: [ - 'name', - 'email', - 'account', - 'location', - 'date', - 'amount', - 'phone', - 'version', - ], - setVisibleColumns: () => {}, - }, - gridStyle: { - fontSize: 's', - cellPadding: 'm', - border: 'all', - stripes: false, - header: 'shade', - footer: 'overline', - stickyFooter: true, - rowHover: 'highlight', - rowClasses: {}, - }, - width: '700px', - height: '', - toolbarVisibility: false, - rowHeightsOptions: { - defaultHeight: { - lineCount: 1, - }, - rowHeights: { - 2: 'auto', - 3: 48, - 4: { - height: 48, - }, - }, - lineHeight: undefined, - scrollAnchorRow: undefined, - }, + ...defaultStorybookArgs, + width: '300px', + height: '300px', }, render: (args: EuiDataGridProps) => , }; @@ -492,6 +80,7 @@ export const CustomHeaderContent: Story = { }, }, args: { + ...defaultStorybookArgs, columns: [ { id: 'name', @@ -534,94 +123,8 @@ export const CustomHeaderContent: Story = { }, ], }, - ...[...columns].slice(2), + ...[...defaultStorybookArgs.columns].slice(2), ], - rowCount: 10, - renderCellValue: RenderCellValue, - inMemory: { level: 'sorting' }, - toolbarVisibility: { - showColumnSelector: true, - showDisplaySelector: true, - showSortSelector: true, - showKeyboardShortcuts: true, - showFullScreenSelector: true, - additionalControls: null, - }, }, render: (args: EuiDataGridProps) => , }; - -const StatefulDataGrid = (props: EuiDataGridProps) => { - const { pagination, sorting, columnVisibility, ...rest } = props; - - // Pagination - const [_pagination, setPagination] = useState({ - pageIndex: pagination?.pageIndex ?? 0, - ...pagination, - }); - const onChangeItemsPerPage = useCallback( - (pageSize: number) => - setPagination((pagination) => ({ - ...pagination, - pageSize, - pageIndex: 0, - })), - [setPagination] - ); - const onChangePage = useCallback( - (pageIndex: number) => - setPagination((pagination) => ({ ...pagination, pageIndex })), - [setPagination] - ); - - useEffect(() => { - if (pagination) { - setPagination((curentPagination) => ({ - ...curentPagination, - ...pagination, - })); - } - }, [pagination]); - - // Sorting - const [sortingColumns, setSortingColumns] = useState< - EuiDataGridColumnSortingConfig[] - >(sorting?.columns ?? []); - const onSort = useCallback( - (sortingColumns: EuiDataGridColumnSortingConfig[]) => { - setSortingColumns(sortingColumns); - sorting?.onSort?.(sortingColumns); - }, - [setSortingColumns, sorting] - ); - - useEffect(() => { - if (sorting && Array.isArray(sorting.columns)) { - setSortingColumns(sorting.columns); - } - }, [sorting]); - - // Column visibility - const [visibleColumns, setVisibleColumns] = useState( - columnVisibility?.visibleColumns ?? columns.map(({ id }) => id) // initialize to the full set of columns - ); - - useEffect(() => { - if (columnVisibility?.visibleColumns != null) { - setVisibleColumns(columnVisibility?.visibleColumns); - } - }, [columnVisibility]); - - return ( - - ); -}; diff --git a/packages/eui/src/components/datagrid/data_grid.stories.utils.tsx b/packages/eui/src/components/datagrid/data_grid.stories.utils.tsx new file mode 100644 index 00000000000..f4c2d5b4da6 --- /dev/null +++ b/packages/eui/src/components/datagrid/data_grid.stories.utils.tsx @@ -0,0 +1,389 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* eslint-disable storybook/default-exports, storybook/prefer-pascal-case */ + +import React, { + useCallback, + useEffect, + useState, + FunctionComponent, +} from 'react'; +import { faker } from '@faker-js/faker'; + +import { EuiLink } from '../link'; +import { EuiScreenReaderOnly } from '../accessibility'; +import { EuiButtonIcon } from '../button'; + +import { MINIMUM_WIDTH_FOR_GRID_CONTROLS } from './controls/data_grid_toolbar'; +import type { + EuiDataGridCellValueElementProps, + EuiDataGridColumnCellActionProps, + EuiDataGridColumnSortingConfig, + EuiDataGridProps, + EuiDataGridStyle, + EuiDataGridRowHeightsOptions, + EuiDataGridToolBarVisibilityOptions, + EuiDataGridToolBarAdditionalControlsOptions, +} from './data_grid_types'; +import { EuiDataGrid } from './data_grid'; + +faker.seed(42); + +// NOTE: using faker.date.past() is not fully stable for VRT as the date is +// based on a years time distance (default 1 year) which updates with progressing time +// faker.seed() ensures the same date is output in the same time frame +// but after some time the time distance will generate a newer, closer date +// which then invalidates the VRT +const staticDates = [ + new Date('Tue Mar 19 2024 18:54:51 GMT+0100'), + new Date('Mon Mar 25 2024 19:27:35 GMT+0100'), + new Date('Sat Sep 09 2023 00:32:42 GMT+0200'), + new Date('Wed Jun 14 2023 06:48:29 GMT+0200'), + new Date('Mon Mar 04 2024 04:40:36 GMT+0100'), + new Date('Mon Feb 05 2024 10:51:48 GMT+0100'), + new Date('Mon Jun 19 2023 12:08:38 GMT+0200'), + new Date('Wed Jul 26 2023 01:15:02 GMT+0200'), + new Date('Wed Nov 08 2023 08:49:13 GMT+0100'), + new Date('Sun Nov 19 2023 01:49:12 GMT+0100'), +]; + +const dataKeys = [ + 'name', + 'email', + 'account', + 'location', + 'date', + 'version', +] as const; + +export const raw_data = Array.from({ length: 10 }).map((_, i) => { + const email = faker.internet.email(); + const name = `${faker.person.lastName()}, ${faker.person.firstName()}`; + const date = staticDates[i].toDateString(); + const suffix = faker.person.suffix(); + return { + name: { + formatted: `${name} ${suffix}`, + raw: name, + }, + email: { + formatted: {faker.internet.email()}, + raw: email, + }, + location: ( + <> + {`${faker.location.city()}, `} + {faker.location.country()} + + ), + date: `${date}`, + account: faker.finance.accountNumber(), + version: faker.system.semver(), + }; +}); + +const columns = [ + { + id: 'name', + displayAsText: 'Name', + defaultSortDirection: 'asc' as const, + cellActions: [ + ({ rowIndex, Component }: EuiDataGridColumnCellActionProps) => { + const data = raw_data; + const value = data[rowIndex].name.raw; + return ( + alert(`Hi ${value}`)} + iconType="heart" + aria-label={`Say hi to ${value}!`} + > + Say hi + + ); + }, + ], + }, + { + id: 'email', + displayAsText: 'Email address', + initialWidth: 130, + cellActions: [ + ({ rowIndex, Component }: EuiDataGridColumnCellActionProps) => { + const data = raw_data; + const value = data[rowIndex].email.raw; + return ( + alert(value)} + iconType="email" + aria-label={`Send email to ${value}`} + > + Send email + + ); + }, + ], + }, + { + id: 'location', + displayAsText: 'Location', + }, + { + id: 'account', + displayAsText: 'Account', + actions: { + showHide: { label: 'Custom hide label' }, + showMoveLeft: false, + showMoveRight: false, + additional: [ + { + label: 'Custom action', + onClick: () => {}, + iconType: 'cheer', + size: 'xs' as const, + color: 'text' as const, + }, + ], + }, + cellActions: [ + ({ + rowIndex, + Component, + isExpanded, + }: EuiDataGridColumnCellActionProps) => { + const data = raw_data; + const value = data[rowIndex].account; + const onClick = isExpanded + ? () => alert(`Sent money to ${value} when expanded`) + : () => alert(`Sent money to ${value} when not expanded`); + return ( + + Send money + + ); + }, + ], + }, + { + id: 'date', + displayAsText: 'Date', + defaultSortDirection: 'desc' as const, + }, + { + id: 'version', + displayAsText: 'Version', + defaultSortDirection: 'desc' as const, + initialWidth: 70, + isResizable: false, + actions: false as const, + }, +]; + +const RenderCellValue = ({ + rowIndex, + columnId, +}: EuiDataGridCellValueElementProps) => { + const data = raw_data; + const row = data[rowIndex]; + const columnName = columnId as (typeof dataKeys)[number]; + const column = row[columnName]; + + const getFormatted = () => { + if (typeof column === 'object') { + const hasFormatted = 'formatted' in column; + + return hasFormatted ? column.formatted : column; + } + + return typeof column === 'string' ? column : null; + }; + + return data.hasOwnProperty(rowIndex) ? getFormatted() : null; +}; + +export const defaultStorybookArgs = { + 'aria-label': 'EuiDataGrid', + columns, + rowCount: 10, + renderCellValue: RenderCellValue, + trailingControlColumns: [ + { + id: 'trailing-actions', + width: 40, + headerCellRender: () => ( + + Trailing actions + + ), + rowCellRender: () => , + }, + ], + leadingControlColumns: [ + { + id: 'leading-actions', + width: 40, + headerCellRender: () => ( + + Leading actions + + ), + rowCellRender: () => , + }, + ], + // setup for easier testing/QA + columnVisibility: { + visibleColumns: [ + 'name', + 'email', + 'account', + 'location', + 'date', + 'amount', + 'phone', + 'version', + ], + setVisibleColumns: () => {}, + }, + inMemory: { level: 'sorting' } as const, + pagination: { + pageIndex: 0, + pageSize: 10, + pageSizeOptions: [10, 20, 50], + onChangeItemsPerPage: () => {}, + onChangePage: () => {}, + }, + gridStyle: { + fontSize: 'm', + cellPadding: 'm', + border: 'all', + stripes: false, + header: 'shade', + footer: 'overline', + stickyFooter: true, + rowHover: 'highlight', + rowClasses: {}, + } as const, + width: '', + height: '', + toolbarVisibility: { + showColumnSelector: true, + showDisplaySelector: true, + showSortSelector: true, + showKeyboardShortcuts: true, + showFullScreenSelector: true, + additionalControls: null, + } as const, + minSizeForControls: MINIMUM_WIDTH_FOR_GRID_CONTROLS, + rowHeightsOptions: { + defaultHeight: undefined, + rowHeights: {}, + lineHeight: undefined, + scrollAnchorRow: undefined, + } as const, +}; + +export const StatefulDataGrid = (props: EuiDataGridProps) => { + const { pagination, sorting, columnVisibility, ...rest } = props; + + // Pagination + const [_pagination, setPagination] = useState({ + pageIndex: pagination?.pageIndex ?? 0, + ...pagination, + }); + const onChangeItemsPerPage = useCallback( + (pageSize: number) => + setPagination((pagination) => ({ + ...pagination, + pageSize, + pageIndex: 0, + })), + [setPagination] + ); + const onChangePage = useCallback( + (pageIndex: number) => + setPagination((pagination) => ({ ...pagination, pageIndex })), + [setPagination] + ); + + useEffect(() => { + if (pagination) { + setPagination((curentPagination) => ({ + ...curentPagination, + ...pagination, + })); + } + }, [pagination]); + + // Sorting + const [sortingColumns, setSortingColumns] = useState< + EuiDataGridColumnSortingConfig[] + >(sorting?.columns ?? []); + const onSort = useCallback( + (sortingColumns: EuiDataGridColumnSortingConfig[]) => { + setSortingColumns(sortingColumns); + sorting?.onSort?.(sortingColumns); + }, + [setSortingColumns, sorting] + ); + + useEffect(() => { + if (sorting && Array.isArray(sorting.columns)) { + setSortingColumns(sorting.columns); + } + }, [sorting]); + + // Column visibility + const [visibleColumns, setVisibleColumns] = useState( + columnVisibility?.visibleColumns ?? columns.map(({ id }) => id) // initialize to the full set of columns + ); + + useEffect(() => { + if (columnVisibility?.visibleColumns != null) { + setVisibleColumns(columnVisibility?.visibleColumns); + } + }, [columnVisibility]); + + return ( + + ); +}; + +/* + * Components that exist purely for allowing Storybook to parse certain nested + * interfaces/types into specific example control tables. + * + * For whatever reason, they needs to be in a separate file for Storybook's + * react-typescript-docgen to parse the jsdoc comments into the controls table + */ + +export const EuiDataGridToolbarPropsComponent: FunctionComponent< + EuiDataGridProps & // We really just want toolbarVisibility and renderCustomToolbar from here, but typescript-docgen is unhappy if we Pick<> + EuiDataGridToolBarVisibilityOptions & + EuiDataGridToolBarAdditionalControlsOptions +> = () => <>; + +export const EuiDataGridStylePropsComponent: FunctionComponent< + EuiDataGridStyle +> = () => <>; + +export const EuiDataGridRowHeightsPropsComponent: FunctionComponent< + EuiDataGridRowHeightsOptions +> = () => <>; diff --git a/packages/eui/src/components/datagrid/data_grid.styles.ts b/packages/eui/src/components/datagrid/data_grid.styles.ts index 25637454272..2a4b8b3166c 100644 --- a/packages/eui/src/components/datagrid/data_grid.styles.ts +++ b/packages/eui/src/components/datagrid/data_grid.styles.ts @@ -8,12 +8,45 @@ import { css } from '@emotion/react'; -import { UseEuiTheme } from '../../services'; -import { logicalCSS, logicalSizeCSS } from '../../global_styling'; +import { UseEuiTheme, tintOrShade } from '../../services'; +import { + euiFontSize, + logicalCSS, + logicalSizeCSS, + mathWithUnits, +} from '../../global_styling'; -export const euiDataGridStyles = (euiThemeContext: UseEuiTheme) => { +export const euiDataGridVariables = (euiThemeContext: UseEuiTheme) => { const { euiTheme } = euiThemeContext; + return { + cellPadding: { + s: euiTheme.size.xs, + m: mathWithUnits(euiTheme.size.m, (x) => x / 2), + l: euiTheme.size.s, + }, + lineHeight: { + s: euiFontSize(euiThemeContext, 'xs').lineHeight, + m: euiFontSize(euiThemeContext, 'm').lineHeight, + }, + fontSize: { + s: euiFontSize(euiThemeContext, 'xs').fontSize, + m: euiFontSize(euiThemeContext, 's').fontSize, + }, + levels: { + cellPopover: Number(euiTheme.levels.header), // Same z-index as EuiFlyout mask overlays - cell popovers should be under both modal and flyout overlays + get stickyHeader() { + return this.cellPopover - 1; // Needs to sit above the content + cell focus outlines/actions, but below actual popovers + }, + }, + }; +}; + +export const euiDataGridStyles = (euiThemeContext: UseEuiTheme) => { + const { euiTheme, colorMode } = euiThemeContext; + const { cellPadding, lineHeight, fontSize } = + euiDataGridVariables(euiThemeContext); + return { euiDataGrid: css` display: flex; @@ -21,7 +54,147 @@ export const euiDataGridStyles = (euiThemeContext: UseEuiTheme) => { align-items: stretch; ${logicalCSS('height', '100%')} overflow: hidden; + + /* Note: Several Kibana custom renderers are using the .euiDataGridRow classes + * directly for styles, hence why we're defining it here as opposed to applying + * it directly on the row element via Emotion. However, we also need to use + * :where to reduce specificity / allow easier overrides via rowClasses */ + + *:where(& .euiDataGridRow) { + background-color: ${euiTheme.colors.emptyShade}; + } + + *:where(&.euiDataGrid--stripes .euiDataGridRow--striped) { + background-color: ${euiTheme.colors.lightestShade}; + } + + *:where(&.euiDataGrid--rowHoverHighlight .euiDataGridRow:hover) { + background-color: ${euiTheme.colors.highlight}; + } `, + cellPadding: { + cellPadding: (size: 's' | 'm' | 'l') => css` + .euiDataGridHeaderCell, + .euiDataGridRowCell__content { + padding: ${cellPadding[size]}; + } + + /* Workaround to trim line-clamp and padding - @see https://github.com/elastic/eui/issues/7780 */ + .euiDataGridRowCell__content--lineCountHeight { + ${logicalCSS('padding-bottom', 0)} + ${logicalCSS( + 'border-bottom', + `${cellPadding[size]} solid transparent` + )} + } + `, + get s() { + return css(this.cellPadding('s')); + }, + get m() { + return css(this.cellPadding('m')); + }, + get l() { + return css(this.cellPadding('l')); + }, + }, + fontSize: { + fontSize: (size: 's' | 'm') => css` + .euiDataGridHeaderCell, + .euiDataGridRowCell { + font-size: ${fontSize[size]}; + line-height: ${lineHeight[size]}; + } + `, + get s() { + return css(this.fontSize('s')); + }, + get m() { + return css(this.fontSize('m')); + }, + get l() { + // On the Amsterdam theme, the l fontSize is the same as m + return css(this.fontSize('m')); + }, + }, + borders: { + none: null, + horizontal: css` + label: borders; + + .euiDataGridRowCell:not(.euiDataGridFooterCell), + .euiDataGridFooter, + &:not(.euiDataGrid--headerUnderline) .euiDataGridHeader { + ${logicalCSS('border-bottom', euiTheme.border.thin)} + } + + &:not(.euiDataGrid--footerOverline) .euiDataGridFooter { + ${logicalCSS('border-top', euiTheme.border.thin)} + ${logicalCSS('margin-top', `-${euiTheme.border.width.thin}`)} + } + + .euiDataGridHeader { + ${logicalCSS('border-top', euiTheme.border.thin)} + } + `, + all: css` + label: borders; + + .euiDataGridRowCell { + &:not(.euiDataGridFooterCell) { + ${logicalCSS('border-bottom', euiTheme.border.thin)} + ${logicalCSS( + 'border-right', + // Visually lighten vertical borders + `${euiTheme.border.width.thin} solid ${tintOrShade( + euiTheme.border.color, + 0.3, + colorMode + )}` + )} + } + + &--firstColumn { + ${logicalCSS('border-left', euiTheme.border.thin)} + } + + &--lastColumn { + ${logicalCSS('border-right-color', euiTheme.border.color)} + } + } + + .euiDataGridFooterCell, + .euiDataGridHeaderCell { + ${logicalCSS('border-right', euiTheme.border.thin)} + + &:first-of-type { + ${logicalCSS('border-left', euiTheme.border.thin)} + } + } + + .euiDataGridFooter { + ${logicalCSS('border-bottom', euiTheme.border.thin)} + } + + &:not(.euiDataGrid--footerOverline) .euiDataGridFooter { + ${logicalCSS('border-top', euiTheme.border.thin)} + ${logicalCSS('margin-top', `-${euiTheme.border.width.thin}`)} + } + + &:not(.euiDataGrid--headerUnderline) .euiDataGridHeader { + ${logicalCSS('border-bottom', euiTheme.border.thin)} + } + + &:is(.euiDataGrid--noControls) .euiDataGridHeader { + ${logicalCSS('border-top', euiTheme.border.thin)} + } + + .euiDataGrid__controls { + border: ${euiTheme.border.thin}; + background-color: ${euiTheme.colors.body}; + } + `, + }, // Sits below the controls above it and pagination below it euiDataGrid__content: css` z-index: 1; diff --git a/packages/eui/src/components/datagrid/data_grid.tsx b/packages/eui/src/components/datagrid/data_grid.tsx index 89bd611a559..117b95457bb 100644 --- a/packages/eui/src/components/datagrid/data_grid.tsx +++ b/packages/eui/src/components/datagrid/data_grid.tsx @@ -429,6 +429,12 @@ export const EuiDataGrid = memo( ); const styles = useEuiMemoizedStyles(euiDataGridStyles); + const cssStyles = [ + styles.euiDataGrid, + styles.cellPadding[gridStyles.cellPadding!], + styles.fontSize[gridStyles.fontSize!], + styles.borders[gridStyles.border!], + ]; return ( @@ -440,7 +446,7 @@ export const EuiDataGrid = memo( css={styles.euiDataGrid__focusWrap} >
= { + title: 'Tabular Content/EuiDataGrid/rowHeightsOptions (prop)', + component: EuiDataGridRowHeightsPropsComponent, + parameters: { + codeSnippet: { + snippet: ``, + }, + }, +}; +enableFunctionToggleControls(meta, ['onChange']); + +export default meta; +type Story = StoryObj; + +const storyArgs = { + ...defaultStorybookArgs, + width: 800, // make it easier to test wrapping text + rowCount: 5, // make VRT screenshots smaller +}; + +export const Auto: Story = { + args: { + defaultHeight: 'auto', + }, + render: (rowHeightsOptions) => ( + + ), +}; + +export const LineCount: Story = { + args: { + defaultHeight: { lineCount: 2 }, + }, + render: (rowHeightsOptions) => ( + + ), +}; + +export const StaticHeight: Story = { + args: { + defaultHeight: { height: 48 }, + }, + render: (rowHeightsOptions) => ( + + ), +}; + +export const CustomRowHeights: Story = { + parameters: { controls: { include: ['rowHeights'] } }, + args: { + rowHeights: { + 2: 'auto', + 3: 48, + 4: { + height: 56, + }, + 5: { + lineCount: 2, + }, + }, + }, + render: (rowHeightsOptions) => ( + + ), +}; + +export const CustomLineHeight: Story = { + parameters: { controls: { include: ['lineHeight'] } }, + args: { + lineHeight: '40px', + }, + render: (rowHeightsOptions) => ( + + ), +}; diff --git a/packages/eui/src/components/datagrid/data_grid_styles.stories.tsx b/packages/eui/src/components/datagrid/data_grid_styles.stories.tsx new file mode 100644 index 00000000000..715fddd8799 --- /dev/null +++ b/packages/eui/src/components/datagrid/data_grid_styles.stories.tsx @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; +import { css } from '@emotion/css'; +import { enableFunctionToggleControls } from '../../../.storybook/utils'; + +import { + StatefulDataGrid, + defaultStorybookArgs, + EuiDataGridStylePropsComponent, +} from './data_grid.stories.utils'; +import type { EuiDataGridStyle } from './data_grid_types'; + +const meta: Meta = { + title: 'Tabular Content/EuiDataGrid/gridStyle (prop)', + component: EuiDataGridStylePropsComponent, +}; + +export default meta; +type Story = StoryObj; + +const storyArgs = { + ...defaultStorybookArgs, + renderFooterCellValue: ({ columnId }: { columnId: string }) => + columnId === 'account' ? '5 accounts' : null, + height: 400, // to more easily test sticky footers +}; + +export const Playground: Story = { + parameters: { + codeSnippet: { + snippet: ``, + }, + controls: { sort: 'none' }, + }, + args: { + fontSize: 'm', + cellPadding: 'm', + border: 'all', + header: 'shade', + footer: 'striped', + stripes: true, + stickyFooter: true, + rowHover: 'highlight', + rowClasses: { + 1: css` + label: warning; + background-color: rgba(255, 0, 0, 0.1); + `, + }, + }, + render: (gridStyle: EuiDataGridStyle) => ( + + ), +}; +enableFunctionToggleControls(Playground, ['onChange']); + +/** + * VRT only + */ + +export const HorizontalLines: Story = { + tags: ['vrt-only'], + args: { + border: 'horizontal', + header: 'shade', + footer: 'shade', + }, + render: (gridStyle) => ( + + ), +}; + +export const Minimal: Story = { + tags: ['vrt-only'], + args: { + border: 'none', + header: 'underline', + footer: 'overline', + rowHover: 'none', + stickyFooter: false, + }, + render: (gridStyle) => ( + + ), +}; + +export const Compact: Story = { + tags: ['vrt-only'], + args: { + fontSize: 's', + cellPadding: 's', + }, + render: (gridStyle) => ( + + ), +}; + +export const Expanded: Story = { + tags: ['vrt-only'], + args: { + fontSize: 'l', + cellPadding: 'l', + }, + render: (gridStyle) => ( + + ), +}; diff --git a/packages/eui/src/components/datagrid/data_grid_types.ts b/packages/eui/src/components/datagrid/data_grid_types.ts index 162cc900215..33cc33d45e1 100644 --- a/packages/eui/src/components/datagrid/data_grid_types.ts +++ b/packages/eui/src/components/datagrid/data_grid_types.ts @@ -142,6 +142,7 @@ export interface EuiDataGridHeaderRowPropsSpecificProps { setColumnWidth: (columnId: string, width: number) => void; setVisibleColumns: (columnId: string[]) => void; switchColumnPos: (colFromId: string, colToId: string) => void; + gridStyles: EuiDataGridStyle; } export type EuiDataGridHeaderRowProps = CommonProps & @@ -151,7 +152,7 @@ export type EuiDataGridHeaderRowProps = CommonProps & export interface EuiDataGridHeaderCellProps extends Omit< EuiDataGridHeaderRowPropsSpecificProps, - 'leadingControlColumns' + 'leadingControlColumns' | 'gridStyles' > { column: EuiDataGridColumn; index: number; @@ -186,6 +187,7 @@ export type EuiDataGridFooterRowProps = CommonProps & renderCellPopover?: EuiDataGridCellProps['renderCellPopover']; interactiveCellId: EuiDataGridCellProps['interactiveCellId']; visibleRowIndex?: number; + gridStyles: EuiDataGridStyle; }; export interface EuiDataGridVisibleRows { @@ -629,7 +631,7 @@ export interface EuiDataGridCellProps { | ((props: EuiDataGridCellPopoverElementProps) => ReactNode); setRowHeight?: (height: number) => void; getRowHeight?: (rowIndex: number) => number; - style?: React.CSSProperties; + style?: CSSProperties; rowHeightsOptions?: EuiDataGridRowHeightsOptions; rowHeightUtils?: RowHeightUtilsType; rowManager?: EuiDataGridRowManager; @@ -829,34 +831,42 @@ export type EuiDataGridStyleCellPaddings = 's' | 'm' | 'l'; export interface EuiDataGridStyle { /** * Size of fonts used within the row and column cells + * @default m */ fontSize?: EuiDataGridStyleFontSizes; /** * Defines the padding with the row and column cells + * @default m */ cellPadding?: EuiDataGridStyleCellPaddings; /** - * Border uses for the row and column cells + * Border used for the row and column cells + * @default all */ border?: EuiDataGridStyleBorders; /** * If set to true, rows will alternate zebra striping for clarity + * @default false */ stripes?: boolean; /** * Visual style for the column headers. Recommendation is to use the `underline` style in times when #EuiDataGrid `toolbarVisibility` is set to `false`. + * @default shade */ header?: EuiDataGridStyleHeader; /** * Visual style for the column footers. + * @default overline */ footer?: EuiDataGridStyleFooter; /** * If set to true, the footer row will be sticky + * @default true */ stickyFooter?: boolean; /** * Will define what visual style to show on row hover + * @default hover */ rowHover?: EuiDataGridStyleRowHover; /** @@ -903,6 +913,7 @@ export interface EuiDataGridToolBarVisibilityDisplaySelectorOptions { export interface EuiDataGridToolBarVisibilityOptions { /** * Allows the ability for the user to hide fields and sort columns, boolean or a #EuiDataGridToolBarVisibilityColumnSelectorOptions + * @default true */ showColumnSelector?: | boolean @@ -910,21 +921,25 @@ export interface EuiDataGridToolBarVisibilityOptions { /** * Allows the ability for the user to customize display settings such as grid density and row heights. * User changes will override what is provided in #EuiDataGridStyle and #EuiDataGridRowHeightsOptions + * @default true */ showDisplaySelector?: | boolean | EuiDataGridToolBarVisibilityDisplaySelectorOptions; /** * Allows the ability for the user to sort rows based upon column values + * @default true */ showSortSelector?: boolean; /** * Displays a popover listing all keyboard controls and shortcuts for the data grid. * If set to `false`, the toggle will be visually hidden, but still focusable by keyboard and screen reader users. + * @default true */ showKeyboardShortcuts?: boolean; /** * Allows user to be able to fullscreen the data grid. If set to `false` make sure your grid fits within a large enough panel to still show the other controls. + * @default true */ showFullScreenSelector?: boolean; /** diff --git a/packages/eui/src/components/datagrid/utils/row_heights.test.ts b/packages/eui/src/components/datagrid/utils/row_heights.test.ts index 17c542a8212..200e40e6762 100644 --- a/packages/eui/src/components/datagrid/utils/row_heights.test.ts +++ b/packages/eui/src/components/datagrid/utils/row_heights.test.ts @@ -12,7 +12,6 @@ import { renderHook } from '../../../test/rtl'; import { startingStyles } from '../controls'; import type { ImperativeGridApi } from '../data_grid_types'; import { - cellPaddingsMap, RowHeightUtils, RowHeightVirtualizationUtils, useRowHeightUtils, @@ -162,20 +161,35 @@ describe('RowHeightUtils', () => { describe('styles utils', () => { describe('cacheStyles', () => { + const mockCellPaddingsMap = { + s: '4px', + m: '6px', + l: '8px', + }; + it('stores a styles instance variable based on the grid density', () => { - Object.entries(cellPaddingsMap).forEach(([densitySize, padding]) => { - rowHeightUtils.cacheStyles({ cellPadding: densitySize as any }); - - // @ts-ignore this var is private, but we're inspecting it for the sake of the unit test - expect(rowHeightUtils.styles).toEqual({ - paddingTop: padding, - paddingBottom: padding, - }); - }); + Object.entries(mockCellPaddingsMap).forEach( + ([densitySize, paddingStyle]) => { + const expectedPadding = parseFloat(paddingStyle); + + rowHeightUtils.cacheStyles( + { cellPadding: densitySize as any }, + mockCellPaddingsMap + ); + // @ts-ignore this var is private, but we're inspecting it for the sake of the unit test + expect(rowHeightUtils.styles).toEqual({ + paddingTop: expectedPadding, + paddingBottom: expectedPadding, + }); + } + ); }); it('falls back to m-sized cellPadding if gridStyle.cellPadding is undefined', () => { - rowHeightUtils.cacheStyles({ cellPadding: undefined }); + rowHeightUtils.cacheStyles( + { cellPadding: undefined }, + mockCellPaddingsMap + ); // @ts-ignore this var is private, but we're inspecting it for the sake of the unit test expect(rowHeightUtils.styles).toEqual({ @@ -220,9 +234,10 @@ describe('RowHeightUtils', () => { describe('calculateHeightForLineCount', () => { let getComputedStyleSpy: jest.SpyInstance; const cell = document.createElement('div'); + const mockCellPaddingsMap = { s: '', m: '6px', l: '' }; beforeEach(() => { - rowHeightUtils.cacheStyles({ cellPadding: 'm' }); + rowHeightUtils.cacheStyles({ cellPadding: 'm' }, mockCellPaddingsMap); getComputedStyleSpy = jest .spyOn(window, 'getComputedStyle') .mockReturnValue({ lineHeight: '24px' } as CSSStyleDeclaration); diff --git a/packages/eui/src/components/datagrid/utils/row_heights.ts b/packages/eui/src/components/datagrid/utils/row_heights.ts index a58697b40ff..8e0acacf48b 100644 --- a/packages/eui/src/components/datagrid/utils/row_heights.ts +++ b/packages/eui/src/components/datagrid/utils/row_heights.ts @@ -15,7 +15,11 @@ import { useState, } from 'react'; import { GridOnItemsRenderedProps } from 'react-window'; -import { useForceRender, useLatest } from '../../../services'; +import { + useForceRender, + useLatest, + useEuiMemoizedStyles, +} from '../../../services'; import { isNumber, isObject } from '../../../services/predicate'; import { EuiDataGridColumn, @@ -23,18 +27,11 @@ import { EuiDataGridRowHeightsOptions, EuiDataGridScrollAnchorRow, EuiDataGridStyle, - EuiDataGridStyleCellPaddings, ImperativeGridApi, } from '../data_grid_types'; +import { euiDataGridVariables } from '../data_grid.styles'; import { DataGridSortedContext } from './sorting'; -// TODO: Once JS variables are available, use them here instead of hard-coded maps -export const cellPaddingsMap: Record = { - s: 4, - m: 6, - l: 8, -}; - export const AUTO_HEIGHT = 'auto'; export const DEFAULT_ROW_HEIGHT = 34; @@ -99,10 +96,16 @@ export class RowHeightUtils { paddingBottom: 0, }; - cacheStyles(gridStyles: EuiDataGridStyle) { + cacheStyles( + gridStyles: EuiDataGridStyle, + cellPaddingsMap: ReturnType['cellPadding'] + ) { + const paddingSize = gridStyles.cellPadding ?? 'm'; + const padding = parseFloat(cellPaddingsMap[paddingSize]); + this.styles = { - paddingTop: cellPaddingsMap[gridStyles.cellPadding || 'm'], - paddingBottom: cellPaddingsMap[gridStyles.cellPadding || 'm'], + paddingTop: padding, + paddingBottom: padding, }; } @@ -378,11 +381,13 @@ export const useRowHeightUtils = ({ ]); // Re-cache styles whenever grid density changes + const styleVars = useEuiMemoizedStyles(euiDataGridVariables); useEffect(() => { - rowHeightUtils.cacheStyles({ - cellPadding: gridStyles.cellPadding, - }); - }, [gridStyles.cellPadding, rowHeightUtils]); + rowHeightUtils.cacheStyles( + { cellPadding: gridStyles.cellPadding }, + styleVars.cellPadding + ); + }, [gridStyles.cellPadding, rowHeightUtils, styleVars.cellPadding]); // Update row heights map to remove hidden columns whenever orderedVisibleColumns change useEffect(() => { diff --git a/packages/eui/src/themes/amsterdam/overrides/_data_grid.scss b/packages/eui/src/themes/amsterdam/overrides/_data_grid.scss deleted file mode 100644 index f885899ef9c..00000000000 --- a/packages/eui/src/themes/amsterdam/overrides/_data_grid.scss +++ /dev/null @@ -1,5 +0,0 @@ -@include euiDataGridStyles(fontSizeLarge) { - @include euiDataGridRowCell { - @include euiFontSizeM; - } -} diff --git a/packages/eui/src/themes/amsterdam/overrides/_index.scss b/packages/eui/src/themes/amsterdam/overrides/_index.scss deleted file mode 100644 index 357b92614aa..00000000000 --- a/packages/eui/src/themes/amsterdam/overrides/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'data_grid'; diff --git a/packages/eui/src/themes/amsterdam/theme_dark.scss b/packages/eui/src/themes/amsterdam/theme_dark.scss index ec8e0e97075..b18ac759e36 100644 --- a/packages/eui/src/themes/amsterdam/theme_dark.scss +++ b/packages/eui/src/themes/amsterdam/theme_dark.scss @@ -6,7 +6,3 @@ // Components @import '../../components/index'; - -// Component overrides -// Comes after the component import and overrides via cascade -@import './overrides/index'; diff --git a/packages/eui/src/themes/amsterdam/theme_light.scss b/packages/eui/src/themes/amsterdam/theme_light.scss index 27c77c31192..504e8bc600a 100644 --- a/packages/eui/src/themes/amsterdam/theme_light.scss +++ b/packages/eui/src/themes/amsterdam/theme_light.scss @@ -6,7 +6,3 @@ // Components @import '../../components/index'; - -// Component overrides -// Comes after the component import and overrides via cascade -@import './overrides/index';