From 9ab846f7b85172e00c34bf91275991dbab65a79e Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Thu, 15 Aug 2019 08:38:44 -0700 Subject: [PATCH 01/28] style selector dropdown uses hooks, new icon added, full screen mode --- src-docs/src/views/datagrid/datagrid.js | 2 +- src-docs/src/views/icon/icons.js | 3 + src/components/datagrid/_data_grid.scss | 14 ++- src/components/datagrid/column_selector.tsx | 7 +- src/components/datagrid/data_grid.tsx | 70 ++++++----- src/components/datagrid/data_grid_types.ts | 15 +++ src/components/datagrid/style_selector.tsx | 114 ++++++++++++++++++ .../icon/assets/table_density_comfortable.js | 14 +++ .../icon/assets/table_density_comfortable.svg | 3 + .../icon/assets/table_density_compact.js | 14 +++ .../icon/assets/table_density_compact.svg | 3 + .../icon/assets/table_density_normal.js | 14 +++ .../icon/assets/table_density_normal.svg | 3 + src/components/icon/icon.tsx | 3 + 14 files changed, 238 insertions(+), 41 deletions(-) create mode 100644 src/components/datagrid/style_selector.tsx create mode 100644 src/components/icon/assets/table_density_comfortable.js create mode 100644 src/components/icon/assets/table_density_comfortable.svg create mode 100644 src/components/icon/assets/table_density_compact.js create mode 100644 src/components/icon/assets/table_density_compact.svg create mode 100644 src/components/icon/assets/table_density_normal.js create mode 100644 src/components/icon/assets/table_density_normal.svg diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index a6594475771..449a7c298fc 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -229,7 +229,7 @@ export default class DataGrid extends Component { ]; this.state = { - borderSelected: 'all', + borderSelected: 'none', fontSizeSelected: 'm', cellPaddingSelected: 'm', stripes: false, diff --git a/src-docs/src/views/icon/icons.js b/src-docs/src/views/icon/icons.js index 79dd1154109..6962bd48017 100644 --- a/src-docs/src/views/icon/icons.js +++ b/src-docs/src/views/icon/icons.js @@ -164,6 +164,9 @@ const iconTypes = [ 'submodule', 'symlink', 'tableOfContents', + 'tableDensityComfortable', + 'tableDensityCompact', + 'tableDensityNormal', 'tag', 'tear', 'temperature', diff --git a/src/components/datagrid/_data_grid.scss b/src/components/datagrid/_data_grid.scss index 983544e2990..8a11e336a96 100644 --- a/src/components/datagrid/_data_grid.scss +++ b/src/components/datagrid/_data_grid.scss @@ -1,11 +1,22 @@ +.euiDataGrid--fullScreen { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: $euiZModal; + background: $euiColorEmptyShade; +} + .euiDataGrid__content { @include euiScrollBar; + font-feature-settings: 'tnum' 1; // Tabular numbers overflow-x: auto; scroll-padding: 0; max-width: 100%; width: 100%; - background: $euiColorLightestShade; + background: $euiPageBackgroundColor; } .euiDataGrid__controls { @@ -16,4 +27,5 @@ border-top: $euiBorderThin; border-right: $euiBorderThin; border-left: $euiBorderThin; + padding: $euiSizeXS; } \ No newline at end of file diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index 8cea5046078..17a47f5e34b 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -58,10 +58,11 @@ export const useColumnSelector = ( button={ setIsOpen(!isOpen)}> - Columns + Fields }> diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index d0acbc557e3..0d86f789cc3 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -6,7 +6,6 @@ import React, { useState, useRef, useEffect, - Fragment, } from 'react'; import classNames from 'classnames'; import { EuiDataGridHeaderRow } from './data_grid_header_row'; @@ -15,31 +14,24 @@ import { EuiDataGridColumn, EuiDataGridColumnWidths, EuiDataGridPaginationProps, + EuiDataGridStyle, + EuiDataGridStyleBorders, + EuiDataGridStyleCellPaddings, + EuiDataGridStyleFontSizes, + EuiDataGridStyleHeader, + EuiDataGridStyleRowHover, } from './data_grid_types'; import { EuiDataGridCellProps } from './data_grid_cell'; import { keyCodes } from '../../services'; import { EuiSpacer } from '../spacer'; +// @ts-ignore-next-line +import { EuiButtonEmpty } from '../button'; import { EuiDataGridBody } from './data_grid_body'; import { useColumnSelector } from './column_selector'; +import { useStyleSelector } from './style_selector'; // @ts-ignore-next-line import { EuiTablePagination } from '../table/table_pagination'; -// Types for styling options, passed down through the `gridStyle` prop -type EuiDataGridStyleFontSizes = 's' | 'm' | 'l'; -type EuiDataGridStyleBorders = 'all' | 'horizontal' | 'none'; -type EuiDataGridStyleHeader = 'shade' | 'underline'; -type EuiDataGridStyleRowHover = 'highlight' | 'none'; -type EuiDataGridStyleCellPaddings = 's' | 'm' | 'l'; - -interface EuiDataGridStyle { - fontSize?: EuiDataGridStyleFontSizes; - border?: EuiDataGridStyleBorders; - stripes?: boolean; - header?: EuiDataGridStyleHeader; - rowHover?: EuiDataGridStyleRowHover; - cellPadding?: EuiDataGridStyleCellPaddings; -} - type CommonGridProps = CommonProps & HTMLAttributes & { columns: EuiDataGridColumn[]; @@ -153,6 +145,8 @@ export const EuiDataGrid: FunctionComponent = props => { } }, []); + const [isFullScreen, setIsFullScreen] = useState(false); + const [focusedCell, setFocusedCell] = useState<[number, number]>(ORIGIN); const onCellFocus = useCallback( (x: number, y: number) => { @@ -200,37 +194,42 @@ export const EuiDataGrid: FunctionComponent = props => { rowCount, renderCellValue, className, - gridStyle = {}, + gridStyle, pagination, ...rest } = props; - const fontSize = gridStyle.fontSize || 'm'; - const border = gridStyle.border || 'all'; - const header = gridStyle.header || 'shade'; - const rowHover = gridStyle.rowHover || 'highlight'; - const stripes = gridStyle.stripes ? true : false; - const cellPadding = gridStyle.cellPadding || 'm'; + const [ColumnSelector, visibleColumns] = useColumnSelector(columns); + const [StyleSelector, gridStyles] = useStyleSelector(gridStyle); const classes = classNames( 'euiDataGrid', - fontSizesToClassMap[fontSize], - bordersToClassMap[border], - headerToClassMap[header], - rowHoverToClassMap[rowHover], - cellPaddingsToClassMap[cellPadding], + fontSizesToClassMap[gridStyles.fontSize || 'm'], + bordersToClassMap[gridStyles.border || 'all'], + headerToClassMap[gridStyles.header || 'shade'], + rowHoverToClassMap[gridStyles.rowHover || 'highlight'], + cellPaddingsToClassMap[gridStyles.cellPadding || 'm'], + { + 'euiDataGrid--stripes': gridStyles.stripes || false, + }, { - 'euiDataGrid--stripes': stripes, + 'euiDataGrid--fullScreen': isFullScreen, }, className ); - const [ColumnSelector, visibleColumns] = useColumnSelector(columns); - return ( - +
+ + setIsFullScreen(!isFullScreen)}> + Full screen +
{/* Unsure why this element causes errors as focus follows spec */} {/* eslint-disable-next-line jsx-a11y/interactive-supports-focus */} @@ -239,8 +238,7 @@ export const EuiDataGrid: FunctionComponent = props => { onKeyDown={handleKeyDown} ref={gridRef} // {...label} - {...rest} - className={classes}> + {...rest}>
= props => { {renderPagination(props)}
- +
); }; diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index a332e02ebfd..e31f5ae9ae7 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -16,3 +16,18 @@ export interface EuiDataGridPaginationProps { onChangeItemsPerPage: (itemsPerPage: number) => void; onChangePage: (pageIndex: number) => void; } +// Types for styling options, passed down through the `gridStyle` prop +export type EuiDataGridStyleFontSizes = 's' | 'm' | 'l'; +export type EuiDataGridStyleBorders = 'all' | 'horizontal' | 'none'; +export type EuiDataGridStyleHeader = 'shade' | 'underline'; +export type EuiDataGridStyleRowHover = 'highlight' | 'none'; +export type EuiDataGridStyleCellPaddings = 's' | 'm' | 'l'; + +export interface EuiDataGridStyle { + fontSize: EuiDataGridStyleFontSizes; + border: EuiDataGridStyleBorders; + stripes: boolean; + header: EuiDataGridStyleHeader; + rowHover: EuiDataGridStyleRowHover; + cellPadding: EuiDataGridStyleCellPaddings; +} diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx new file mode 100644 index 00000000000..6d8385d38ea --- /dev/null +++ b/src/components/datagrid/style_selector.tsx @@ -0,0 +1,114 @@ +import React, { FunctionComponent, useState } from 'react'; +import { EuiDataGridStyle } from './data_grid_types'; +// @ts-ignore-next-line +import { EuiPopover } from '../popover'; +// @ts-ignore-next-line +import { EuiButtonEmpty } from '../button'; +// @ts-ignore-next-line +import { EuiButtonGroup } from '../button'; + +export const useStyleSelector = ( + initialStyles: EuiDataGridStyle = { + cellPadding: 'm', + fontSize: 'm', + border: 'all', + stripes: false, + rowHover: 'highlight', + header: 'shade', + } +): [FunctionComponent, EuiDataGridStyle] => { + const [gridStyles, setGridStyles] = useState(initialStyles); + + const [isOpen, setIsOpen] = useState(false); + + const [gridDensity, setGridDensity] = useState('normal'); + + const comfortable: EuiDataGridStyle = { + cellPadding: 'l', + fontSize: 'l', + border: 'all', + stripes: false, + rowHover: 'highlight', + header: 'shade', + }; + + const normal: EuiDataGridStyle = { + cellPadding: 'm', + fontSize: 'm', + border: 'all', + stripes: false, + rowHover: 'highlight', + header: 'shade', + }; + + const compact: EuiDataGridStyle = { + cellPadding: 's', + fontSize: 's', + border: 'all', + stripes: false, + rowHover: 'highlight', + header: 'shade', + }; + + const densityOptions = [ + { + id: 'tableDensityComfortable', + label: 'Table density comfortable', + iconType: 'tableDensityComfortable', + density: comfortable, + }, + { + id: 'tableDensityNormal', + label: 'Table density normal', + iconType: 'tableDensityNormal', + density: normal, + }, + { + id: 'tableDensityCompact', + label: 'Table density compact', + iconType: 'tableDensityCompact', + density: compact, + }, + ]; + + const onChangeDensity = (optionId: any) => { + setGridDensity(optionId); + + const selectedDensity = densityOptions.filter(options => { + return options.id == optionId; + })[0]; + setGridStyles(selectedDensity.density); + }; + + const StyleSelector = () => ( + setIsOpen(false)} + anchorPosition="downCenter" + panelPaddingSize="s" + ownFocus + panelClassName="euiDataGridColumnSelectorPopover" + button={ + setIsOpen(!isOpen)}> + Density + + }> + + + ); + + return [StyleSelector, gridStyles]; +}; diff --git a/src/components/icon/assets/table_density_comfortable.js b/src/components/icon/assets/table_density_comfortable.js new file mode 100644 index 00000000000..0350391c812 --- /dev/null +++ b/src/components/icon/assets/table_density_comfortable.js @@ -0,0 +1,14 @@ +import React from 'react'; + +const EuiIconTableDensityComfortable = props => ( + + + +); + +export const icon = EuiIconTableDensityComfortable; diff --git a/src/components/icon/assets/table_density_comfortable.svg b/src/components/icon/assets/table_density_comfortable.svg new file mode 100644 index 00000000000..b465916216d --- /dev/null +++ b/src/components/icon/assets/table_density_comfortable.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/icon/assets/table_density_compact.js b/src/components/icon/assets/table_density_compact.js new file mode 100644 index 00000000000..e9dd4483e32 --- /dev/null +++ b/src/components/icon/assets/table_density_compact.js @@ -0,0 +1,14 @@ +import React from 'react'; + +const EuiIconTableDensityCompact = props => ( + + + +); + +export const icon = EuiIconTableDensityCompact; diff --git a/src/components/icon/assets/table_density_compact.svg b/src/components/icon/assets/table_density_compact.svg new file mode 100644 index 00000000000..79329247a6f --- /dev/null +++ b/src/components/icon/assets/table_density_compact.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/icon/assets/table_density_normal.js b/src/components/icon/assets/table_density_normal.js new file mode 100644 index 00000000000..2d92f3bba24 --- /dev/null +++ b/src/components/icon/assets/table_density_normal.js @@ -0,0 +1,14 @@ +import React from 'react'; + +const EuiIconTableDensityNormal = props => ( + + + +); + +export const icon = EuiIconTableDensityNormal; diff --git a/src/components/icon/assets/table_density_normal.svg b/src/components/icon/assets/table_density_normal.svg new file mode 100644 index 00000000000..aa9b43c2d8c --- /dev/null +++ b/src/components/icon/assets/table_density_normal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/icon/icon.tsx b/src/components/icon/icon.tsx index 2da808dc7f1..0f559682978 100644 --- a/src/components/icon/icon.tsx +++ b/src/components/icon/icon.tsx @@ -286,6 +286,9 @@ const typeToPathMap = { swatchInput: 'swatch_input', // Undocumented on purpose. Has an extra stroke for EuiColorPicker symlink: 'symlink', tableOfContents: 'tableOfContents', + tableDensityComfortable: 'table_density_comfortable', + tableDensityCompact: 'table_density_compact', + tableDensityNormal: 'table_density_normal', tag: 'tag', tear: 'tear', temperature: 'temperature', From 5842787c34f39fb61956cbcd52926cb48cdaf74f Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Thu, 15 Aug 2019 09:16:21 -0700 Subject: [PATCH 02/28] snaps --- .../__snapshots__/data_grid.test.tsx.snap | 70 +++++++++++++++++-- .../icon/__snapshots__/icon.test.tsx.snap | 45 ++++++++++++ 2 files changed, 108 insertions(+), 7 deletions(-) diff --git a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap index a6815af58ad..9321ccf5e6a 100644 --- a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap +++ b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap @@ -119,7 +119,9 @@ exports[`EuiDataGrid pagination renders 1`] = ` `; exports[`EuiDataGrid rendering renders with common and div attributes 1`] = ` -Array [ +
@@ -131,7 +133,7 @@ Array [ class="euiPopover__anchor" >
- , +
+
+ +
+
+ +
@@ -270,6 +326,6 @@ Array [
-
, -] +
+ `; diff --git a/src/components/icon/__snapshots__/icon.test.tsx.snap b/src/components/icon/__snapshots__/icon.test.tsx.snap index d1c1662a4b8..d29dc4a0d25 100644 --- a/src/components/icon/__snapshots__/icon.test.tsx.snap +++ b/src/components/icon/__snapshots__/icon.test.tsx.snap @@ -5880,6 +5880,51 @@ exports[`EuiIcon props type symlink is rendered 1`] = ` `; +exports[`EuiIcon props type tableDensityComfortable is rendered 1`] = ` + + + +`; + +exports[`EuiIcon props type tableDensityCompact is rendered 1`] = ` + + + +`; + +exports[`EuiIcon props type tableDensityNormal is rendered 1`] = ` + + + +`; + exports[`EuiIcon props type tableOfContents is rendered 1`] = ` Date: Thu, 15 Aug 2019 12:59:53 -0500 Subject: [PATCH 03/28] setState return --- src/components/datagrid/data_grid.tsx | 9 ++++++++- src/components/datagrid/style_selector.tsx | 21 ++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 0d86f789cc3..f27be934388 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -200,7 +200,14 @@ export const EuiDataGrid: FunctionComponent = props => { } = props; const [ColumnSelector, visibleColumns] = useColumnSelector(columns); - const [StyleSelector, gridStyles] = useStyleSelector(gridStyle); + const [StyleSelector, gridStyles, setGridStyles] = useStyleSelector( + gridStyle + ); + useEffect(() => { + if (gridStyle) { + setGridStyles(gridStyle); + } + }, [gridStyle]); const classes = classNames( 'euiDataGrid', diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx index 6d8385d38ea..58e319af593 100644 --- a/src/components/datagrid/style_selector.tsx +++ b/src/components/datagrid/style_selector.tsx @@ -1,11 +1,14 @@ -import React, { FunctionComponent, useState } from 'react'; +import React, { + Dispatch, + FunctionComponent, + SetStateAction, + useState, +} from 'react'; import { EuiDataGridStyle } from './data_grid_types'; // @ts-ignore-next-line import { EuiPopover } from '../popover'; // @ts-ignore-next-line -import { EuiButtonEmpty } from '../button'; -// @ts-ignore-next-line -import { EuiButtonGroup } from '../button'; +import { EuiButtonEmpty, EuiButtonGroup } from '../button'; export const useStyleSelector = ( initialStyles: EuiDataGridStyle = { @@ -16,7 +19,11 @@ export const useStyleSelector = ( rowHover: 'highlight', header: 'shade', } -): [FunctionComponent, EuiDataGridStyle] => { +): [ + FunctionComponent, + EuiDataGridStyle, + Dispatch> +] => { const [gridStyles, setGridStyles] = useState(initialStyles); const [isOpen, setIsOpen] = useState(false); @@ -75,7 +82,7 @@ export const useStyleSelector = ( setGridDensity(optionId); const selectedDensity = densityOptions.filter(options => { - return options.id == optionId; + return options.id === optionId; })[0]; setGridStyles(selectedDensity.density); }; @@ -110,5 +117,5 @@ export const useStyleSelector = ( ); - return [StyleSelector, gridStyles]; + return [StyleSelector, gridStyles, setGridStyles]; }; From 0afdb3f823cfe3154dd8c03a2817748e60007acd Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Thu, 15 Aug 2019 23:51:56 -0700 Subject: [PATCH 04/28] full screen kinda. need to rework a lot of this. just playing with concepts --- package.json | 1 + src-docs/src/views/datagrid/datagrid.js | 151 ++------ .../__snapshots__/data_grid.test.tsx.snap | 347 ++++++++++-------- src/components/datagrid/_data_grid.scss | 45 ++- .../datagrid/_data_grid_data_row.scss | 40 +- src/components/datagrid/column_selector.tsx | 23 +- src/components/datagrid/data_grid.tsx | 95 +++-- src/components/datagrid/data_grid_cell.tsx | 4 +- yarn.lock | 5 + 9 files changed, 366 insertions(+), 345 deletions(-) diff --git a/package.json b/package.json index b834384fe05..0cdff1e15cf 100644 --- a/package.json +++ b/package.json @@ -126,6 +126,7 @@ "eslint-plugin-prefer-object-spread": "^1.2.1", "eslint-plugin-prettier": "^3.1.0", "eslint-plugin-react": "^7.13.0", + "faker": "^4.1.0", "file-loader": "^1.1.11", "findup": "^0.1.5", "fork-ts-checker-webpack-plugin": "^0.4.4", diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index 449a7c298fc..12a697829fd 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -1,4 +1,5 @@ import React, { Component } from 'react'; +import { fake } from 'faker'; import { EuiDataGrid, @@ -7,146 +8,48 @@ import { EuiFormRow, EuiPopover, EuiButton, + EuiAvatar, } from '../../../../src/components/'; const columns = [ { - id: 'name', - }, - { - id: 'avatar_url', - }, - { - id: 'url', - }, - { - id: 'contributions', - }, -]; - -const data = [ - { - name: 'cjcenizal', - avatar_url: 'https://avatars2.githubusercontent.com/u/1238659?v=4', - url: 'https://api.github.com/users/cjcenizal', - contributions: 392, + id: 'avatar', }, { - name: 'snide', - avatar_url: 'https://avatars3.githubusercontent.com/u/324519?v=4', - url: 'https://api.github.com/users/snide', - contributions: 361, - }, - { - name: 'chandlerprall', - avatar_url: 'https://avatars3.githubusercontent.com/u/313125?v=4', - url: 'https://api.github.com/users/chandlerprall', - contributions: 274, - }, - { - name: 'cchaos', - avatar_url: 'https://avatars3.githubusercontent.com/u/549577?v=4', - url: 'https://api.github.com/users/cchaos', - contributions: 156, - }, - { - name: 'bevacqua', - avatar_url: 'https://avatars3.githubusercontent.com/u/934293?v=4', - url: 'https://api.github.com/users/bevacqua', - contributions: 128, - }, - { - name: 'thompsongl', - avatar_url: 'https://avatars0.githubusercontent.com/u/2728212?v=4', - url: 'https://api.github.com/users/thompsongl', - contributions: 106, - }, - { - name: 'pugnascotia', - avatar_url: 'https://avatars1.githubusercontent.com/u/8696382?v=4', - url: 'https://api.github.com/users/pugnascotia', - contributions: 82, - }, - { - name: 'nreese', - avatar_url: 'https://avatars0.githubusercontent.com/u/373691?v=4', - url: 'https://api.github.com/users/nreese', - contributions: 58, - }, - { - name: 'dmeiss', - avatar_url: 'https://avatars3.githubusercontent.com/u/45879454?v=4', - url: 'https://api.github.com/users/dmeiss', - contributions: 52, - }, - { - name: 'ryankeairns', - avatar_url: 'https://avatars2.githubusercontent.com/u/446285?v=4', - url: 'https://api.github.com/users/ryankeairns', - contributions: 32, - }, - { - name: 'stacey-gammon', - avatar_url: 'https://avatars3.githubusercontent.com/u/16563603?v=4', - url: 'https://api.github.com/users/stacey-gammon', - contributions: 24, - }, - { - name: 'theodesp', - avatar_url: 'https://avatars0.githubusercontent.com/u/328805?v=4', - url: 'https://api.github.com/users/theodesp', - contributions: 22, - }, - { - name: 'uboness', - avatar_url: 'https://avatars3.githubusercontent.com/u/211019?v=4', - url: 'https://api.github.com/users/uboness', - contributions: 17, - }, - { - name: 'weltenwort', - avatar_url: 'https://avatars3.githubusercontent.com/u/973741?v=4', - url: 'https://api.github.com/users/weltenwort', - contributions: 16, - }, - { - name: 'jen-huang', - avatar_url: 'https://avatars0.githubusercontent.com/u/1965714?v=4', - url: 'https://api.github.com/users/jen-huang', - contributions: 13, - }, - { - name: 'PopradiArpad', - avatar_url: 'https://avatars3.githubusercontent.com/u/4144816?v=4', - url: 'https://api.github.com/users/PopradiArpad', - contributions: 11, + id: 'name', }, { - name: 'chrisronline', - avatar_url: 'https://avatars1.githubusercontent.com/u/56682?v=4', - url: 'https://api.github.com/users/chrisronline', - contributions: 10, + id: 'email', }, { - name: 'timroes', - avatar_url: 'https://avatars0.githubusercontent.com/u/877229?v=4', - url: 'https://api.github.com/users/timroes', - contributions: 10, + id: 'city', }, { - name: 'daveyholler', - avatar_url: 'https://avatars2.githubusercontent.com/u/739960?v=4', - url: 'https://api.github.com/users/daveyholler', - contributions: 9, + id: 'country', }, { - name: 'sqren', - avatar_url: 'https://avatars3.githubusercontent.com/u/209966?v=4', - url: 'https://api.github.com/users/sqren', - contributions: 9, + id: 'account', }, ]; +const data = []; + +for (let i = 1; i < 100; i++) { + data.push({ + avatar: ( + + ), + name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'), + email: fake('{{internet.email}}'), + city: fake('{{address.city}}'), + country: fake('{{address.country}}'), + account: fake('{{finance.account}}'), + }); +} + export default class DataGrid extends Component { constructor(props) { super(props); @@ -240,7 +143,7 @@ export default class DataGrid extends Component { pagination: { pageIndex: 0, - pageSize: 10, + pageSize: 50, }, }; } diff --git a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap index 9321ccf5e6a..f61aaf8396f 100644 --- a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap +++ b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap @@ -119,51 +119,90 @@ exports[`EuiDataGrid pagination renders 1`] = ` `; exports[`EuiDataGrid rendering renders with common and div attributes 1`] = ` -
+Array [ +
, +
,
- -
-
-
-
+ + + + Hide fields + + + +
+
+
+
+ +
+
-
- -
-
-
- A +
+
+ A +
+
+
+
+ B +
+
-
-
- B +
+ 0, A +
+
+ 0, B +
+
+
+
+ 1, A +
+
+ 1, B +
+
+
+
+ 2, A +
+
+ 2, B +
-
-
-
-
- 0, A -
-
- 0, B -
-
-
-
- 1, A -
-
- 1, B -
-
-
-
- 2, A
- 2, B -
+ class="euiSpacer euiSpacer--s" + />
-
-
-
+
, +
, +] `; diff --git a/src/components/datagrid/_data_grid.scss b/src/components/datagrid/_data_grid.scss index 8a11e336a96..bbd5609d9eb 100644 --- a/src/components/datagrid/_data_grid.scss +++ b/src/components/datagrid/_data_grid.scss @@ -1,4 +1,5 @@ .euiDataGrid--fullScreen { + height: 100%; position: fixed; top: 0; left: 0; @@ -6,6 +7,35 @@ bottom: 0; z-index: $euiZModal; background: $euiColorEmptyShade; + display: flex; + flex-direction: column; + align-items: stretch; + overflow: hidden; + + .euiDataGrid__controls { + flex-grow: 0; + } + + .euiDataGrid__pagination { + flex-grow: 0; + padding-bottom: $euiSize; + background: $euiColorLightestShade; + } + + .euiDataGrid__verticalScroll { + flex-grow: 1; + overflow-y: hidden; + height: 100%; + } + + .euiDataGrid__overflow { + overflow-y: hidden; + height: 100%; + } + + .euiDataGrid__content { + @include euiYScrollWithShadows; + } } .euiDataGrid__content { @@ -22,10 +52,23 @@ .euiDataGrid__controls { @include euiBottomShadowSmall; + background: $euiPageBackgroundColor; position: relative; z-index: 2; border-top: $euiBorderThin; border-right: $euiBorderThin; border-left: $euiBorderThin; padding: $euiSizeXS; -} \ No newline at end of file +} + +.euiDataGrid__controlBtn--active { + background: tintOrShade($euiColorSuccess, 80%, 50%); + border-radius: $euiBorderRadius; + + &:focus { + background: tintOrShade($euiColorSuccess, 80%, 50%); + } +} +.euiDataGrid__pagination { + padding-top: $euiSize; +} diff --git a/src/components/datagrid/_data_grid_data_row.scss b/src/components/datagrid/_data_grid_data_row.scss index d600af65a1b..ab8dc00109a 100644 --- a/src/components/datagrid/_data_grid_data_row.scss +++ b/src/components/datagrid/_data_grid_data_row.scss @@ -5,24 +5,42 @@ @include euiDataGridRowCell { @include euiFontSizeS; - @include euiTextTruncate; padding: $euiDataGridCellPaddingM; border-right: $euiBorderThin; + border-right-color: tintOrShade($euiBorderColor, 60%, 60%); border-bottom: $euiBorderThin; - overflow: hidden; - white-space: nowrap; flex: 0 0 auto; background: $euiColorEmptyShade; + position: relative; + align-items: center; + display: flex; &:first-of-type { border-left: $euiBorderThin; } + &:last-of-type { + border-right-color: $euiBorderColor; + } + &:focus { - @include euiFocusRing; + border: 1px solid transparent; + margin-top: -1px; + box-shadow: 0 0 0 2px $euiColorPrimary; + border-radius: 1px; z-index: 2; // Needed so it sits above potentional striping in the next row } + + &:focus:not(:first-of-type) { + padding-left: $euiDataGridCellPaddingM - 1px; + } +} + +.euiDataGridRowCell__content { + @include euiTextTruncate; + overflow: hidden; + white-space: nowrap; } // Row highlights @@ -48,14 +66,14 @@ // Border alternates @include euiDataGridStyles(bordersNone) { @include euiDataGridRowCell { - border: none; + border-color: transparent; } } @include euiDataGridStyles(bordersHorizontal) { @include euiDataGridRowCell { - border-right: none; - border-left: none; + border-right-color: transparent; + border-left-color: transparent; } } @@ -76,11 +94,19 @@ @include euiDataGridStyles(paddingSmall) { @include euiDataGridRowCell { padding: $euiDataGridCellPaddingS; + + &:focus:not(:first-of-type) { + padding-left: $euiDataGridCellPaddingS - 1px; + } } } @include euiDataGridStyles(paddingLarge) { @include euiDataGridRowCell { padding: $euiDataGridCellPaddingL; + + &:focus:not(:first-of-type) { + padding-left: $euiDataGridCellPaddingL - 1px; + } } } \ No newline at end of file diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index 17a47f5e34b..957411b1837 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -46,6 +46,8 @@ export const useColumnSelector = ( setVisibleColumns(nextVisibleColumns); } + const numberOfHiddenFields = availableColumns.length - visibleColumns.length; + const ColumnSelector = () => ( - setIsOpen(!isOpen)}> - Fields - - + 0 ? 'euiDataGrid__controlBtn--active' : null + } + onClick={() => setIsOpen(!isOpen)}> + {numberOfHiddenFields > 0 + ? `${numberOfHiddenFields} hidden fields` + : 'Hide fields'} + }> & { @@ -155,7 +156,16 @@ export const EuiDataGrid: FunctionComponent = props => { [setFocusedCell] ); - const handleKeyDown = (e: KeyboardEvent) => { + const handleGridKeyDown = (e: KeyboardEvent) => { + switch (e.keyCode) { + case keyCodes.ESCAPE: + e.preventDefault(); + setIsFullScreen(false); + break; + } + }; + + const handleGridCellsKeyDown = (e: KeyboardEvent) => { const colCount = props.columns.length - 1; const [x, y] = focusedCell; const rowCount = computeVisibleRows(props); @@ -226,45 +236,50 @@ export const EuiDataGrid: FunctionComponent = props => { ); return ( -
-
- - - setIsFullScreen(!isFullScreen)}> - Full screen - -
- {/* Unsure why this element causes errors as focus follows spec */} - {/* eslint-disable-next-line jsx-a11y/interactive-supports-focus */} -
-
- - + +
+
+ + + setIsFullScreen(!isFullScreen)}> + {isFullScreen ? 'Exit full screen' : 'Full screen'} + +
+ {/* Unsure why this element causes errors as focus follows spec */} + {/* eslint-disable-next-line jsx-a11y/interactive-supports-focus */} +
+
+
+ + +
+
- - {renderPagination(props)} +
{renderPagination(props)}
-
+ ); }; diff --git a/src/components/datagrid/data_grid_cell.tsx b/src/components/datagrid/data_grid_cell.tsx index ee929840eb4..4505731de5d 100644 --- a/src/components/datagrid/data_grid_cell.tsx +++ b/src/components/datagrid/data_grid_cell.tsx @@ -74,7 +74,9 @@ export class EuiDataGridCell extends Component< data-test-subj="dataGridRowCell" onFocus={() => onCellFocus(colIndex, rowIndex)} style={{ width: `${width}px` }}> - +
+ +
); } diff --git a/yarn.lock b/yarn.lock index 4ea8d442f83..35d9c0685c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5463,6 +5463,11 @@ eyes@0.1.x: resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= +faker@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f" + integrity sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8= + fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" From 95c48d115b81a9416ed053910a80bb7bb53dfc02 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 28 Aug 2019 15:40:54 -0700 Subject: [PATCH 05/28] cleaup. grid now works in small containers --- src-docs/src/views/datagrid/container.js | 90 +++++ src-docs/src/views/datagrid/datagrid.js | 264 ++------------- .../src/views/datagrid/datagrid_example.js | 17 +- src-docs/src/views/datagrid/styling.js | 317 ++++++++++++++++++ src/components/datagrid/_data_grid.scss | 55 +-- src/components/datagrid/data_grid.tsx | 123 ++++--- src/components/focus_trap/focus_trap.js | 4 +- 7 files changed, 544 insertions(+), 326 deletions(-) create mode 100644 src-docs/src/views/datagrid/container.js create mode 100644 src-docs/src/views/datagrid/styling.js diff --git a/src-docs/src/views/datagrid/container.js b/src-docs/src/views/datagrid/container.js new file mode 100644 index 00000000000..38e6e8cdc07 --- /dev/null +++ b/src-docs/src/views/datagrid/container.js @@ -0,0 +1,90 @@ +import React, { Component } from 'react'; +import { fake } from 'faker'; + +import { EuiDataGrid, EuiPanel } from '../../../../src/components/'; + +const columns = [ + { + id: 'name', + }, + { + id: 'email', + }, + { + id: 'city', + }, + { + id: 'country', + }, + { + id: 'account', + }, +]; + +const data = []; + +for (let i = 1; i < 100; i++) { + data.push({ + name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'), + email: fake('{{internet.email}}'), + city: fake('{{address.city}}'), + country: fake('{{address.country}}'), + account: fake('{{finance.account}}'), + }); +} + +export default class DataGridContainer extends Component { + constructor(props) { + super(props); + + this.state = { + pagination: { + pageIndex: 0, + pageSize: 50, + }, + }; + } + + setPageIndex = pageIndex => + this.setState(({ pagination }) => ({ + pagination: { ...pagination, pageIndex }, + })); + + setPageSize = pageSize => + this.setState(({ pagination }) => ({ + pagination: { ...pagination, pageSize }, + })); + + render() { + const { pagination } = this.state; + + return ( + +
+ + data[rowIndex][columnId] + } + pagination={{ + ...pagination, + pageSizeOptions: [5, 10, 25], + onChangeItemsPerPage: this.setPageSize, + onChangePage: this.setPageIndex, + }} + /> +
+
+ ); + } +} diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index 12a697829fd..d2f8b6cc416 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -1,15 +1,7 @@ import React, { Component } from 'react'; import { fake } from 'faker'; -import { - EuiDataGrid, - EuiButtonGroup, - EuiSpacer, - EuiFormRow, - EuiPopover, - EuiButton, - EuiAvatar, -} from '../../../../src/components/'; +import { EuiDataGrid, EuiAvatar } from '../../../../src/components/'; const columns = [ { @@ -50,97 +42,11 @@ for (let i = 1; i < 100; i++) { }); } -export default class DataGrid extends Component { +export default class DataGridContainer extends Component { constructor(props) { super(props); - this.borderOptions = [ - { - id: 'all', - label: 'All', - }, - { - id: 'horizontal', - label: 'Horizontal only', - }, - { - id: 'none', - label: 'None', - }, - ]; - - this.fontSizeOptions = [ - { - id: 's', - label: 'Small', - }, - { - id: 'm', - label: 'Medium', - }, - { - id: 'l', - label: 'Large', - }, - ]; - - this.cellPaddingOptions = [ - { - id: 's', - label: 'Small', - }, - { - id: 'm', - label: 'Medium', - }, - { - id: 'l', - label: 'Large', - }, - ]; - - this.stripeOptions = [ - { - id: 'true', - label: 'Stripes on', - }, - { - id: 'false', - label: 'Stripes off', - }, - ]; - - this.rowHoverOptions = [ - { - id: 'none', - label: 'None', - }, - { - id: 'highlight', - label: 'Highlight', - }, - ]; - - this.headerOptions = [ - { - id: 'shade', - label: 'Shade', - }, - { - id: 'underline', - label: 'Underline', - }, - ]; this.state = { - borderSelected: 'none', - fontSizeSelected: 'm', - cellPaddingSelected: 'm', - stripes: false, - stripesSelected: 'false', - rowHoverSelected: 'highlight', - isPopoverOpen: false, - headerSelected: 'shade', - pagination: { pageIndex: 0, pageSize: 50, @@ -148,55 +54,6 @@ export default class DataGrid extends Component { }; } - onBorderChange = optionId => { - this.setState({ - borderSelected: optionId, - }); - }; - - onFontSizeChange = optionId => { - this.setState({ - fontSizeSelected: optionId, - }); - }; - - onCellPaddingChange = optionId => { - this.setState({ - cellPaddingSelected: optionId, - }); - }; - - onStripesChange = optionId => { - this.setState({ - stripesSelected: optionId, - stripes: !this.state.stripes, - }); - }; - - onRowHoverChange = optionId => { - this.setState({ - rowHoverSelected: optionId, - }); - }; - - onHeaderChange = optionId => { - this.setState({ - headerSelected: optionId, - }); - }; - - onPopoverButtonClick() { - this.setState({ - isPopoverOpen: !this.state.isPopoverOpen, - }); - } - - closePopover() { - this.setState({ - isPopoverOpen: false, - }); - } - setPageIndex = pageIndex => this.setState(({ pagination }) => ({ pagination: { ...pagination, pageIndex }, @@ -210,104 +67,27 @@ export default class DataGrid extends Component { render() { const { pagination } = this.state; - const button = ( - - Table styling - - ); - return ( -
- -
- - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - data[rowIndex][columnId]} - pagination={{ - ...pagination, - pageSizeOptions: [5, 10, 25], - onChangeItemsPerPage: this.setPageSize, - onChangePage: this.setPageIndex, - }} - /> -
+ data[rowIndex][columnId]} + pagination={{ + ...pagination, + pageSizeOptions: [5, 10, 25], + onChangeItemsPerPage: this.setPageSize, + onChangePage: this.setPageIndex, + }} + /> ); } } diff --git a/src-docs/src/views/datagrid/datagrid_example.js b/src-docs/src/views/datagrid/datagrid_example.js index 38d1b742e91..1a44a4eacfd 100644 --- a/src-docs/src/views/datagrid/datagrid_example.js +++ b/src-docs/src/views/datagrid/datagrid_example.js @@ -9,6 +9,10 @@ import DataGrid from './datagrid'; const dataGridSource = require('!!raw-loader!./datagrid'); const dataGridHtml = renderToHtml(DataGrid); +import DataGridContainer from './container'; +const dataGridContainerSource = require('!!raw-loader!./container'); +const dataGridContainerHtml = renderToHtml(DataGridContainer); + export const DataGridExample = { title: 'Data Grid', sections: [ @@ -16,17 +20,18 @@ export const DataGridExample = { source: [ { type: GuideSectionTypes.JS, - code: dataGridSource, + code: dataGridContainerSource, }, { type: GuideSectionTypes.HTML, - code: dataGridHtml, + code: dataGridContainerHtml, }, ], - text:

EuiDataGrid

, - components: { EuiDataGrid }, - demo: , - props: { EuiDataGrid }, + title: 'DataGrid inside a container', + text:

EuiDataGrid within containers

, + components: { DataGridContainer }, + demo: , + props: { DataGridContainer }, }, ], }; diff --git a/src-docs/src/views/datagrid/styling.js b/src-docs/src/views/datagrid/styling.js new file mode 100644 index 00000000000..a9a7d324938 --- /dev/null +++ b/src-docs/src/views/datagrid/styling.js @@ -0,0 +1,317 @@ +import React, { Component } from 'react'; +import { fake } from 'faker'; + +import { + EuiDataGrid, + EuiButtonGroup, + EuiSpacer, + EuiFormRow, + EuiPopover, + EuiButton, + EuiAvatar, +} from '../../../../src/components/'; + +const columns = [ + { + id: 'avatar', + }, + { + id: 'name', + }, + { + id: 'email', + }, + { + id: 'city', + }, + { + id: 'country', + }, + { + id: 'account', + }, +]; + +const data = []; + +for (let i = 1; i < 100; i++) { + data.push({ + avatar: ( + + ), + name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'), + email: fake('{{internet.email}}'), + city: fake('{{address.city}}'), + country: fake('{{address.country}}'), + account: fake('{{finance.account}}'), + }); +} + +export default class DataGrid extends Component { + constructor(props) { + super(props); + this.borderOptions = [ + { + id: 'all', + label: 'All', + }, + { + id: 'horizontal', + label: 'Horizontal only', + }, + { + id: 'none', + label: 'None', + }, + ]; + + this.fontSizeOptions = [ + { + id: 's', + label: 'Small', + }, + { + id: 'm', + label: 'Medium', + }, + { + id: 'l', + label: 'Large', + }, + ]; + + this.cellPaddingOptions = [ + { + id: 's', + label: 'Small', + }, + { + id: 'm', + label: 'Medium', + }, + { + id: 'l', + label: 'Large', + }, + ]; + + this.stripeOptions = [ + { + id: 'true', + label: 'Stripes on', + }, + { + id: 'false', + label: 'Stripes off', + }, + ]; + + this.rowHoverOptions = [ + { + id: 'none', + label: 'None', + }, + { + id: 'highlight', + label: 'Highlight', + }, + ]; + + this.headerOptions = [ + { + id: 'shade', + label: 'Shade', + }, + { + id: 'underline', + label: 'Underline', + }, + ]; + + this.state = { + borderSelected: 'none', + fontSizeSelected: 'm', + cellPaddingSelected: 'm', + stripes: false, + stripesSelected: 'false', + rowHoverSelected: 'highlight', + isPopoverOpen: false, + headerSelected: 'shade', + + pagination: { + pageIndex: 0, + pageSize: 50, + }, + }; + } + + onBorderChange = optionId => { + this.setState({ + borderSelected: optionId, + }); + }; + + onFontSizeChange = optionId => { + this.setState({ + fontSizeSelected: optionId, + }); + }; + + onCellPaddingChange = optionId => { + this.setState({ + cellPaddingSelected: optionId, + }); + }; + + onStripesChange = optionId => { + this.setState({ + stripesSelected: optionId, + stripes: !this.state.stripes, + }); + }; + + onRowHoverChange = optionId => { + this.setState({ + rowHoverSelected: optionId, + }); + }; + + onHeaderChange = optionId => { + this.setState({ + headerSelected: optionId, + }); + }; + + onPopoverButtonClick() { + this.setState({ + isPopoverOpen: !this.state.isPopoverOpen, + }); + } + + closePopover() { + this.setState({ + isPopoverOpen: false, + }); + } + + setPageIndex = pageIndex => + this.setState(({ pagination }) => ({ + pagination: { ...pagination, pageIndex }, + })); + + setPageSize = pageSize => + this.setState(({ pagination }) => ({ + pagination: { ...pagination, pageSize }, + })); + + render() { + const { pagination } = this.state; + + const button = ( + + Table styling + + ); + + return ( +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + data[rowIndex][columnId] + } + pagination={{ + ...pagination, + pageSizeOptions: [5, 10, 25], + onChangeItemsPerPage: this.setPageSize, + onChangePage: this.setPageIndex, + }} + /> +
+
+ ); + } +} diff --git a/src/components/datagrid/_data_grid.scss b/src/components/datagrid/_data_grid.scss index bbd5609d9eb..327bb7499c4 100644 --- a/src/components/datagrid/_data_grid.scss +++ b/src/components/datagrid/_data_grid.scss @@ -1,3 +1,11 @@ +.euiDataGrid { + display: flex; + flex-direction: column; + align-items: stretch; + overflow: hidden; + height: 100%; +} + .euiDataGrid--fullScreen { height: 100%; position: fixed; @@ -7,35 +15,11 @@ bottom: 0; z-index: $euiZModal; background: $euiColorEmptyShade; - display: flex; - flex-direction: column; - align-items: stretch; - overflow: hidden; - - .euiDataGrid__controls { - flex-grow: 0; - } .euiDataGrid__pagination { - flex-grow: 0; padding-bottom: $euiSize; background: $euiColorLightestShade; } - - .euiDataGrid__verticalScroll { - flex-grow: 1; - overflow-y: hidden; - height: 100%; - } - - .euiDataGrid__overflow { - overflow-y: hidden; - height: 100%; - } - - .euiDataGrid__content { - @include euiYScrollWithShadows; - } } .euiDataGrid__content { @@ -59,6 +43,7 @@ border-right: $euiBorderThin; border-left: $euiBorderThin; padding: $euiSizeXS; + flex-grow: 0; } .euiDataGrid__controlBtn--active { @@ -71,4 +56,26 @@ } .euiDataGrid__pagination { padding-top: $euiSize; + flex-grow: 0; +} + +.euiDataGrid__verticalScroll { + flex-grow: 1; + overflow-y: hidden; + height: 100%; +} + +.euiDataGrid__overflow { + overflow-y: hidden; + height: 100%; +} + +.euiDataGrid__content { + @include euiYScrollWithShadows; +} + +// This is used to remove extra scrollbars on the body when fullscreen is enabled +.euiDataGrid__restrictBody { + height: 100vh; + overflow: hidden; } diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index f577c4e1322..cbf1835257e 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -4,8 +4,8 @@ import React, { KeyboardEvent, useCallback, useState, - useRef, useEffect, + Fragment, } from 'react'; import classNames from 'classnames'; import { EuiDataGridHeaderRow } from './data_grid_header_row'; @@ -32,6 +32,7 @@ import { useStyleSelector } from './style_selector'; import { EuiTablePagination } from '../table/table_pagination'; // @ts-ignore-next-line import { EuiFocusTrap } from '../focus_trap'; +import { EuiResizeObserver } from '../observer/resize_observer'; type CommonGridProps = CommonProps & HTMLAttributes & { @@ -122,33 +123,29 @@ function renderPagination(props: EuiDataGridProps) { } export const EuiDataGrid: FunctionComponent = props => { + const [isFullScreen, setIsFullScreen] = useState(false); + const [showGridControls, setShowGridControls] = useState(true); + const [focusedCell, setFocusedCell] = useState<[number, number]>(ORIGIN); const [columnWidths, setColumnWidths] = useState({}); const setColumnWidth = (columnId: string, width: number) => { setColumnWidths({ ...columnWidths, [columnId]: width }); }; - const gridRef = useRef(null); - - useEffect(() => { - if (gridRef.current != null) { - const gridWidth = Math.max( - gridRef.current!.clientWidth / props.columns.length, - 100 - ); - const columnWidths = props.columns.reduce( - (columnWidths: EuiDataGridColumnWidths, column) => { - columnWidths[column.id] = gridWidth; - return columnWidths; - }, - {} - ); - setColumnWidths(columnWidths); - } - }, []); - - const [isFullScreen, setIsFullScreen] = useState(false); + // This sets the original column widths to fill their container + // Additionally it hides the controls when the container is too small + const onResize = ({ width }: { width: number }) => { + const initialColumnWidths = Math.max(width / props.columns.length, 100); + const columnWidths = props.columns.reduce( + (columnWidths: EuiDataGridColumnWidths, column) => { + columnWidths[column.id] = initialColumnWidths; + return columnWidths; + }, + {} + ); + setColumnWidths(columnWidths); + setShowGridControls(width > 480); + }; - const [focusedCell, setFocusedCell] = useState<[number, number]>(ORIGIN); const onCellFocus = useCallback( (x: number, y: number) => { setFocusedCell([x, y]); @@ -156,6 +153,7 @@ export const EuiDataGrid: FunctionComponent = props => { [setFocusedCell] ); + // Using ESCAPE exists the full screen grid const handleGridKeyDown = (e: KeyboardEvent) => { switch (e.keyCode) { case keyCodes.ESCAPE: @@ -213,6 +211,7 @@ export const EuiDataGrid: FunctionComponent = props => { const [StyleSelector, gridStyles, setGridStyles] = useStyleSelector( gridStyle ); + useEffect(() => { if (gridStyle) { setGridStyles(gridStyle); @@ -235,49 +234,69 @@ export const EuiDataGrid: FunctionComponent = props => { className ); + // These grid controls will only show when there is room. Check the resize observer callback + const gridControls = ( + + + + + ); + + // When data grid is full screen, we add a class to the body to remove the extra scrollbar + if (isFullScreen) { + document.body.classList.add('euiDataGrid__restrictBody'); + } else { + document.body.classList.remove('euiDataGrid__restrictBody'); + } + return ( - +
- - + {showGridControls ? gridControls : null} setIsFullScreen(!isFullScreen)}> + onClick={() => setIsFullScreen(!isFullScreen)} + onKeyDown={handleGridKeyDown}> {isFullScreen ? 'Exit full screen' : 'Full screen'}
{/* Unsure why this element causes errors as focus follows spec */} - {/* eslint-disable-next-line jsx-a11y/interactive-supports-focus */} -
-
-
- - + {/* eslint-disable jsx-a11y/interactive-supports-focus */} + + {resizeRef => ( +
+
+
+ + +
+
-
-
+ )} + +
{renderPagination(props)}
diff --git a/src/components/focus_trap/focus_trap.js b/src/components/focus_trap/focus_trap.js index a98ac743c55..5fac7874c8c 100644 --- a/src/components/focus_trap/focus_trap.js +++ b/src/components/focus_trap/focus_trap.js @@ -90,11 +90,11 @@ export class EuiFocusTrap extends React.Component { isDisabled={isDisabled} onOutsideClick={this.handleOutsideClick}> - {children} + {children} ) : ( - {children} + {children} ); } } From a38dd47aec76c32c71ff81625d1d42ec2579820b Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 28 Aug 2019 15:58:12 -0700 Subject: [PATCH 06/28] only set column widths initially, not on resize --- src/components/datagrid/data_grid.tsx | 34 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index cbf1835257e..d40ec68939f 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -5,6 +5,7 @@ import React, { useCallback, useState, useEffect, + useRef, Fragment, } from 'react'; import classNames from 'classnames'; @@ -132,17 +133,26 @@ export const EuiDataGrid: FunctionComponent = props => { }; // This sets the original column widths to fill their container - // Additionally it hides the controls when the container is too small + const containerRef = useRef(null); + useEffect(() => { + if (containerRef.current != null) { + const gridWidth = Math.max( + containerRef.current!.clientWidth / props.columns.length, + 100 + ); + const columnWidths = props.columns.reduce( + (columnWidths: EuiDataGridColumnWidths, column) => { + columnWidths[column.id] = gridWidth; + return columnWidths; + }, + {} + ); + setColumnWidths(columnWidths); + } + }, []); + + // Check the size of the grid, and show controls if there is room const onResize = ({ width }: { width: number }) => { - const initialColumnWidths = Math.max(width / props.columns.length, 100); - const columnWidths = props.columns.reduce( - (columnWidths: EuiDataGridColumnWidths, column) => { - columnWidths[column.id] = initialColumnWidths; - return columnWidths; - }, - {} - ); - setColumnWidths(columnWidths); setShowGridControls(width > 480); }; @@ -251,7 +261,7 @@ export const EuiDataGrid: FunctionComponent = props => { return ( -
+
{showGridControls ? gridControls : null} = props => {
From c6ee31405e242ad14e9dcecde6f3ed50cf167d76 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 28 Aug 2019 23:47:31 -0700 Subject: [PATCH 07/28] more cleanup, density controls now merge! --- src-docs/src/views/datagrid/container.js | 8 -- src-docs/src/views/datagrid/datagrid.js | 19 +-- .../src/views/datagrid/datagrid_example.js | 48 +++++++- src/components/datagrid/data_grid.tsx | 34 ++++-- src/components/datagrid/data_grid_types.ts | 12 +- src/components/datagrid/style_selector.tsx | 108 ++++++++++-------- 6 files changed, 136 insertions(+), 93 deletions(-) diff --git a/src-docs/src/views/datagrid/container.js b/src-docs/src/views/datagrid/container.js index 38e6e8cdc07..a9554d4aac3 100644 --- a/src-docs/src/views/datagrid/container.js +++ b/src-docs/src/views/datagrid/container.js @@ -65,14 +65,6 @@ export default class DataGridContainer extends Component { aria-label="Top EUI contributors" columns={columns} rowCount={data.length} - gridStyle={{ - border: this.state.borderSelected, - fontSize: this.state.fontSizeSelected, - cellPadding: this.state.cellPaddingSelected, - stripes: this.state.stripes, - rowHover: this.state.rowHoverSelected, - header: this.state.headerSelected, - }} renderCellValue={({ rowIndex, columnId }) => data[rowIndex][columnId] } diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index d2f8b6cc416..abbd3d93f15 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -1,12 +1,9 @@ import React, { Component } from 'react'; import { fake } from 'faker'; -import { EuiDataGrid, EuiAvatar } from '../../../../src/components/'; +import { EuiDataGrid } from '../../../../src/components/'; const columns = [ - { - id: 'avatar', - }, { id: 'name', }, @@ -28,12 +25,6 @@ const data = []; for (let i = 1; i < 100; i++) { data.push({ - avatar: ( - - ), name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'), email: fake('{{internet.email}}'), city: fake('{{address.city}}'), @@ -73,12 +64,8 @@ export default class DataGridContainer extends Component { columns={columns} rowCount={data.length} gridStyle={{ - border: this.state.borderSelected, - fontSize: this.state.fontSizeSelected, - cellPadding: this.state.cellPaddingSelected, - stripes: this.state.stripes, - rowHover: this.state.rowHoverSelected, - header: this.state.headerSelected, + border: 'horizontal', + stripes: true, }} renderCellValue={({ rowIndex, columnId }) => data[rowIndex][columnId]} pagination={{ diff --git a/src-docs/src/views/datagrid/datagrid_example.js b/src-docs/src/views/datagrid/datagrid_example.js index 1a44a4eacfd..62bfe27a54b 100644 --- a/src-docs/src/views/datagrid/datagrid_example.js +++ b/src-docs/src/views/datagrid/datagrid_example.js @@ -13,6 +13,10 @@ import DataGridContainer from './container'; const dataGridContainerSource = require('!!raw-loader!./container'); const dataGridContainerHtml = renderToHtml(DataGridContainer); +import DataGridStyling from './styling'; +const dataGridStylingSource = require('!!raw-loader!./styling'); +const dataGridStylingHtml = renderToHtml(DataGridStyling); + export const DataGridExample = { title: 'Data Grid', sections: [ @@ -27,11 +31,49 @@ export const DataGridExample = { code: dataGridContainerHtml, }, ], - title: 'DataGrid inside a container', - text:

EuiDataGrid within containers

, + title: 'DataGrid container', + text:

Inside a small container

, components: { DataGridContainer }, demo: , - props: { DataGridContainer }, + props: { EuiDataGrid }, }, ], }; +{ + /** + { + source: [ + { + type: GuideSectionTypes.JS, + code: dataGridContainerSource, + }, + { + type: GuideSectionTypes.HTML, + code: dataGridContainerHtml, + }, + ], + title: 'DataGrid container', + text:

Inside a small container

, + components: { DataGridContainer }, + demo: , + props: { EuiDataGrid }, + }, + { + source: [ + { + type: GuideSectionTypes.JS, + code: dataGridStylingSource, + }, + { + type: GuideSectionTypes.HTML, + code: dataGridStylingHtml, + }, + ], + title: 'DataGrid', + text:

EuiDataGrid

, + components: { DataGridStyling }, + demo: , + props: { EuiDataGrid }, + }, + **/ +} diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index d40ec68939f..d1deb9ee5cf 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -28,7 +28,7 @@ import { keyCodes } from '../../services'; import { EuiButtonEmpty } from '../button'; import { EuiDataGridBody } from './data_grid_body'; import { useColumnSelector } from './column_selector'; -import { useStyleSelector } from './style_selector'; +import { useStyleSelector, startingStyles } from './style_selector'; // @ts-ignore-next-line import { EuiTablePagination } from '../table/table_pagination'; // @ts-ignore-next-line @@ -212,31 +212,41 @@ export const EuiDataGrid: FunctionComponent = props => { rowCount, renderCellValue, className, - gridStyle, + gridStyle = startingStyles, pagination, ...rest } = props; const [ColumnSelector, visibleColumns] = useColumnSelector(columns); - const [StyleSelector, gridStyles, setGridStyles] = useStyleSelector( - gridStyle - ); + const [StyleSelector, gridStyles, setGridStyles] = useStyleSelector(); useEffect(() => { if (gridStyle) { - setGridStyles(gridStyle); + const oldStyles = gridStyles; + /*eslint-disable */ + const mergedStyle = Object.assign( + /*eslint-enable */ + {}, + oldStyles, + // @ts-ignore + gridStyle + ); + setGridStyles(mergedStyle); + } else { + setGridStyles(startingStyles); } + console.log('', gridStyles); }, [gridStyle]); const classes = classNames( 'euiDataGrid', - fontSizesToClassMap[gridStyles.fontSize || 'm'], - bordersToClassMap[gridStyles.border || 'all'], - headerToClassMap[gridStyles.header || 'shade'], - rowHoverToClassMap[gridStyles.rowHover || 'highlight'], - cellPaddingsToClassMap[gridStyles.cellPadding || 'm'], + fontSizesToClassMap[gridStyles.fontSize!], + bordersToClassMap[gridStyles.border!], + headerToClassMap[gridStyles.header!], + rowHoverToClassMap[gridStyles.rowHover!], + cellPaddingsToClassMap[gridStyles.cellPadding!], { - 'euiDataGrid--stripes': gridStyles.stripes || false, + 'euiDataGrid--stripes': gridStyles.stripes!, }, { 'euiDataGrid--fullScreen': isFullScreen, diff --git a/src/components/datagrid/data_grid_types.ts b/src/components/datagrid/data_grid_types.ts index e31f5ae9ae7..63d8aa10dca 100644 --- a/src/components/datagrid/data_grid_types.ts +++ b/src/components/datagrid/data_grid_types.ts @@ -24,10 +24,10 @@ export type EuiDataGridStyleRowHover = 'highlight' | 'none'; export type EuiDataGridStyleCellPaddings = 's' | 'm' | 'l'; export interface EuiDataGridStyle { - fontSize: EuiDataGridStyleFontSizes; - border: EuiDataGridStyleBorders; - stripes: boolean; - header: EuiDataGridStyleHeader; - rowHover: EuiDataGridStyleRowHover; - cellPadding: EuiDataGridStyleCellPaddings; + fontSize?: EuiDataGridStyleFontSizes; + border?: EuiDataGridStyleBorders; + stripes?: boolean; + header?: EuiDataGridStyleHeader; + rowHover?: EuiDataGridStyleRowHover; + cellPadding?: EuiDataGridStyleCellPaddings; } diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx index 58e319af593..85c373c0417 100644 --- a/src/components/datagrid/style_selector.tsx +++ b/src/components/datagrid/style_selector.tsx @@ -3,6 +3,7 @@ import React, { FunctionComponent, SetStateAction, useState, + useEffect, } from 'react'; import { EuiDataGridStyle } from './data_grid_types'; // @ts-ignore-next-line @@ -10,83 +11,94 @@ import { EuiPopover } from '../popover'; // @ts-ignore-next-line import { EuiButtonEmpty, EuiButtonGroup } from '../button'; -export const useStyleSelector = ( - initialStyles: EuiDataGridStyle = { - cellPadding: 'm', - fontSize: 'm', - border: 'all', - stripes: false, - rowHover: 'highlight', - header: 'shade', - } -): [ +export const startingStyles: EuiDataGridStyle = { + cellPadding: 'm', + fontSize: 'm', + border: 'all', + stripes: false, + rowHover: 'highlight', + header: 'shade', +}; + +export const useStyleSelector = (): [ FunctionComponent, EuiDataGridStyle, Dispatch> ] => { - const [gridStyles, setGridStyles] = useState(initialStyles); - - const [isOpen, setIsOpen] = useState(false); + const [gridStyles, setGridStyles] = useState(startingStyles); - const [gridDensity, setGridDensity] = useState('normal'); + console.log('in style selector', gridStyles); - const comfortable: EuiDataGridStyle = { - cellPadding: 'l', - fontSize: 'l', - border: 'all', - stripes: false, - rowHover: 'highlight', - header: 'shade', - }; - - const normal: EuiDataGridStyle = { - cellPadding: 'm', - fontSize: 'm', - border: 'all', - stripes: false, - rowHover: 'highlight', - header: 'shade', - }; + const [isOpen, setIsOpen] = useState(false); - const compact: EuiDataGridStyle = { - cellPadding: 's', - fontSize: 's', - border: 'all', - stripes: false, - rowHover: 'highlight', - header: 'shade', + const densityStyles = { + comfotable: { + fontSize: 'l', + cellPadding: 'l', + }, + normal: { + fontSize: 'm', + cellPadding: 'm', + }, + compact: { + fontSize: 's', + cellPadding: 's', + }, }; const densityOptions = [ { - id: 'tableDensityComfortable', + id: 'comfotable', label: 'Table density comfortable', iconType: 'tableDensityComfortable', - density: comfortable, }, { - id: 'tableDensityNormal', + id: 'normal', label: 'Table density normal', iconType: 'tableDensityNormal', - density: normal, }, { - id: 'tableDensityCompact', + id: 'compact', label: 'Table density compact', iconType: 'tableDensityCompact', - density: compact, }, ]; - const onChangeDensity = (optionId: any) => { - setGridDensity(optionId); + const [gridDensity, setGridDensity] = useState(densityOptions[1]); + const onChangeDensity = (optionId: any) => { const selectedDensity = densityOptions.filter(options => { return options.id === optionId; })[0]; - setGridStyles(selectedDensity.density); + + setGridDensity(selectedDensity); }; + useEffect(() => { + const oldStyles = gridStyles; + + /*eslint-disable */ + const mergedStyle = Object.assign( + {}, + oldStyles, + // @ts-ignore + densityStyles[gridDensity.id] + ); + /*eslint-enable */ + console.log( + 'gridDensity', + gridDensity, + 'old', + oldStyles, + 'new', + // @ts-ignore + densityStyles[gridDensity.id], + 'merged', + mergedStyle + ); + setGridStyles(mergedStyle); + }, [gridDensity]); + const StyleSelector = () => ( From ae53136ff8ed8abd0215f6235c7b9be0a187b677 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Fri, 30 Aug 2019 15:39:13 -0700 Subject: [PATCH 08/28] cleanup of docs and sass --- src-docs/src/views/datagrid/datagrid.js | 48 +++++++++++++++---- .../src/views/datagrid/datagrid_example.js | 20 ++++---- src/components/datagrid/_data_grid.scss | 1 + src/components/datagrid/column_selector.tsx | 1 + src/components/datagrid/data_grid.tsx | 4 +- src/components/datagrid/style_selector.tsx | 1 + 6 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index 56d9560fd45..2e6dea7bad2 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { Component, Fragment } from 'react'; import { fake } from 'faker'; import { @@ -16,14 +16,26 @@ const columns = [ id: 'email', }, { - id: 'city', + id: 'location', }, { - id: 'country', + id: 'account', }, { - id: 'account', + id: 'date', + }, + { + id: 'amount', + }, + { + id: 'phone', + }, + { + id: 'version', }, + // { + // id: 'actions', + // }, ]; const data = []; @@ -31,12 +43,32 @@ const data = []; for (let i = 1; i < 100; i++) { data.push({ name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'), - email: fake('{{internet.email}}'), - city: ( - {fake('{{address.city}}')} + email: {fake('{{internet.email}}')}, + location: ( + + {fake('{{address.city}}')},{' '} + + {fake('{{address.country}}')} + + ), - country: fake('{{address.country}}'), + date: fake('{{date.past}}'), account: fake('{{finance.account}}'), + amount: fake('{{finance.currencySymbol}}{{finance.amount}}'), + phone: fake('{{phone.phoneNumber}}'), + version: fake('{{system.semver}}'), + // actions: ( + // + // + // + // + // ), }); } diff --git a/src-docs/src/views/datagrid/datagrid_example.js b/src-docs/src/views/datagrid/datagrid_example.js index b8cde07f082..2aaecd24252 100644 --- a/src-docs/src/views/datagrid/datagrid_example.js +++ b/src-docs/src/views/datagrid/datagrid_example.js @@ -5,13 +5,13 @@ import { renderToHtml } from '../../services'; import { GuideSectionTypes } from '../../components'; import { EuiDataGrid } from '../../../../src/components'; -// import DataGrid from './datagrid'; -// const dataGridSource = require('!!raw-loader!./datagrid'); -// const dataGridHtml = renderToHtml(DataGrid); +import DataGrid from './datagrid'; +const dataGridSource = require('!!raw-loader!./datagrid'); +const dataGridHtml = renderToHtml(DataGrid); -import DataGridContainer from './container'; -const dataGridContainerSource = require('!!raw-loader!./container'); -const dataGridContainerHtml = renderToHtml(DataGridContainer); +// import DataGridContainer from './container'; +// const dataGridContainerSource = require('!!raw-loader!./container'); +// const dataGridContainerHtml = renderToHtml(DataGridContainer); // import DataGridStyling from './styling'; // const dataGridStylingSource = require('!!raw-loader!./styling'); @@ -24,17 +24,17 @@ export const DataGridExample = { source: [ { type: GuideSectionTypes.JS, - code: dataGridContainerSource, + code: dataGridSource, }, { type: GuideSectionTypes.HTML, - code: dataGridContainerHtml, + code: dataGridHtml, }, ], title: 'DataGrid container', text:

Inside a small container

, - components: { DataGridContainer }, - demo: , + components: { DataGrid }, + demo: , props: { EuiDataGrid }, }, ], diff --git a/src/components/datagrid/_data_grid.scss b/src/components/datagrid/_data_grid.scss index 7278d77b7fc..8a628e8cdb5 100644 --- a/src/components/datagrid/_data_grid.scss +++ b/src/components/datagrid/_data_grid.scss @@ -19,6 +19,7 @@ .euiDataGrid__pagination { padding-bottom: $euiSize; background: $euiColorLightestShade; + border-top: $euiBorderThin; } } diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index d89d1838f50..f896e890874 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -55,6 +55,7 @@ export const useColumnSelector = ( closePopover={() => setIsOpen(false)} anchorPosition="downLeft" ownFocus + panelPaddingSize="s" panelClassName="euiDataGridColumnSelectorPopover" button={ = props => { document.body.classList.remove('euiDataGrid__restrictBody'); } - const onCellFocusInBody = useCallback(setFocusedCell, [setFocusedCell]); + const onCellFocus = useCallback(setFocusedCell, [setFocusedCell]); return ( @@ -327,7 +327,7 @@ export const EuiDataGrid: FunctionComponent = props => { columnWidths={columnWidths} columns={visibleColumns} focusedCell={focusedCell} - onCellFocus={onCellFocusInBody} + onCellFocus={onCellFocus} pagination={pagination} renderCellValue={renderCellValue} rowCount={rowCount} diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx index 3f8552a4d92..f82ec9c7c23 100644 --- a/src/components/datagrid/style_selector.tsx +++ b/src/components/datagrid/style_selector.tsx @@ -94,6 +94,7 @@ export const useStyleSelector = (): [ closePopover={() => setIsOpen(false)} anchorPosition="downCenter" ownFocus + panelPaddingSize="s" panelClassName="euiDataGridColumnSelectorPopover" button={ Date: Tue, 3 Sep 2019 16:50:41 +0300 Subject: [PATCH 09/28] fixed focus trap issues --- src-docs/src/views/datagrid/datagrid.js | 34 +++++++++---------- .../datagrid/_data_grid_column_selector.scss | 10 +++--- .../datagrid/_data_grid_data_row.scss | 2 +- src/components/datagrid/style_selector.tsx | 6 ++-- src/components/focus_trap/focus_trap.js | 24 +++++++++---- 5 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index 2e6dea7bad2..8f80acbbd90 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -33,9 +33,9 @@ const columns = [ { id: 'version', }, - // { - // id: 'actions', - // }, + { + id: 'actions', + }, ]; const data = []; @@ -46,8 +46,8 @@ for (let i = 1; i < 100; i++) { email: {fake('{{internet.email}}')}, location: ( - {fake('{{address.city}}')},{' '} - + {`${fake('{{address.city}}')}, `} + {fake('{{address.country}}')} @@ -57,18 +57,18 @@ for (let i = 1; i < 100; i++) { amount: fake('{{finance.currencySymbol}}{{finance.amount}}'), phone: fake('{{phone.phoneNumber}}'), version: fake('{{system.semver}}'), - // actions: ( - // - // - // - // - // ), + actions: ( + + + + + ), }); } diff --git a/src/components/datagrid/_data_grid_column_selector.scss b/src/components/datagrid/_data_grid_column_selector.scss index 8a213e8c337..b9284d9b35b 100644 --- a/src/components/datagrid/_data_grid_column_selector.scss +++ b/src/components/datagrid/_data_grid_column_selector.scss @@ -1,8 +1,7 @@ -// sass-lint:disable-block no-empty-rulesets -.euiDataGridColumnSelector { - // sass-lint:disable-block no-important - // background: $euiColorEmptyShade !important; // No need for droppable coloring -} +// .euiDataGridColumnSelector { // No need for droppable coloring +// sass-lint:disable-block no-important +// background: $euiColorEmptyShade !important; +// } .euiDataGridColumnSelector__item { background: $euiColorEmptyShade; @@ -13,7 +12,6 @@ } } -// TODO: Find a better solution for how to deal with fix position draggables inside the transformed popover .euiDataGridColumnSelectorPopover { // sass-lint:disable-block no-important transform: none !important; diff --git a/src/components/datagrid/_data_grid_data_row.scss b/src/components/datagrid/_data_grid_data_row.scss index c7de2784ff3..89622f0d09d 100644 --- a/src/components/datagrid/_data_grid_data_row.scss +++ b/src/components/datagrid/_data_grid_data_row.scss @@ -34,7 +34,7 @@ margin-top: -1px; box-shadow: 0 0 0 2px $euiColorPrimary; border-radius: 1px; - z-index: 2; // Needed so it sits above potentional striping in the next row + z-index: 2; // Needed so it sits above potential striping in the next row } &:focus:not(:first-of-type) { diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx index f82ec9c7c23..5570d82f7e2 100644 --- a/src/components/datagrid/style_selector.tsx +++ b/src/components/datagrid/style_selector.tsx @@ -47,17 +47,17 @@ export const useStyleSelector = (): [ const densityOptions = [ { id: 'comfortable', - label: 'Table density comfortable', + label: 'Comfortable table density', iconType: 'tableDensityComfortable', }, { id: 'normal', - label: 'Table density normal', + label: 'Normal table density', iconType: 'tableDensityNormal', }, { id: 'compact', - label: 'Table density compact', + label: 'Compact table density', iconType: 'tableDensityCompact', }, ]; diff --git a/src/components/focus_trap/focus_trap.js b/src/components/focus_trap/focus_trap.js index 5fac7874c8c..3d6aff4efd0 100644 --- a/src/components/focus_trap/focus_trap.js +++ b/src/components/focus_trap/focus_trap.js @@ -5,7 +5,7 @@ import FocusLock from 'react-focus-lock'; import { EuiOutsideClickDetector } from '../outside_click_detector'; const OutsideEventDetector = ({ children, handleEvent, ...rest }) => { - const eventHanders = ['onMouseDown', 'onTouchStart'].reduce( + const eventHandlers = ['onMouseDown', 'onTouchStart'].reduce( (obj, eventName) => { obj[eventName] = handleEvent; return obj; @@ -13,7 +13,7 @@ const OutsideEventDetector = ({ children, handleEvent, ...rest }) => { {} ); return ( -
+
{children}
); @@ -28,11 +28,11 @@ export class EuiFocusTrap extends React.Component { preventFocusExit = false; componentDidMount() { - this.setInitalFocus(this.props.initialFocus); + this.setInitialFocus(this.props.initialFocus); } // Programmatically sets focus on a nested DOM node; optional - setInitalFocus = initialFocus => { + setInitialFocus = initialFocus => { let node = initialFocus; if (typeof node === 'string') { node = document.querySelector(initialFocus); @@ -79,7 +79,13 @@ export class EuiFocusTrap extends React.Component { }; render() { - const { children, clickOutsideDisables, disabled, ...rest } = this.props; + const { + children, + clickOutsideDisables, + disabled, + style, + ...rest + } = this.props; const isDisabled = disabled || this.state.hasBeenDisabledByClick; const lockProps = { disabled: isDisabled, @@ -90,11 +96,15 @@ export class EuiFocusTrap extends React.Component { isDisabled={isDisabled} onOutsideClick={this.handleOutsideClick}> - {children} + + {children} + ) : ( - {children} + + {children} + ); } } From 4575bd80d9f1547219c9b47e863369777aac9986 Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Tue, 3 Sep 2019 13:41:23 -0600 Subject: [PATCH 10/28] Performance fix to avoid re-processing rows unaffected by changing cell focus --- .../datagrid/data_grid_data_row.tsx | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/components/datagrid/data_grid_data_row.tsx b/src/components/datagrid/data_grid_data_row.tsx index 8bdfd8a991f..1de0ac50c9b 100644 --- a/src/components/datagrid/data_grid_data_row.tsx +++ b/src/components/datagrid/data_grid_data_row.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent, HTMLAttributes } from 'react'; +import React, { FunctionComponent, HTMLAttributes, useMemo } from 'react'; import classnames from 'classnames'; import { EuiDataGridColumn, EuiDataGridColumnWidths } from './data_grid_types'; import { CommonProps } from '../common'; @@ -45,20 +45,32 @@ const EuiDataGridDataRow: FunctionComponent< const width = columnWidths[id]; const isFocusable = focusedCell[0] === i && focusedCell[1] === rowIndex; - - return ( - + return useMemo( + () => ( + + ), + [ + id, + rowIndex, + i, + width, + renderCellValue, + onCellFocus, + isFocusable, + isGridNavigationEnabled, + interactiveCellId, + ] ); })}
From 22346c598aa484aabd3eed96bfeabf9defebffe0 Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Tue, 3 Sep 2019 14:44:17 -0600 Subject: [PATCH 11/28] fix hook problems in datagrid --- .eslintrc.js | 6 ++- package.json | 1 + src-docs/src/routes.js | 2 +- src-docs/webpack.config.js | 6 +-- src/components/datagrid/data_grid.tsx | 6 ++- src/components/datagrid/data_grid_cell.tsx | 17 ++++++++ .../datagrid/data_grid_data_row.tsx | 41 +++++++------------ src/components/datagrid/style_selector.tsx | 3 +- yarn.lock | 5 +++ 9 files changed, 52 insertions(+), 35 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f599c2968bd..2f24a0c65ef 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -30,7 +30,8 @@ module.exports = { plugins: [ "jsx-a11y", "prettier", - "local" + "local", + "react-hooks" ], rules: { "prefer-template": "error", @@ -64,6 +65,9 @@ module.exports = { "jsx-a11y/tabindex-no-positive": "error", "jsx-a11y/label-has-associated-control": "error", + // "react-hooks/rules-of-hooks": "error", + // "react-hooks/exhaustive-deps": "warn", + "@typescript-eslint/array-type": ["error", "array-simple"], "@typescript-eslint/camelcase": "off", "@typescript-eslint/class-name-casing": "off", diff --git a/package.json b/package.json index eb11b085b48..abeb42f4ff6 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,7 @@ "eslint-plugin-prefer-object-spread": "^1.2.1", "eslint-plugin-prettier": "^3.1.0", "eslint-plugin-react": "^7.13.0", + "eslint-plugin-react-hooks": "^2.0.1", "faker": "^4.1.0", "file-loader": "^1.1.11", "findup": "^0.1.5", diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js index 715538614e4..6111503e220 100644 --- a/src-docs/src/routes.js +++ b/src-docs/src/routes.js @@ -392,7 +392,7 @@ const allRoutes = navigation.reduce((accummulatedRoutes, section) => { }, []); export default { - history: useRouterHistory(createHashHistory)(), + history: useRouterHistory(createHashHistory)(), // eslint-disable-line react-hooks/rules-of-hooks navigation, getRouteForPath: path => { diff --git a/src-docs/webpack.config.js b/src-docs/webpack.config.js index d253a2054e3..d96a1006a38 100644 --- a/src-docs/webpack.config.js +++ b/src-docs/webpack.config.js @@ -40,12 +40,12 @@ const webpackConfig = { rules: [ { test: /\.(js|tsx?)$/, - loaders: useCache(['babel-loader']), + loaders: useCache(['babel-loader']), // eslint-disable-line react-hooks/rules-of-hooks exclude: /node_modules/, }, { test: /\.scss$/, - loaders: useCache([ + loaders: useCache([ // eslint-disable-line react-hooks/rules-of-hooks, prettier/prettier 'style-loader/useable', 'css-loader', 'postcss-loader', @@ -55,7 +55,7 @@ const webpackConfig = { }, { test: /\.css$/, - loaders: useCache(['style-loader/useable', 'css-loader']), + loaders: useCache(['style-loader/useable', 'css-loader']), // eslint-disable-line react-hooks/rules-of-hooks exclude: /node_modules/, }, { diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 891347fc753..4097cb90bbc 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -150,7 +150,8 @@ export const EuiDataGrid: FunctionComponent = props => { ); setColumnWidths(columnWidths); } - }, []); + // @TODO: come back to this hook lifecycle + }, []); // eslint-disable-line react-hooks/exhaustive-deps const onResize = ({ width }: { width: number }) => { setShowGridControls(width > 480); @@ -256,7 +257,8 @@ export const EuiDataGrid: FunctionComponent = props => { } else { setGridStyles(startingStyles); } - }, [gridStyle]); + // @TODO: come back to this hook lifecycle + }, [gridStyle]); // eslint-disable-line react-hooks/exhaustive-deps const classes = classNames( 'euiDataGrid', diff --git a/src/components/datagrid/data_grid_cell.tsx b/src/components/datagrid/data_grid_cell.tsx index 9123d907e9e..dabefc8d4fb 100644 --- a/src/components/datagrid/data_grid_cell.tsx +++ b/src/components/datagrid/data_grid_cell.tsx @@ -153,6 +153,23 @@ export class EuiDataGridCell extends Component< } } + shouldComponentUpdate(nextProps: EuiDataGridCellProps) { + if (nextProps.rowIndex !== this.props.rowIndex) return true; + if (nextProps.colIndex !== this.props.colIndex) return true; + if (nextProps.columnId !== this.props.columnId) return true; + if (nextProps.width !== this.props.width) return true; + if (nextProps.renderCellValue !== this.props.renderCellValue) return true; + if (nextProps.onCellFocus !== this.props.onCellFocus) return true; + if (nextProps.isFocusable !== this.props.isFocusable) return true; + if ( + nextProps.isGridNavigationEnabled !== this.props.isGridNavigationEnabled + ) + return true; + if (nextProps.interactiveCellId !== this.props.interactiveCellId) + return true; + return false; + } + render() { const { width, diff --git a/src/components/datagrid/data_grid_data_row.tsx b/src/components/datagrid/data_grid_data_row.tsx index 1de0ac50c9b..3336e21abc2 100644 --- a/src/components/datagrid/data_grid_data_row.tsx +++ b/src/components/datagrid/data_grid_data_row.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent, HTMLAttributes, useMemo } from 'react'; +import React, { FunctionComponent, HTMLAttributes } from 'react'; import classnames from 'classnames'; import { EuiDataGridColumn, EuiDataGridColumnWidths } from './data_grid_types'; import { CommonProps } from '../common'; @@ -45,32 +45,19 @@ const EuiDataGridDataRow: FunctionComponent< const width = columnWidths[id]; const isFocusable = focusedCell[0] === i && focusedCell[1] === rowIndex; - return useMemo( - () => ( - - ), - [ - id, - rowIndex, - i, - width, - renderCellValue, - onCellFocus, - isFocusable, - isGridNavigationEnabled, - interactiveCellId, - ] + return ( + ); })}
diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx index 5570d82f7e2..2b3edeb03be 100644 --- a/src/components/datagrid/style_selector.tsx +++ b/src/components/datagrid/style_selector.tsx @@ -85,7 +85,8 @@ export const useStyleSelector = (): [ ); /*eslint-enable */ setGridStyles(mergedStyle); - }, [gridDensity]); + // @TODO: come back to this hook lifecycle + }, [gridDensity]); // eslint-disable-line react-hooks/exhaustive-deps const StyleSelector = () => ( Date: Tue, 3 Sep 2019 15:29:04 -0600 Subject: [PATCH 12/28] Fixed EuiDataGrid tests --- .../datagrid/__snapshots__/data_grid.test.tsx.snap | 5 +++-- src/components/datagrid/data_grid.test.tsx | 4 ++-- src/components/datagrid/data_grid.tsx | 3 +-- src/components/datagrid/style_selector.tsx | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap index 9a8bd456d6d..de7850ddf74 100644 --- a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap +++ b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap @@ -172,6 +172,7 @@ Array [ />,
{ // purposefully not using data-test-subj attrs to test role semantics const grid = component.find('[role="grid"]'); - const rows = grid.children('[role="row"]'); + const rows = grid.children('[role="row"]'); // technically, this test should also allow role=rowgroup but we don't currently use rowgroups - // technically, this test should also allow role=rowgroup but we don't currently use rowgroups + expect(rows.length).not.toBe(0); expect(grid.children().length).toBe(rows.length); rows.each((i, element) => { diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 4097cb90bbc..0e730a3ad8f 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -313,13 +313,12 @@ export const EuiDataGrid: FunctionComponent = props => { {resizeRef => (
-
+
( setIsOpen(false)} anchorPosition="downCenter" From 742730b787efd33a33720af23c6999a3413f25e7 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 4 Sep 2019 00:10:15 -0700 Subject: [PATCH 13/28] feedback --- src-docs/src/views/icon/icons.js | 2 +- .../__snapshots__/data_grid.test.tsx.snap | 6 +++--- src/components/datagrid/_data_grid.scss | 17 +++++++++++------ .../datagrid/_data_grid_column_selector.scss | 6 +----- .../datagrid/_data_grid_data_row.scss | 11 +++++++---- src/components/datagrid/_variables.scss | 3 ++- src/components/datagrid/column_selector.tsx | 9 ++++++--- src/components/datagrid/data_grid.tsx | 10 +++++++++- src/components/datagrid/style_selector.tsx | 11 ++++++----- .../icon/__snapshots__/icon.test.tsx.snap | 8 ++++---- ...comfortable.js => table_density_expanded.js} | 4 ++-- ...mfortable.svg => table_density_expanded.svg} | 0 src/components/icon/icon.tsx | 2 +- src/global_styling/mixins/_states.scss | 6 ++++-- 14 files changed, 57 insertions(+), 38 deletions(-) rename src/components/icon/assets/{table_density_comfortable.js => table_density_expanded.js} (83%) rename src/components/icon/assets/{table_density_comfortable.svg => table_density_expanded.svg} (100%) diff --git a/src-docs/src/views/icon/icons.js b/src-docs/src/views/icon/icons.js index e201f6994e6..672ebc024bb 100644 --- a/src-docs/src/views/icon/icons.js +++ b/src-docs/src/views/icon/icons.js @@ -164,7 +164,7 @@ export const iconTypes = [ 'submodule', 'symlink', 'tableOfContents', - 'tableDensityComfortable', + 'tableDensityExpanded', 'tableDensityCompact', 'tableDensityNormal', 'tag', diff --git a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap index de7850ddf74..d94f089443f 100644 --- a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap +++ b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap @@ -188,7 +188,7 @@ Array [ class="euiPopover__anchor" >
@@ -277,6 +276,7 @@ Array [ class="euiDataGrid__overflow" >
diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index e06cfa05f52..6df7c186964 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -47,7 +47,10 @@ type CommonGridProps = CommonProps & // This structure forces either aria-label or aria-labelledby to be defined // making some type of label a requirement -type EuiDataGridProps = Omit & +type EuiDataGridProps = Omit< + CommonGridProps, + 'aria-label' | 'aria-labelledby' +> & ({ 'aria-label': string } | { 'aria-labelledby': string }); // Each gridStyle object above sets a specific CSS select to .euiGrid @@ -301,6 +304,20 @@ export const EuiDataGrid: FunctionComponent = props => { const onCellFocus = useCallback(setFocusedCell, [setFocusedCell]); + // extract aria-label and/or aria-labelledby from `rest` + const gridAriaProps: { + 'aria-label'?: string; + 'aria-labelledby'?: string; + } = {}; + if ('aria-label' in rest) { + gridAriaProps['aria-label'] = rest['aria-label']; + delete rest['aria-label']; + } + if ('aria-labelledby' in rest) { + gridAriaProps['aria-labelledby'] = rest['aria-labelledby']; + delete rest['aria-labelledby']; + } + return (
@@ -326,7 +343,10 @@ export const EuiDataGrid: FunctionComponent = props => { ref={resizeRef} {...rest}>
-
+
Date: Wed, 4 Sep 2019 15:11:10 -0700 Subject: [PATCH 16/28] style selector i18n --- .../datagrid/_data_grid_column_selector.scss | 1 + src/components/datagrid/style_selector.tsx | 81 ++++++++++++------- 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/components/datagrid/_data_grid_column_selector.scss b/src/components/datagrid/_data_grid_column_selector.scss index 0dc5577c7de..64c9d270dcb 100644 --- a/src/components/datagrid/_data_grid_column_selector.scss +++ b/src/components/datagrid/_data_grid_column_selector.scss @@ -11,5 +11,6 @@ // Hack because the fixed positions of drag and drop don't work inside of transformed elements // sass-lint:disable-block no-important transform: none !important; + transition: none !important; margin-top: -$euiSizeS; } diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx index 96304e1b68e..6c669531205 100644 --- a/src/components/datagrid/style_selector.tsx +++ b/src/components/datagrid/style_selector.tsx @@ -4,8 +4,10 @@ import React, { SetStateAction, useState, useEffect, + ReactChild, } from 'react'; import { EuiDataGridStyle } from './data_grid_types'; +import { EuiI18n } from '../i18n'; // @ts-ignore-next-line import { EuiPopover } from '../popover'; // @ts-ignore-next-line @@ -44,29 +46,15 @@ export const useStyleSelector = (): [ }, }; - const densityOptions = [ - { - id: 'expanded', - label: 'Expanded table density', - iconType: 'tableDensityExpanded', - }, - { - id: 'normal', - label: 'Normal table density', - iconType: 'tableDensityNormal', - }, - { - id: 'compact', - label: 'Compact table density', - iconType: 'tableDensityCompact', - }, - ]; + // These are the available options. They power the gridDensity hook and also the options in the render + const densityOptions: Array<{}> = ['expanded', 'normal', 'compact']; + // Normal is the defaul density const [gridDensity, setGridDensity] = useState(densityOptions[1]); const onChangeDensity = (optionId: string) => { const selectedDensity = densityOptions.filter(options => { - return options.id === optionId; + return options === optionId; })[0]; setGridDensity(selectedDensity); @@ -104,18 +92,55 @@ export const useStyleSelector = (): [ className="euiDataGrid__controlBtn" color="text" onClick={() => setIsOpen(!isOpen)}> - Density + }> - + + {([ + buttonLegend, + labelExpanded, + labelNormal, + labelCompact, + ]: ReactChild[]) => ( + + )} + ); From 82c49e4d8ab722951029eebb4aa43f4e01eac696 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 4 Sep 2019 15:55:42 -0700 Subject: [PATCH 17/28] euiDataGrid i18n --- src/components/datagrid/data_grid.tsx | 34 +++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 6df7c186964..6ac56a0e29f 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -7,8 +7,10 @@ import React, { useEffect, useRef, Fragment, + ReactChild, } from 'react'; import classNames from 'classnames'; +import { EuiI18n } from '../i18n'; import { EuiDataGridHeaderRow } from './data_grid_header_row'; import { CommonProps, Omit } from '../common'; import { @@ -323,15 +325,24 @@ export const EuiDataGrid: FunctionComponent = props => {
{showGridControls ? gridControls : null} - setIsFullScreen(!isFullScreen)} - onKeyDown={handleGridKeyDown}> - {isFullScreen ? 'Exit full screen' : 'Full screen'} - + + {([fullScreenButton, fullScreenButtonActive]: ReactChild[]) => ( + setIsFullScreen(!isFullScreen)} + onKeyDown={handleGridKeyDown}> + {isFullScreen ? fullScreenButtonActive : fullScreenButton} + + )} +
{/* Unsure why this element causes errors as focus follows spec */} {/* eslint-disable jsx-a11y/interactive-supports-focus */} @@ -371,7 +382,10 @@ export const EuiDataGrid: FunctionComponent = props => { {renderPagination(props)}
From a98779a0f265f92974379ddcaeaef98331f7c767 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 4 Sep 2019 16:07:41 -0700 Subject: [PATCH 18/28] column selector i18n --- src/components/datagrid/column_selector.tsx | 44 +++++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index 9309ceffa65..b153f51e0d5 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -1,8 +1,14 @@ -import React, { Fragment, FunctionComponent, useState } from 'react'; +import React, { + Fragment, + FunctionComponent, + useState, + ReactChild, +} from 'react'; import classNames from 'classnames'; import { EuiDataGridColumn } from './data_grid_types'; // @ts-ignore-next-line import { EuiPopover, EuiPopoverFooter } from '../popover'; +import { EuiI18n } from '../i18n'; // @ts-ignore-next-line import { EuiButtonEmpty } from '../button'; import { EuiFlexGroup, EuiFlexItem } from '../flex'; @@ -63,16 +69,25 @@ export const useColumnSelector = ( panelPaddingSize="s" panelClassName="euiDataGridColumnSelectorPopover" button={ - setIsOpen(!isOpen)}> - {numberOfHiddenFields > 0 - ? `${numberOfHiddenFields} hidden fields` - : 'Hide fields'} - + + {([button, buttonActive]: ReactChild[]) => ( + setIsOpen(!isOpen)}> + {numberOfHiddenFields > 0 + ? `${numberOfHiddenFields} ${buttonActive}` + : button} + + )} + }> setVisibleColumns(sortedColumns)}> - Show all + @@ -135,7 +153,7 @@ export const useColumnSelector = ( size="xs" flush="right" onClick={() => setVisibleColumns([])}> - Hide all + From 278510e6dd95247fdbb1493aead2db6671ab69e6 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 4 Sep 2019 16:15:00 -0700 Subject: [PATCH 19/28] full screen check --- src/components/datagrid/data_grid.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index 6ac56a0e29f..cec35df6231 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -159,7 +159,7 @@ export const EuiDataGrid: FunctionComponent = props => { }, []); // eslint-disable-line react-hooks/exhaustive-deps const onResize = ({ width }: { width: number }) => { - setShowGridControls(width > 480); + setShowGridControls(width > 480 || isFullScreen); }; const [isGridNavigationEnabled, setIsGridNavigationEnabled] = useState< From ed6626995d854eb013baa4068ab57419d5059e1c Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 4 Sep 2019 16:22:13 -0700 Subject: [PATCH 20/28] const for screen width --- src/components/datagrid/data_grid.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/datagrid/data_grid.tsx b/src/components/datagrid/data_grid.tsx index cec35df6231..025e32a75a8 100644 --- a/src/components/datagrid/data_grid.tsx +++ b/src/components/datagrid/data_grid.tsx @@ -38,6 +38,9 @@ import { EuiFocusTrap } from '../focus_trap'; import { EuiResizeObserver } from '../observer/resize_observer'; import { CELL_CONTENTS_ATTR } from './utils'; +// When below this number the grid only shows the full screen button +const MINIMUM_WIDTH_FOR_GRID_CONTROLS = 479; + type CommonGridProps = CommonProps & HTMLAttributes & { columns: EuiDataGridColumn[]; @@ -159,7 +162,9 @@ export const EuiDataGrid: FunctionComponent = props => { }, []); // eslint-disable-line react-hooks/exhaustive-deps const onResize = ({ width }: { width: number }) => { - setShowGridControls(width > 480 || isFullScreen); + setShowGridControls( + width > MINIMUM_WIDTH_FOR_GRID_CONTROLS || isFullScreen + ); }; const [isGridNavigationEnabled, setIsGridNavigationEnabled] = useState< From 9f2dce1dcc9f11df773099dd657ef150e7fc542d Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 4 Sep 2019 16:28:18 -0700 Subject: [PATCH 21/28] sass lint, stupid vim --- src/components/datagrid/_data_grid_column_selector.scss | 2 +- src/global_styling/mixins/_states.scss | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/datagrid/_data_grid_column_selector.scss b/src/components/datagrid/_data_grid_column_selector.scss index 64c9d270dcb..b7e6b3e1f97 100644 --- a/src/components/datagrid/_data_grid_column_selector.scss +++ b/src/components/datagrid/_data_grid_column_selector.scss @@ -2,8 +2,8 @@ padding: $euiSizeXS; &-isDragging { - background: $euiColorEmptyShade; @include euiBottomShadow; + background: $euiColorEmptyShade; } } diff --git a/src/global_styling/mixins/_states.scss b/src/global_styling/mixins/_states.scss index 29b4e692aea..1b60d15273b 100644 --- a/src/global_styling/mixins/_states.scss +++ b/src/global_styling/mixins/_states.scss @@ -12,6 +12,7 @@ $euiFocusRingSizeLarge: 4px; // sass-lint:disable-block no-important animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimateLarge !important; } @else { + // sass-lint:disable-block no-important animation: $euiAnimSpeedSlow $euiAnimSlightResistance 1 normal forwards focusRingAnimate !important; } } From c47a4ed074f5fd773a6ce82be9a91f837b593e64 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 4 Sep 2019 16:57:38 -0700 Subject: [PATCH 22/28] ie11 fixes and some i18n stuffs --- src/components/datagrid/_data_grid_column_selector.scss | 2 ++ src/components/datagrid/column_selector.tsx | 2 +- src/components/datagrid/style_selector.tsx | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/datagrid/_data_grid_column_selector.scss b/src/components/datagrid/_data_grid_column_selector.scss index b7e6b3e1f97..63aab23b946 100644 --- a/src/components/datagrid/_data_grid_column_selector.scss +++ b/src/components/datagrid/_data_grid_column_selector.scss @@ -13,4 +13,6 @@ transform: none !important; transition: none !important; margin-top: -$euiSizeS; + // IE11 needs a min-width + min-width: $euiSize * 12; } diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index b153f51e0d5..6c3323ba7fb 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -74,7 +74,7 @@ export const useColumnSelector = ( 'euiColumnSelector.button', 'euiColumnSelector.buttonActive', ]} - defaults={['Full screen', 'Exit full screen']}> + defaults={['Hide fields', 'fields hidden']}> {([button, buttonActive]: ReactChild[]) => ( Date: Thu, 5 Sep 2019 09:23:37 -0600 Subject: [PATCH 23/28] Fix/update datagrid tests' popover helper utils --- src/components/datagrid/data_grid.test.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/components/datagrid/data_grid.test.tsx b/src/components/datagrid/data_grid.test.tsx index 526b7de0884..b692b6369a9 100644 --- a/src/components/datagrid/data_grid.test.tsx +++ b/src/components/datagrid/data_grid.test.tsx @@ -124,7 +124,9 @@ function setColumnVisibility( let popoverButton = popover .find('div[className="euiPopover__anchor"]') - .childAt(0); + .find('[onClick]') + .first(); + // @ts-ignore-next-line act(() => popoverButton.props().onClick()); datagrid.update(); @@ -150,7 +152,9 @@ function setColumnVisibility( popoverButton = popover .find('div[className="euiPopover__anchor"]') - .childAt(0); + .find('[onClick]') + .first(); + // @ts-ignore-next-line act(() => popoverButton.props().onClick()); datagrid.update(); @@ -174,7 +178,9 @@ function moveColumnToIndex( let popoverButton = popover .find('div[className="euiPopover__anchor"]') - .childAt(0); + .find('[onClick]') + .first(); + // @ts-ignore-next-line act(() => popoverButton.props().onClick()); datagrid.update(); @@ -207,7 +213,9 @@ function moveColumnToIndex( popoverButton = popover .find('div[className="euiPopover__anchor"]') - .childAt(0); + .find('[onClick]') + .first(); + // @ts-ignore-next-line act(() => popoverButton.props().onClick()); datagrid.update(); From 1550e28b2ebdf309af287718488f6be46f2235d5 Mon Sep 17 00:00:00 2001 From: Chandler Prall Date: Thu, 5 Sep 2019 09:50:19 -0600 Subject: [PATCH 24/28] Update EuiI18n types around defaults & children callback to provide more feedback to devs and make them more accurate --- src/components/datagrid/style_selector.tsx | 2 +- src/components/i18n/i18n.tsx | 27 ++++++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/components/datagrid/style_selector.tsx b/src/components/datagrid/style_selector.tsx index f00c09f3575..290abbbbf5d 100644 --- a/src/components/datagrid/style_selector.tsx +++ b/src/components/datagrid/style_selector.tsx @@ -116,7 +116,7 @@ export const useStyleSelector = (): [ ]: ReactChild[]) => ( > { values?: T; } -interface I18nTokensShape { +interface I18nTokensShape { tokens: string[]; - defaults: ReactChild[]; - children: (x: ReactChild[]) => ReactChild; + defaults: T; + children: (x: Array) => ReactChild; } -type EuiI18nProps> = ExclusiveUnion< - I18nTokenShape, - I18nTokensShape ->; +type EuiI18nProps< + T, + DEFAULT extends Renderable, + DEFAULTS extends any[] +> = ExclusiveUnion, I18nTokensShape>; -function hasTokens(x: EuiI18nProps): x is I18nTokensShape { +function hasTokens( + x: EuiI18nProps +): x is I18nTokensShape { return x.tokens != null; } // Must use the generics // If instead typed with React.FunctionComponent there isn't feedback given back to the dev // when using a `values` object with a renderer callback. -const EuiI18n = >( - props: EuiI18nProps +const EuiI18n = < + T extends {}, + DEFAULT extends Renderable, + DEFAULTS extends any[] +>( + props: EuiI18nProps ) => ( {i18nConfig => { From 9f5cd079f5b1b36a0d55e22b7c14c042622ce0bd Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Thu, 5 Sep 2019 11:01:00 -0700 Subject: [PATCH 25/28] fix for focus trap styles. hat tip to chandler --- .../src/views/datagrid/datagrid_example.js | 20 ++++++++----------- .../__snapshots__/data_grid.test.tsx.snap | 2 +- src/components/focus_trap/focus_trap.js | 4 ++-- .../__snapshots__/super_select.test.js.snap | 6 +++++- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src-docs/src/views/datagrid/datagrid_example.js b/src-docs/src/views/datagrid/datagrid_example.js index 2aaecd24252..646c2a94046 100644 --- a/src-docs/src/views/datagrid/datagrid_example.js +++ b/src-docs/src/views/datagrid/datagrid_example.js @@ -9,13 +9,13 @@ import DataGrid from './datagrid'; const dataGridSource = require('!!raw-loader!./datagrid'); const dataGridHtml = renderToHtml(DataGrid); -// import DataGridContainer from './container'; -// const dataGridContainerSource = require('!!raw-loader!./container'); -// const dataGridContainerHtml = renderToHtml(DataGridContainer); +import DataGridContainer from './container'; +const dataGridContainerSource = require('!!raw-loader!./container'); +const dataGridContainerHtml = renderToHtml(DataGridContainer); -// import DataGridStyling from './styling'; -// const dataGridStylingSource = require('!!raw-loader!./styling'); -// const dataGridStylingHtml = renderToHtml(DataGridStyling); +import DataGridStyling from './styling'; +const dataGridStylingSource = require('!!raw-loader!./styling'); +const dataGridStylingHtml = renderToHtml(DataGridStyling); export const DataGridExample = { title: 'Data Grid', @@ -37,10 +37,6 @@ export const DataGridExample = { demo: , props: { EuiDataGrid }, }, - ], -}; -{ - /** { source: [ { @@ -75,5 +71,5 @@ export const DataGridExample = { demo: , props: { EuiDataGrid }, }, - **/ -} + ], +}; diff --git a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap index 6b11e2595ef..8d093658514 100644 --- a/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap +++ b/src/components/datagrid/__snapshots__/data_grid.test.tsx.snap @@ -172,7 +172,7 @@ Array [ />,
- + {children} ) : ( - + {children} ); diff --git a/src/components/form/super_select/__snapshots__/super_select.test.js.snap b/src/components/form/super_select/__snapshots__/super_select.test.js.snap index b11fb127f96..50748d01bfb 100644 --- a/src/components/form/super_select/__snapshots__/super_select.test.js.snap +++ b/src/components/form/super_select/__snapshots__/super_select.test.js.snap @@ -645,7 +645,11 @@ exports[`EuiSuperSelect props more props are propogated to each option 2`] = ` as="div" autoFocus={true} disabled={true} - lockProps={Object {}} + lockProps={ + Object { + "style": undefined, + } + } noFocusGuards={false} persistentFocus={false} returnFocus={true} From d32c8e2ab0fbe06310b8409c7dfeed90690bab4f Mon Sep 17 00:00:00 2001 From: "dave.snider@gmail.com" Date: Thu, 5 Sep 2019 11:31:11 -0700 Subject: [PATCH 26/28] Update src/components/datagrid/column_selector.tsx Co-Authored-By: Caroline Horn <549577+cchaos@users.noreply.github.com> --- src/components/datagrid/column_selector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index 6c3323ba7fb..dc408af8600 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -153,7 +153,7 @@ export const useColumnSelector = ( size="xs" flush="right" onClick={() => setVisibleColumns([])}> - + From ad66a767edf92bd7f320860f407370ac84ce4d9e Mon Sep 17 00:00:00 2001 From: "dave.snider@gmail.com" Date: Thu, 5 Sep 2019 11:32:05 -0700 Subject: [PATCH 27/28] Update src/components/datagrid/column_selector.tsx Co-Authored-By: Caroline Horn <549577+cchaos@users.noreply.github.com> --- src/components/datagrid/column_selector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index dc408af8600..4345139f04f 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -144,7 +144,7 @@ export const useColumnSelector = ( onClick={() => setVisibleColumns(sortedColumns)}> From 36a9be2fbc23e80f40f9c3f135059c4700572efb Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Thu, 5 Sep 2019 13:02:48 -0700 Subject: [PATCH 28/28] fix ci, update docs --- src-docs/src/views/datagrid/datagrid.js | 4 -- .../src/views/datagrid/datagrid_example.js | 29 +++++++--- src-docs/src/views/datagrid/styling.js | 55 +++++++++---------- src/components/datagrid/column_selector.tsx | 5 +- 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src-docs/src/views/datagrid/datagrid.js b/src-docs/src/views/datagrid/datagrid.js index 8f80acbbd90..6f5ed5e6c67 100644 --- a/src-docs/src/views/datagrid/datagrid.js +++ b/src-docs/src/views/datagrid/datagrid.js @@ -109,10 +109,6 @@ export default class DataGridContainer extends Component { aria-label="Top EUI contributors" columns={columns} rowCount={data.length} - gridStyle={{ - border: 'horizontal', - stripes: true, - }} renderCellValue={({ rowIndex, columnId }) => data[rowIndex][columnId]} pagination={{ ...pagination, diff --git a/src-docs/src/views/datagrid/datagrid_example.js b/src-docs/src/views/datagrid/datagrid_example.js index 646c2a94046..9738b0e5418 100644 --- a/src-docs/src/views/datagrid/datagrid_example.js +++ b/src-docs/src/views/datagrid/datagrid_example.js @@ -3,7 +3,7 @@ import React from 'react'; import { renderToHtml } from '../../services'; import { GuideSectionTypes } from '../../components'; -import { EuiDataGrid } from '../../../../src/components'; +import { EuiDataGrid, EuiCode } from '../../../../src/components'; import DataGrid from './datagrid'; const dataGridSource = require('!!raw-loader!./datagrid'); @@ -18,7 +18,7 @@ const dataGridStylingSource = require('!!raw-loader!./styling'); const dataGridStylingHtml = renderToHtml(DataGridStyling); export const DataGridExample = { - title: 'Data Grid', + title: 'Data grid', sections: [ { source: [ @@ -31,8 +31,8 @@ export const DataGridExample = { code: dataGridHtml, }, ], - title: 'DataGrid container', - text:

Inside a small container

, + title: 'DataGrid', + text:

By default the data grid will grow into the container.

, components: { DataGrid }, demo: , props: { EuiDataGrid }, @@ -48,8 +48,13 @@ export const DataGridExample = { code: dataGridContainerHtml, }, ], - title: 'DataGrid container', - text:

Inside a small container

, + title: 'Data grid adapts to its container', + text: ( +

+ When wrapped inside a container, like a dashboard panel, the grid will + start hiding controls and adopt a more strict flex layout +

+ ), components: { DataGridContainer }, demo: , props: { EuiDataGrid }, @@ -65,8 +70,16 @@ export const DataGridExample = { code: dataGridStylingHtml, }, ], - title: 'DataGrid', - text:

EuiDataGrid

, + title: 'Customize data grid styling', + text: ( +

+ Styling can be passed down to the grid through the{' '} + gridStyle prop. It accepts an object shape that + allows for customization. When the density controls are also present, + both font size and padding will merge against the initial defaults + provided by the prop. +

+ ), components: { DataGridStyling }, demo: , props: { EuiDataGrid }, diff --git a/src-docs/src/views/datagrid/styling.js b/src-docs/src/views/datagrid/styling.js index a9a7d324938..f9302702ce3 100644 --- a/src-docs/src/views/datagrid/styling.js +++ b/src-docs/src/views/datagrid/styling.js @@ -34,7 +34,7 @@ const columns = [ const data = []; -for (let i = 1; i < 100; i++) { +for (let i = 1; i < 5; i++) { data.push({ avatar: ( -
- - data[rowIndex][columnId] - } - pagination={{ - ...pagination, - pageSizeOptions: [5, 10, 25], - onChangeItemsPerPage: this.setPageSize, - onChangePage: this.setPageIndex, - }} - /> -
+ data[rowIndex][columnId]} + pagination={{ + ...pagination, + pageSizeOptions: [5, 10, 25], + onChangeItemsPerPage: this.setPageSize, + onChangePage: this.setPageIndex, + }} + />
); } diff --git a/src/components/datagrid/column_selector.tsx b/src/components/datagrid/column_selector.tsx index 4345139f04f..735f6c7ccd4 100644 --- a/src/components/datagrid/column_selector.tsx +++ b/src/components/datagrid/column_selector.tsx @@ -142,10 +142,7 @@ export const useColumnSelector = ( size="xs" flush="left" onClick={() => setVisibleColumns(sortedColumns)}> - +