From 08f2d453b51e6eb7bf29c53c1d28623ed2837711 Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Wed, 12 Sep 2018 14:09:26 -0400 Subject: [PATCH] Table actions visibility (#1103) --- CHANGELOG.md | 8 ++- src-docs/src/views/tables/actions/actions.js | 55 ++++++++++------ .../views/tables/actions/actions_section.js | 8 ++- src-docs/src/views/tool_tip/tool_tip.js | 10 +++ .../__snapshots__/basic_table.test.js.snap | 63 +++++++++++++++++-- .../collapsed_item_actions.test.js.snap | 28 +++++---- .../default_item_action.test.js.snap | 52 ++++++++------- .../expanded_item_actions.test.js.snap | 2 + src/components/basic_table/basic_table.js | 24 ++++--- .../basic_table/collapsed_item_actions.js | 13 +++- .../basic_table/default_item_action.js | 41 +++++++----- .../basic_table/expanded_item_actions.js | 23 ++++++- src/components/table/_responsive.scss | 18 +++--- src/components/table/_table.scss | 32 ++++++++-- src/components/tool_tip/_tool_tip.scss | 5 ++ src/components/tool_tip/tool_tip.js | 15 +++++ 16 files changed, 294 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 190aa3bf874..3c27c1a6c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -No public interface changes since `3.11.0`. +- Added `delay` prop to `EuiToolTip` ([#1103](https://github.com/elastic/eui/pull/1103)) + +**Breaking changes** + +- `EuiBasicTable` now shows up to 2 actions before condensing to all popover, but still displaying the top/primary 2 actions as well ([#1103](https://github.com/elastic/eui/pull/1103)) +- `EuiBasicTable` will automatically add `hasActions` and `isSelectable` to allow proper responsive style handling, but are still overridable ([#1103](https://github.com/elastic/eui/pull/1103)) + ## [`3.11.0`](https://github.com/elastic/eui/tree/v3.11.0) diff --git a/src-docs/src/views/tables/actions/actions.js b/src-docs/src/views/tables/actions/actions.js index f4d868f2126..cc5f5e909af 100644 --- a/src-docs/src/views/tables/actions/actions.js +++ b/src-docs/src/views/tables/actions/actions.js @@ -11,7 +11,6 @@ import { EuiFlexItem, EuiSwitch, EuiSpacer, - EuiText, } from '../../../../../src/components'; /* @@ -93,13 +92,15 @@ export class Table extends Component { } return ( - - Delete {selectedItems.length} Users - + + + Delete {selectedItems.length} Users + + ); } @@ -145,31 +146,47 @@ export class Table extends Component { ? [{ render: (item) => { return ( - this.cloneUser(item)}> + this.cloneUser(item)}> Clone - + ); } }, { render: (item) => { return ( - this.deleteUser(item)}> + this.deleteUser(item)}> Delete - + ); } }] : [{ name: 'Clone', - description: 'Clone this person', + description: 'Clone this user', icon: 'copy', onClick: this.cloneUser }, { name: 'Delete', - description: 'Delete this person', + description: 'Delete this user', icon: 'trash', color: 'danger', - onClick: this.deleteUser + type: 'icon', + onClick: this.deleteUser, + isPrimary: true, + }, { + name: 'Edit', + isPrimary: true, + description: 'Edit this user', + icon: 'pencil', + type: 'icon', + onClick: () => {}, + }, { + name: 'Share', + isPrimary: true, + description: 'Share this user', + icon: 'share', + type: 'icon', + onClick: () => {}, }]; } else { actions = customAction @@ -187,7 +204,7 @@ export class Table extends Component { }] : [{ name: 'Delete', - description: 'Delete this person', + description: 'Delete this user', icon: 'trash', color: 'danger', type: 'icon', @@ -270,7 +287,6 @@ export class Table extends Component { return ( - {deleteButton} + + {deleteButton} @@ -296,8 +314,7 @@ export class Table extends Component { pagination={pagination} sorting={sorting} selection={selection} - isSelectable={true} - hasActions={true} + hasActions={customAction ? false : true} onChange={this.onTableChange} /> diff --git a/src-docs/src/views/tables/actions/actions_section.js b/src-docs/src/views/tables/actions/actions_section.js index 3609c93edc0..640c54ffb45 100644 --- a/src-docs/src/views/tables/actions/actions_section.js +++ b/src-docs/src/views/tables/actions/actions_section.js @@ -32,11 +32,13 @@ export const section = {

diff --git a/src-docs/src/views/tool_tip/tool_tip.js b/src-docs/src/views/tool_tip/tool_tip.js index 58f4fbff504..2e8d25501cf 100644 --- a/src-docs/src/views/tool_tip/tool_tip.js +++ b/src-docs/src/views/tool_tip/tool_tip.js @@ -45,6 +45,16 @@ export default () => (

+

+ This tooltip has a long delay because it might be in a repeatable component{' '} + + wink + +

+

This tooltip appears on the bottom of this icon:{' '} + + + } closePopover={[Function]} hasArrow={true} diff --git a/src/components/basic_table/__snapshots__/default_item_action.test.js.snap b/src/components/basic_table/__snapshots__/default_item_action.test.js.snap index dee76650464..e07983baee7 100644 --- a/src/components/basic_table/__snapshots__/default_item_action.test.js.snap +++ b/src/components/basic_table/__snapshots__/default_item_action.test.js.snap @@ -1,29 +1,39 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DefaultItemAction render - button 1`] = ` - - action1 - + + action1 + + `; exports[`DefaultItemAction render - icon 1`] = ` - + + + `; diff --git a/src/components/basic_table/__snapshots__/expanded_item_actions.test.js.snap b/src/components/basic_table/__snapshots__/expanded_item_actions.test.js.snap index cad74905029..811e7ae0ccf 100644 --- a/src/components/basic_table/__snapshots__/expanded_item_actions.test.js.snap +++ b/src/components/basic_table/__snapshots__/expanded_item_actions.test.js.snap @@ -10,6 +10,7 @@ Array [ "onClick": [Function], } } + className="" enabled={true} index={0} item={ @@ -28,6 +29,7 @@ Array [ "render": [Function], } } + className="" enabled={true} index={1} item={ diff --git a/src/components/basic_table/basic_table.js b/src/components/basic_table/basic_table.js index 26db8be6c34..546ad341a56 100644 --- a/src/components/basic_table/basic_table.js +++ b/src/components/basic_table/basic_table.js @@ -4,6 +4,7 @@ import React, { } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; +import { dropWhile, slice } from 'lodash'; import { formatAuto, formatBoolean, formatDate, formatNumber, formatText, LEFT_ALIGNMENT, PropertySortType, RIGHT_ALIGNMENT, SortDirection @@ -63,6 +64,7 @@ const DefaultItemActionType = PropTypes.shape({ onClick: PropTypes.func.isRequired, // (item) => void, available: PropTypes.func, // (item) => boolean; enabled: PropTypes.func, // (item) => boolean; + isPrimary: PropTypes.bool, icon: PropTypes.oneOfType([ // required when type is 'icon' PropTypes.oneOf(ICON_TYPES), PropTypes.func // (item) => oneOf(ICON_TYPES) @@ -76,7 +78,8 @@ const DefaultItemActionType = PropTypes.shape({ const CustomItemActionType = PropTypes.shape({ render: PropTypes.func.isRequired, // (item, enabled) => PropTypes.node; available: PropTypes.func, // (item) => boolean; - enabled: PropTypes.func // (item) => boolean; + enabled: PropTypes.func, // (item) => boolean; + isPrimary: PropTypes.bool, }); const SupportedItemActionType = PropTypes.oneOfType([ @@ -566,13 +569,17 @@ export class EuiBasicTable extends Component { getItemId(selectedItem, itemIdCallback) === itemId )); + let calculatedHasSelection; if (selection) { cells.push(this.renderItemSelectionCell(itemId, item, selected)); + calculatedHasSelection = true; } + let calculatedHasActions; columns.forEach((column, columnIndex) => { if (column.actions) { cells.push(this.renderItemActionsCell(itemId, item, column, columnIndex, rowIndex)); + calculatedHasActions = true; } else if (column.field) { cells.push(this.renderItemFieldDataCell(itemId, item, column, columnIndex)); } else { @@ -607,9 +614,9 @@ export class EuiBasicTable extends Component { @@ -660,7 +667,10 @@ export class EuiBasicTable extends Component { this.state.selection.length === 0 && (!action.enabled || action.enabled(item)); let actualActions = column.actions; - if (column.actions.length > 1) { + if (column.actions.length > 2) { + + // if any of the actions `isPrimary`, add them inline as well, but only the first 2 + actualActions = slice(dropWhile(column.actions, function (o) { return !o.isPrimary; }), 0, 2); // if we have more than 1 action, we don't show them all in the cell, instead we // put them all in a popover tool. This effectively means we can only have a maximum @@ -668,9 +678,9 @@ export class EuiBasicTable extends Component { // // here we create a single custom action that triggers the popover with all the configured actions - actualActions = [ + actualActions.push( { - name: 'Actions', + name: 'All actions', render: (item) => { return ( ); + const withTooltip = !allDisabled && ( + + {popoverButton} + + ); + return ( action.onClick(item); const color = this.resolveActionColor(); const icon = this.resolveActionIcon(); + + let button; if (action.type === 'icon') { if (!icon) { throw new Error(`Cannot render item action [${action.name}]. It is configured to render as an icon but no icon is provided. Make sure to set the 'icon' property of the action`); } - return ( + button = ( ); + } else { + button = ( + + {action.name} + + ); } - return ( - - {action.name} - - ); + return (enabled && action.description) ? ( + + {button} + + ) : button; } resolveActionIcon() { diff --git a/src/components/basic_table/expanded_item_actions.js b/src/components/basic_table/expanded_item_actions.js index d9bb928b97e..fa40eadb403 100644 --- a/src/components/basic_table/expanded_item_actions.js +++ b/src/components/basic_table/expanded_item_actions.js @@ -1,22 +1,39 @@ import React from 'react'; +import classNames from 'classnames'; import { DefaultItemAction } from './default_item_action'; import { CustomItemAction } from './custom_item_action'; -export const ExpandedItemActions = ({ actions, itemId, item, actionEnabled, className }) => { +export const ExpandedItemActions = ({ + actions, + itemId, + item, + actionEnabled, + className, +}) => { + + const moreThanThree = actions.length > 2; return actions.reduce((tools, action, index) => { + const available = action.available ? action.available(item) : true; if (!available) { return tools; } + const enabled = actionEnabled(action); + const key = `item_action_${itemId}_${index}`; + + const classes = classNames(className, { + 'expandedItemActions__completelyHide': moreThanThree && index < 2, + }); + if (action.render) { // custom action has a render function tools.push(