From 29725dc8d6afd548c99e521614c7b4ccd273ad91 Mon Sep 17 00:00:00 2001 From: Ryan Keairns Date: Tue, 12 Mar 2019 10:22:29 -0500 Subject: [PATCH 1/3] Adds side nav toggle (#1701) --- CHANGELOG.md | 3 +- src-docs/src/views/list_group/list_group.js | 2 +- src-docs/src/views/nav_drawer/nav_drawer.js | 570 ++++++------------ .../views/nav_drawer/nav_drawer_example.js | 31 +- src/components/index.js | 2 +- .../list_group_item.test.js.snap | 2 + src/components/list_group/_index.scss | 1 + .../list_group/_list_group_item.scss | 15 +- src/components/list_group/list_group.js | 21 +- src/components/list_group/list_group_item.js | 61 +- src/components/nav_drawer/_index.scss | 2 +- src/components/nav_drawer/_nav_drawer.scss | 139 ++--- .../nav_drawer/_nav_drawer_flyout.scss | 19 +- .../nav_drawer/_nav_drawer_group.scss | 14 + .../nav_drawer/_nav_drawer_menu.scss | 4 - src/components/nav_drawer/index.js | 4 +- src/components/nav_drawer/nav_drawer.js | 283 +++++++-- .../nav_drawer/nav_drawer_flyout.js | 9 +- src/components/nav_drawer/nav_drawer_group.js | 53 ++ src/components/nav_drawer/nav_drawer_menu.js | 24 - 20 files changed, 700 insertions(+), 559 deletions(-) create mode 100644 src/components/nav_drawer/_nav_drawer_group.scss delete mode 100644 src/components/nav_drawer/_nav_drawer_menu.scss create mode 100644 src/components/nav_drawer/nav_drawer_group.js delete mode 100644 src/components/nav_drawer/nav_drawer_menu.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 48519e5aa7a..475f805fc0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## [`master`](https://github.com/elastic/eui/tree/master) +- Added `footerLink` and `showToolTips` to `EuiNavDrawer` and added `EuiNavDrawerGroup` ([#1701](https://github.com/elastic/eui/pull/1701)) + **Bug fixes** - Fixed `EuiSuperDatePicker` time selection jumping on focus ([#1704](https://github.com/elastic/eui/pull/1704)) @@ -14,7 +16,6 @@ - Adjusted the dark theme palette a bit more and adjusted a few components ([#1700](https://github.com/elastic/eui/pull/1700)) - ## [`9.1.0`](https://github.com/elastic/eui/tree/v9.1.0) - Adjusted the dark theme palette to have a slight blue tint ([#1691](https://github.com/elastic/eui/pull/1691)) diff --git a/src-docs/src/views/list_group/list_group.js b/src-docs/src/views/list_group/list_group.js index 4112799a0d0..0f596fe16d7 100644 --- a/src-docs/src/views/list_group/list_group.js +++ b/src-docs/src/views/list_group/list_group.js @@ -55,7 +55,7 @@ export default class extends Component { - + diff --git a/src-docs/src/views/nav_drawer/nav_drawer.js b/src-docs/src/views/nav_drawer/nav_drawer.js index af13f8a9121..d043bf1f906 100644 --- a/src-docs/src/views/nav_drawer/nav_drawer.js +++ b/src-docs/src/views/nav_drawer/nav_drawer.js @@ -17,16 +17,16 @@ import { EuiHeaderLogo, EuiIcon, EuiTitle, + EuiNavDrawerGroup, EuiNavDrawer, - EuiNavDrawerMenu, - EuiNavDrawerFlyout, - EuiListGroup, EuiHorizontalRule, EuiShowFor, - EuiHideFor, - EuiOutsideClickDetector, + EuiFocusTrap, + EuiButton } from '../../../../src/components'; +import { keyCodes } from '../../../../src/services'; + import HeaderUserMenu from '../header/header_user_menu'; import HeaderSpacesMenu from '../header/header_spaces_menu'; @@ -35,48 +35,84 @@ export default class extends Component { super(props); this.state = { - isCollapsed: true, - flyoutIsCollapsed: true, - flyoutIsAnimating: false, - navFlyoutTitle: undefined, - navFlyoutContent: [], - mobileIsHidden: true, - showScrollbar: false, - outsideClickDisabled: true, - isManagingFocus: false, + isFullScreen: false, }; this.topLinks = [ { label: 'Recently viewed', iconType: 'clock', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Recently viewed items', - onClick: () => this.expandFlyout(this.recentLinks, 'Recent items'), - extraAction: { - color: 'subdued', - iconType: 'arrowRight', - iconSize: 's', - 'aria-label': 'Expand to view recent apps and objects', - onClick: () => this.expandFlyout(this.recentLinks, 'Recent items'), - alwaysShow: true, + flyoutMenu: { + title: 'Recent items', + listItems: [ + { + label: 'My dashboard', + href: '/#/layout/nav-drawer', + iconType: 'dashboardApp', + extraAction: { + color: 'subdued', + iconType: 'starEmpty', + iconSize: 's', + 'aria-label': 'Add to favorites', + }, + }, + { + label: 'Workpad with title that wraps', + href: '/#/layout/nav-drawer', + iconType: 'canvasApp', + extraAction: { + color: 'subdued', + iconType: 'starEmpty', + iconSize: 's', + 'aria-label': 'Add to favorites', + }, + }, + { + label: 'My logs', + href: '/#/layout/nav-drawer', + iconType: 'loggingApp', + 'aria-label': 'This is an alternate aria-label', + extraAction: { + color: 'subdued', + iconType: 'starEmpty', + iconSize: 's', + 'aria-label': 'Add to favorites', + }, + }, + ], }, }, { label: 'Favorites', iconType: 'starEmpty', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Favorited items', - onClick: () => this.expandFlyout(this.favoriteLinks, 'Favorite items'), - extraAction: { - color: 'subdued', - iconType: 'arrowRight', - iconSize: 's', - 'aria-label': 'Expand to view favorited apps and objects', - onClick: () => this.expandFlyout(this.favoriteLinks, 'Favorite items'), - alwaysShow: true, + flyoutMenu: { + title: 'Favorite items', + listItems: [ + { + label: 'My workpad', + href: '/#/layout/nav-drawer', + iconType: 'canvasApp', + extraAction: { + color: 'subdued', + iconType: 'starFilled', + iconSize: 's', + 'aria-label': 'Add to favorites', + alwaysShow: true, + }, + }, + { + label: 'My logs', + href: '/#/layout/nav-drawer', + iconType: 'loggingApp', + extraAction: { + color: 'subdued', + iconType: 'starFilled', + iconSize: 's', + 'aria-label': 'Add to favorites', + alwaysShow: true, + }, + }, + ], }, }, ]; @@ -86,9 +122,6 @@ export default class extends Component { label: 'Canvas', href: '/#/layout/nav-drawer', iconType: 'canvasApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Canvas', isActive: true, extraAction: { color: 'subdued', @@ -102,9 +135,6 @@ export default class extends Component { label: 'Discover', href: '/#/layout/nav-drawer', iconType: 'discoverApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Discover', extraAction: { color: 'subdued', iconType: 'pin', @@ -116,9 +146,6 @@ export default class extends Component { label: 'Visualize', href: '/#/layout/nav-drawer', iconType: 'visualizeApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Visualize', extraAction: { color: 'subdued', iconType: 'pin', @@ -130,9 +157,6 @@ export default class extends Component { label: 'Dashboard', href: '/#/layout/nav-drawer', iconType: 'dashboardApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Dashboard', extraAction: { color: 'subdued', iconType: 'pin', @@ -144,9 +168,6 @@ export default class extends Component { label: 'Machine learning', href: '/#/layout/nav-drawer', iconType: 'machineLearningApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Machine learning', extraAction: { color: 'subdued', iconType: 'pin', @@ -158,9 +179,6 @@ export default class extends Component { label: 'Graph', href: '/#/layout/nav-drawer', iconType: 'graphApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Graph', extraAction: { color: 'subdued', iconType: 'pin', @@ -175,9 +193,6 @@ export default class extends Component { label: 'APM', href: '/#/layout/nav-drawer', iconType: 'apmApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'APM', extraAction: { color: 'subdued', iconType: 'pin', @@ -189,9 +204,6 @@ export default class extends Component { label: 'Infrastructure', href: '/#/layout/nav-drawer', iconType: 'infraApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Infra', extraAction: { color: 'subdued', iconType: 'pin', @@ -203,9 +215,6 @@ export default class extends Component { label: 'Log viewer', href: '/#/layout/nav-drawer', iconType: 'loggingApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Logs', extraAction: { color: 'subdued', iconType: 'pin', @@ -217,9 +226,6 @@ export default class extends Component { label: 'Uptime', href: '/#/layout/nav-drawer', iconType: 'upgradeAssistantApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Graph', extraAction: { color: 'subdued', iconType: 'pin', @@ -231,9 +237,6 @@ export default class extends Component { label: 'Maps', href: '/#/layout/nav-drawer', iconType: 'gisApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Maps', extraAction: { color: 'subdued', iconType: 'pin', @@ -245,9 +248,6 @@ export default class extends Component { label: 'SIEM', href: '/#/layout/nav-drawer', iconType: 'securityAnalyticsApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'SIEM', extraAction: { color: 'subdued', iconType: 'pin', @@ -261,144 +261,67 @@ export default class extends Component { { label: 'Admin', iconType: 'managementApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Admin', - onClick: () => this.expandFlyout(this.adminSubLinks, 'Tools and settings'), - extraAction: { - color: 'subdued', - iconType: 'arrowRight', - iconSize: 's', - 'aria-label': 'Pin to top', - alwaysShow: true, - onClick: () => this.expandFlyout(this.adminSubLinks, 'Tools and settings'), + flyoutMenu: { + title: 'Tools and settings', + listItems: [ + { + label: 'Dev tools', + href: '/#/layout/nav-drawer', + iconType: 'devToolsApp', + extraAction: { + color: 'subdued', + iconType: 'starEmpty', + iconSize: 's', + 'aria-label': 'Add to favorites', + }, + }, + { + label: 'Stack Monitoring', + href: '/#/layout/nav-drawer', + iconType: 'monitoringApp', + extraAction: { + color: 'subdued', + iconType: 'starEmpty', + iconSize: 's', + 'aria-label': 'Add to favorites', + }, + }, + { + label: 'Stack Management', + href: '/#/layout/nav-drawer', + iconType: 'managementApp', + extraAction: { + color: 'subdued', + iconType: 'starEmpty', + iconSize: 's', + 'aria-label': 'Add to favorites', + }, + }, + ] }, }, ]; + } - this.adminSubLinks = [ - { - label: 'Dev tools', - href: '/#/layout/nav-drawer', - iconType: 'devToolsApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Dev tools', - extraAction: { - color: 'subdued', - iconType: 'starEmpty', - iconSize: 's', - 'aria-label': 'Add to favorites', - }, - }, - { - label: 'Stack Monitoring', - href: '/#/layout/nav-drawer', - iconType: 'monitoringApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Monitoring', - extraAction: { - color: 'subdued', - iconType: 'starEmpty', - iconSize: 's', - 'aria-label': 'Add to favorites', - }, - }, - { - label: 'Stack Management', - href: '/#/layout/nav-drawer', - iconType: 'managementApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Management', - extraAction: { - color: 'subdued', - iconType: 'starEmpty', - iconSize: 's', - 'aria-label': 'Add to favorites', - }, - }, - ]; + onKeyDown = event => { + if (event.keyCode === keyCodes.ESCAPE) { + event.preventDefault(); + event.stopPropagation(); + this.closeFullScreen(); + } + }; - this.recentLinks = [ - { - label: 'My dashboard', - href: '/#/layout/nav-drawer', - iconType: 'dashboardApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'My dashboard', - extraAction: { - color: 'subdued', - iconType: 'starEmpty', - iconSize: 's', - 'aria-label': 'Add to favorites', - }, - }, - { - label: 'Workpad with title that wraps', - href: '/#/layout/nav-drawer', - iconType: 'canvasApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'Workpad with title that wraps', - extraAction: { - color: 'subdued', - iconType: 'starEmpty', - iconSize: 's', - 'aria-label': 'Add to favorites', - }, - }, - { - label: 'My logs', - href: '/#/layout/nav-drawer', - iconType: 'loggingApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'My logs', - extraAction: { - color: 'subdued', - iconType: 'starEmpty', - iconSize: 's', - 'aria-label': 'Add to favorites', - }, - }, - ]; + toggleFullScreen = () => { + this.setState(prevState => ({ + isFullScreen: !prevState.isFullScreen, + })); + }; - this.favoriteLinks = [ - { - label: 'My workpad', - href: '/#/layout/nav-drawer', - iconType: 'canvasApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'My workpad', - extraAction: { - color: 'subdued', - iconType: 'starFilled', - iconSize: 's', - 'aria-label': 'Add to favorites', - alwaysShow: true, - }, - }, - { - label: 'My logs', - href: '/#/layout/nav-drawer', - iconType: 'loggingApp', - size: 's', - style: { color: 'inherit' }, - 'aria-label': 'My logs', - extraAction: { - color: 'subdued', - iconType: 'starFilled', - iconSize: 's', - 'aria-label': 'Add to favorites', - alwaysShow: true, - }, - }, - ]; - } + closeFullScreen = () => { + this.setState({ + isFullScreen: false, + }); + }; renderLogo() { return ( @@ -414,7 +337,7 @@ export default class extends Component { return ( this.navDrawerRef.toggleOpen()} > @@ -469,181 +392,49 @@ export default class extends Component { ); } - timeoutID; - - toggleOpen = () => { - this.setState({ - mobileIsHidden: !this.state.mobileIsHidden - }); - - setTimeout(() => { - this.setState({ - outsideClickDisabled: this.state.mobileIsHidden ? true : false, - }); - }, 350); - }; - - expandDrawer = () => { - this.setState({ isCollapsed: false }); - - setTimeout(() => { - this.setState({ - showScrollbar: true, - }); - }, 350); - - // This prevents the drawer from collapsing when tabbing through children - // by clearing the timeout thus cancelling the onBlur event (see focusOut). - // This means isManagingFocus remains true as long as a child element - // has focus. This is the case since React bubbles up onFocus and onBlur - // events from the child elements. - clearTimeout(this.timeoutID); - - if (!this.state.isManagingFocus) { - this.setState({ - isManagingFocus: true, - }); - } - }; - - collapseDrawer = () => { - this.setState({ - flyoutIsAnimating: false, - }); - - setTimeout(() => { - this.setState({ - isCollapsed: true, - flyoutIsCollapsed: true, - mobileIsHidden: true, - showScrollbar: false, - outsideClickDisabled: true, - }); - }, 350); - - // Scrolls the menu and flyout back to top when the nav drawer collapses - setTimeout(() => { - document.getElementById('navDrawerMenu').scrollTop = 0; - document.getElementById('navDrawerFlyout').scrollTop = 0; - }, 300); - }; - - focusOut = () => { - // This collapses the drawer when no children have focus (i.e. tabbed out). - // In other words, if focus does not bubble up from a child element, then - // the drawer will collapse. See the corresponding block in expandDrawer - // (called by onFocus) which cancels this operation via clearTimeout. - this.timeoutID = setTimeout(() => { - if (this.state.isManagingFocus) { - this.setState({ - isManagingFocus: false, - }); - - this.collapseDrawer(); - } - }, 0); - } - - expandFlyout = (links, title) => { - const content = links; - - this.setState(prevState => ({ - flyoutIsCollapsed: prevState.navFlyoutTitle === title ? !this.state.flyoutIsCollapsed : false, - })); - - this.setState({ - flyoutIsAnimating: true, - navFlyoutTitle: title, - navFlyoutContent: content - }); - }; - - collapseFlyout = () => { - this.setState({ flyoutIsAnimating: true }); - - setTimeout(() => { - this.setState({ - flyoutIsCollapsed: true, - navFlyoutTitle: null, - navFlyoutContent: null - }); - }, 250); - }; + setNavDrawerRef = ref => this.navDrawerRef = ref; render() { - const { - isCollapsed, - flyoutIsCollapsed, - flyoutIsAnimating, - navFlyoutTitle, - navFlyoutContent, - mobileIsHidden, - showScrollbar, - outsideClickDisabled, - } = this.state; - return ( - -
- - - + let fullScreenDisplay; + + if (this.state.isFullScreen) { + + fullScreenDisplay = ( + +
+ + + + + {this.renderMenuTrigger()} + + + {this.renderLogo()} - {this.renderMenuTrigger()} + - - {this.renderLogo()} - - - - + - {this.renderBreadcrumbs()} + {this.renderBreadcrumbs()} - - - - - - - this.collapseDrawer()} - isDisabled={outsideClickDisabled} - > - - - - - - - - - - - + + + + + + + + + + + + + + - - - - + + @@ -660,13 +451,38 @@ export default class extends Component { - Body content + + Exit fullscreen demo + - - - -
+ + +
+ + ); + } + return ( + + + Show fullscreen demo + + + {/* + If the below fullScreen code renders, it actually attaches to the body because of + EuiOverlayMask's React portal usage. + */} + + {fullScreenDisplay} ); } diff --git a/src-docs/src/views/nav_drawer/nav_drawer_example.js b/src-docs/src/views/nav_drawer/nav_drawer_example.js index 0cfd4a5f95f..ee6f93d4273 100644 --- a/src-docs/src/views/nav_drawer/nav_drawer_example.js +++ b/src-docs/src/views/nav_drawer/nav_drawer_example.js @@ -9,11 +9,15 @@ import { import { EuiNavDrawer, EuiCode, + EuiCallOut, } from '../../../../src/components'; import NavDrawer from './nav_drawer'; const navDrawerSource = require('!!raw-loader!./nav_drawer'); const navDrawerHtml = renderToHtml(NavDrawer); +const navDrawerSnippet = ` + +`; export const NavDrawerExample = { title: 'Nav Drawer', @@ -26,13 +30,28 @@ export const NavDrawerExample = { code: navDrawerHtml, }], text: ( -

- EuiNavDrawer provides a side navigation feature that - is complete with interactions and a mobile-friendly design. It can - contain one or more EuiListGroup components and is - designed to be used in conjunction with EuiHeader. -

+
+

+ EuiNavDrawer provides a side navigation feature that + is complete with interactions and a mobile-friendly design. It can + contain one or more EuiNavDrawerGroup components and is + designed to be used in conjunction with EuiHeader. +

+ +

+ Providing a flyoutMenu prop on + the listItems object of + an EuiNavDrawerGroup will result in that link + opening a secondary menu. Note that this will also override + the onClick event. See sample data in the Demo JS tab. +

+
+
), + snippet: navDrawerSnippet, props: { EuiNavDrawer, }, diff --git a/src/components/index.js b/src/components/index.js index beced0b814d..3f718c299bd 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -235,7 +235,7 @@ export { export { EuiNavDrawer, - EuiNavDrawerMenu, + EuiNavDrawerGroup, EuiNavDrawerFlyout, } from './nav_drawer'; diff --git a/src/components/list_group/__snapshots__/list_group_item.test.js.snap b/src/components/list_group/__snapshots__/list_group_item.test.js.snap index 1b34c68b527..edcd1a84d0e 100644 --- a/src/components/list_group/__snapshots__/list_group_item.test.js.snap +++ b/src/components/list_group/__snapshots__/list_group_item.test.js.snap @@ -9,6 +9,7 @@ exports[`EuiListGroupItem is rendered 1`] = ` > Label @@ -26,6 +27,7 @@ exports[`EuiListGroupItem renders href 1`] = ` > Label diff --git a/src/components/list_group/_index.scss b/src/components/list_group/_index.scss index ab5c9e1dd4c..9d6423c4f21 100644 --- a/src/components/list_group/_index.scss +++ b/src/components/list_group/_index.scss @@ -1,4 +1,5 @@ // List group provides a way to neatly present a set of text-based items +@import '../header/variables'; @import 'list_group'; @import 'list_group_item'; diff --git a/src/components/list_group/_list_group_item.scss b/src/components/list_group/_list_group_item.scss index 0c9f7a5b299..d69173a23b7 100644 --- a/src/components/list_group/_list_group_item.scss +++ b/src/components/list_group/_list_group_item.scss @@ -1,6 +1,6 @@ .euiListGroupItem { padding: 0; - margin-top: $euiSizeXS; + margin-top: $euiSizeS; border-radius: $euiBorderRadius; overflow: hidden; display: flex; @@ -38,7 +38,7 @@ .euiListGroupItem__text, .euiListGroupItem__button { - padding: $euiSizeM $euiSizeS; + padding: $euiSizeS; display: flex; align-items: center; flex: 1 0 auto; // The flex-shrink and flex-basis values are needed for IE11 @@ -81,17 +81,20 @@ .euiListGroupItem--xSmall { font-size: $euiFontSizeXS; + line-height: $euiSizeM; } .euiListGroupItem--small { font-size: $euiFontSizeS; + line-height: $euiSize; } .euiListGroupItem--large { font-size: $euiFontSizeL; + line-height: $euiSize; } -.euiListGroup-wrapText { +.euiListGroupItem--wrapText { .euiListGroupItem__button, .euiListGroupItem__text { width: 100%; @@ -99,7 +102,7 @@ } .euiListGroupItem__label { - white-space: initial; + white-space: inherit; } } @@ -120,3 +123,7 @@ border-bottom-right-radius: $euiBorderRadius; } } + +.euiListGroupItem__tooltip { + width: 100%; +} diff --git a/src/components/list_group/list_group.js b/src/components/list_group/list_group.js index 299550655c0..5dd88822178 100644 --- a/src/components/list_group/list_group.js +++ b/src/components/list_group/list_group.js @@ -15,6 +15,7 @@ export const EuiListGroup = ({ listItems, maxWidth, style, + showToolTips, ...rest, }) => { @@ -32,7 +33,6 @@ export const EuiListGroup = ({ { 'euiListGroup-flush': flush, 'euiListGroup-bordered': bordered, - 'euiListGroup-wrapText': wrapText, }, widthClassName, className @@ -45,13 +45,23 @@ export const EuiListGroup = ({ return [ ]; }) ); } else { - childrenOrListItems = children; + if (showToolTips) { + childrenOrListItems = React.Children.map(children, child => { + return React.cloneElement(child, { + showToolTip: true + }); + }); + } else { + childrenOrListItems = children; + } } return ( @@ -73,6 +83,7 @@ EuiListGroup.propTypes = { iconType: PropTypes.string, isActive: PropTypes.boolean, isDisabled: PropTypes.boolean, + showToolTip: PropTypes.boolean, })), children: PropTypes.node, className: PropTypes.string, @@ -92,6 +103,11 @@ EuiListGroup.propTypes = { */ wrapText: PropTypes.bool, + /** + * Display tooltips on all list items + */ + showToolTips: PropTypes.bool, + /** * Sets the max-width of the page, * set to `true` to use the default size, @@ -111,4 +127,5 @@ EuiListGroup.defaultProps = { bordered: false, wrapText: false, maxWidth: true, + showToolTips: false, }; diff --git a/src/components/list_group/list_group_item.js b/src/components/list_group/list_group_item.js index 22c871dfe08..6b48c367397 100644 --- a/src/components/list_group/list_group_item.js +++ b/src/components/list_group/list_group_item.js @@ -1,9 +1,10 @@ -import React from 'react'; +import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { EuiButtonIcon } from '../button'; import { ICON_TYPES, EuiIcon } from '../icon'; +import { EuiToolTip } from '../tool_tip'; const sizeToClassNameMap = { xs: 'euiListGroupItem--xSmall', @@ -24,6 +25,8 @@ export const EuiListGroupItem = ({ extraAction, onClick, size, + showToolTip, + wrapText, ...rest }) => { const classes = classNames( @@ -34,6 +37,7 @@ export const EuiListGroupItem = ({ 'euiListGroupItem-isDisabled': isDisabled, 'euiListGroupItem-isClickable': href || onClick, 'euiListGroupItem-hasExtraAction': extraAction, + 'euiListGroupItem--wrapText': wrapText, }, className ); @@ -65,6 +69,16 @@ export const EuiListGroupItem = ({ ); } + // Only add the label as the title attribute if it's possibly truncated + const labelContent = ( + + {label} + + ); + // Handle the variety of interaction behavior let itemContent; @@ -72,7 +86,7 @@ export const EuiListGroupItem = ({ itemContent = ( {iconNode} - {label} + {labelContent} ); } else if ((href && isDisabled) || onClick) { @@ -84,23 +98,43 @@ export const EuiListGroupItem = ({ {...rest} > {iconNode} - {label} + {labelContent} ); } else { itemContent = ( {iconNode} - {label} + {labelContent} ); } + if (showToolTip) { + itemContent = ( +
  • + + {itemContent} + +
  • + ); + } else { + itemContent = ( +
  • + {itemContent} + {extraActionNode} +
  • + ); + } + return ( -
  • - {itemContent} - {extraActionNode} -
  • + {itemContent} ); }; @@ -137,6 +171,11 @@ EuiListGroupItem.propTypes = { */ iconType: PropTypes.oneOf(ICON_TYPES), + /** + * Display tooltip on list item + */ + showToolTip: PropTypes.bool, + /** * Adds an `EuiButtonIcon` to the right side of the item; `iconType` is required; * pass `alwaysShow` if you don't want the default behavior of only showing on hover @@ -147,10 +186,16 @@ EuiListGroupItem.propTypes = { }), onClick: PropTypes.func, + + /** + * Allow link text to wrap + */ + wrapText: PropTypes.bool, }; EuiListGroupItem.defaultProps = { isActive: false, isDisabled: false, size: 'm', + showToolTip: false, }; diff --git a/src/components/nav_drawer/_index.scss b/src/components/nav_drawer/_index.scss index fc62c67f187..bb973574c19 100644 --- a/src/components/nav_drawer/_index.scss +++ b/src/components/nav_drawer/_index.scss @@ -3,5 +3,5 @@ // Components @import 'nav_drawer'; -@import 'nav_drawer_menu'; @import 'nav_drawer_flyout'; +@import 'nav_drawer_group'; diff --git a/src/components/nav_drawer/_nav_drawer.scss b/src/components/nav_drawer/_nav_drawer.scss index 78004ca67bd..39e9d20fa57 100644 --- a/src/components/nav_drawer/_nav_drawer.scss +++ b/src/components/nav_drawer/_nav_drawer.scss @@ -11,108 +11,109 @@ background: $euiHeaderBackgroundColor; box-shadow: $euiNavDrawerSideShadow; transition: width $euiAnimSpeedExtraFast $euiAnimSlightResistance; - transition-delay: $euiNavDrawerContractingDelay; + display: flex; - &.euiNavDrawer-isCollapsed { - .euiListGroupItem-hasExtraAction .euiListGroupItem__button { - max-width: 100%; + .euiNavDrawerMenu { + @include euiScrollBar; + overflow-y: auto; + width: $euiNavDrawerWidthCollapsed; + height: 100%; + + &-hasFooter { + padding-bottom: $euiSizeXXL; } } - &.euiNavDrawer-isExpanded { - width: $euiNavDrawerWidthExpanded; - transition-delay: $euiNavDrawerExpandingDelay; - - .euiNavDrawerMenu .euiListGroupItem__label { - opacity: 1; - transition-delay: ( - $euiNavDrawerExpandingDelay + $euiNavDrawerMenuAddedDelay - ); + .euiNavDrawer__expandButton { + @include euiBottomShadowFlat; + background-color: $euiColorEmptyShade; + position: fixed; + bottom: 0; + width: $euiNavDrawerWidthCollapsed; + transition: width $euiAnimSpeedExtraFast; + z-index: $euiZHeader + 1; + + .euiListGroupItem__button { + padding: $euiSizeM $euiSize; } + } + &.euiNavDrawer-isCollapsed { &.euiNavDrawer-flyoutIsExpanded { - width: $euiNavDrawerWidthExpanded * 2; + width: $euiNavDrawerWidthCollapsed + $euiNavDrawerWidthExpanded; } - &.euiNavDrawer-flyoutIsAnimating { - transition-delay: 0s; + .euiNavDrawerMenu { + // Prevents scrollbar from overlapping links in collapsed form + // sass-lint:disable-block no-vendor-prefixes + // sass-lint:disable-block no-misspelled-properties + -ms-overflow-style: -ms-autohiding-scrollbar; + scrollbar-width: none; + + &::-webkit-scrollbar { + width: 0; + height: 0; + } + + .euiListGroup:not(.euiNavDrawer__expandButton) .euiListGroupItem__button { + max-width: $euiSizeXL; + } + + .euiListGroupItem__extraAction { + visibility: hidden; + } } } - .euiNavDrawerMenu .euiListGroupItem__label { - white-space: nowrap; - opacity: 0; - transition: opacity $euiAnimSpeedNormal; - transition-delay: ( - $euiNavDrawerContractingDelay + $euiNavDrawerMenuAddedDelay - ); - } + &.euiNavDrawer-isExpanded { + width: $euiNavDrawerWidthExpanded; - &.euiNavDrawer-showScrollbar .euiNavDrawerMenu, - &.euiNavDrawer-showScrollbar .euiNavDrawerFlyout { - height: 100%; - overflow-y: auto; - // This prevents the scrollbar from overlapping the nav links. Scrollbars still show on hover - // sass-lint:disable no-vendor-prefixes - -ms-overflow-style: -ms-autohiding-scrollbar; - } + .euiNavDrawerMenu, + .euiNavDrawer__expandButton { + width: $euiNavDrawerWidthExpanded; + } - .euiListGroupItem__label { - line-height: $euiSize; + &.euiNavDrawer-flyoutIsExpanded { + width: $euiNavDrawerWidthExpanded + $euiNavDrawerWidthCollapsed; + } } +} - .euiListGroupItem__extraAction { - visibility: hidden; - } +.euiNavDrawerPage { + height: 100%; - &.euiNavDrawer-showScrollbar .euiListGroupItem__extraAction { - visibility: visible; + .euiNavDrawerPage__pageBody { + margin-left: $euiNavDrawerWidthCollapsed; } } @include euiBreakpoint('xs', 's') { .euiNavDrawer { - width: $euiNavDrawerWidthExpanded; - - &.euiNavDrawer-mobileIsHidden { - width: 0; - } - - &.euiNavDrawer-isExpanded.euiNavDrawer-flyoutIsExpanded { - width: $euiNavDrawerWidthCollapsed + $euiNavDrawerWidthExpanded; + width: 0; - .euiNavDrawerFlyout { - left: $euiNavDrawerWidthCollapsed; - } - } - - &.euiNavDrawer-flyoutIsExpanded { - .euiNavDrawerMenu { - width: $euiNavDrawerWidthCollapsed; - overflow-y: hidden; - - .euiListGroupItem__extraAction { - visibility: hidden; - } - } - - .euiNavDrawerMenu .euiListGroupItem__label { - display: none; + &.euiNavDrawer-isExpanded .euiNavDrawerMenu { + .euiListGroupItem__icon { + margin-right: $euiSizeM; } } &.euiNavDrawer-flyoutIsCollapsed .euiNavDrawerFlyout { width: 0; - transition-delay: 0s; transition-duration: 0s; } - .euiNavDrawerMenu .euiListGroupItem__label { - opacity: 1; + // No expand toggle on mobile + + .euiNavDrawerMenu-hasFooter { + padding-bottom: 0; } - .euiListGroupItem__extraAction { - visibility: visible; + .euiNavDrawer__expandButton { + display: none; } } + + .euiNavDrawerPage .euiNavDrawerPage__pageBody { + margin-left: 0; + } } diff --git a/src/components/nav_drawer/_nav_drawer_flyout.scss b/src/components/nav_drawer/_nav_drawer_flyout.scss index 789ecbd3457..c0e64954df0 100644 --- a/src/components/nav_drawer/_nav_drawer_flyout.scss +++ b/src/components/nav_drawer/_nav_drawer_flyout.scss @@ -1,23 +1,28 @@ .euiNavDrawerFlyout { @include euiScrollBar; - position: absolute; - left: $euiNavDrawerWidthExpanded; - top: 0; - width: $euiNavDrawerWidthExpanded; + width: 0; height: 100%; - padding: $euiSize; + padding: $euiSizeM $euiSizeS; + overflow-y: auto; background-color: $euiNavDrawerBackgroundColor; border-left: $euiBorderThin; box-shadow: $euiNavDrawerSideShadow; + visibility: hidden; opacity: 0; &.euiNavDrawerFlyout-isExpanded { + visibility: visible; opacity: 1; - transition: opacity $euiAnimSpeedNormal; + width: $euiNavDrawerWidthExpanded; + transition: opacity $euiAnimSpeedFast $euiNavDrawerContractingDelay, width $euiAnimSpeedNormal; } &.euiNavDrawerFlyout-isCollapsed { - transition: opacity $euiAnimSpeedFast $euiNavDrawerContractingDelay; + transition: opacity $euiAnimSpeedFast, width $euiAnimSpeedFast; + } + + .euiNavDrawerFlyout__title { + margin: 0 $euiSizeS $euiSizeXS; } .euiNavDrawerFlyout__listGroup { diff --git a/src/components/nav_drawer/_nav_drawer_group.scss b/src/components/nav_drawer/_nav_drawer_group.scss new file mode 100644 index 00000000000..dc066e2aa9d --- /dev/null +++ b/src/components/nav_drawer/_nav_drawer_group.scss @@ -0,0 +1,14 @@ +.euiNavDrawerGroup__item { + .euiListGroupItem__label { + transition: all $euiAnimSpeedExtraFast; + } + + .euiListGroupItem__button { + color: inherit; // Force color to inherit from regular text color in case it's an anchor tag + + &:focus { + background-color: $euiFocusBackgroundColor; + border-radius: $euiBorderRadius; + } + } +} diff --git a/src/components/nav_drawer/_nav_drawer_menu.scss b/src/components/nav_drawer/_nav_drawer_menu.scss deleted file mode 100644 index 2ef3f729783..00000000000 --- a/src/components/nav_drawer/_nav_drawer_menu.scss +++ /dev/null @@ -1,4 +0,0 @@ -.euiNavDrawerMenu { - @include euiScrollBar; - max-width: $euiNavDrawerWidthExpanded; -} \ No newline at end of file diff --git a/src/components/nav_drawer/index.js b/src/components/nav_drawer/index.js index d67776d58f9..26722e4880f 100644 --- a/src/components/nav_drawer/index.js +++ b/src/components/nav_drawer/index.js @@ -3,8 +3,8 @@ export { } from './nav_drawer'; export { - EuiNavDrawerMenu, -} from './nav_drawer_menu'; + EuiNavDrawerGroup, +} from './nav_drawer_group'; export { EuiNavDrawerFlyout, diff --git a/src/components/nav_drawer/nav_drawer.js b/src/components/nav_drawer/nav_drawer.js index 03991ae15ef..1465bac1b4f 100644 --- a/src/components/nav_drawer/nav_drawer.js +++ b/src/components/nav_drawer/nav_drawer.js @@ -1,63 +1,250 @@ -import React from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; +import { EuiListGroup, EuiListGroupItem } from '../list_group'; +import { EuiNavDrawerFlyout } from './nav_drawer_flyout'; +import { EuiOutsideClickDetector } from '../outside_click_detector'; +import { EuiI18n } from '../i18n'; +import { EuiFlexItem } from '../flex'; -export const EuiNavDrawer = ({ - children, - className, - isCollapsed, - flyoutIsCollapsed, - flyoutIsAnimating, - mobileIsHidden, - showScrollbar, - ...rest -}) => { - const classes = classNames( - 'euiNavDrawer', - { - 'euiNavDrawer-isCollapsed': isCollapsed, - 'euiNavDrawer-isExpanded': !isCollapsed, - 'euiNavDrawer-flyoutIsCollapsed': flyoutIsCollapsed, - 'euiNavDrawer-flyoutIsExpanded': !flyoutIsCollapsed, - 'euiNavDrawer-flyoutIsAnimating': flyoutIsAnimating, - 'euiNavDrawer-mobileIsHidden': mobileIsHidden, - 'euiNavDrawer-showScrollbar': showScrollbar, - }, - className - ); - - return ( -
    - {children} -
    - ); -}; + +export class EuiNavDrawer extends Component { + constructor(props) { + super(props); + + this.state = { + isCollapsed: true, + flyoutIsCollapsed: true, + outsideClickDisabled: true, + isManagingFocus: false, + toolTipsEnabled: true, + }; + } + + timeoutID; + + toggleOpen = () => { + this.setState({ + isCollapsed: !this.state.isCollapsed + }); + + setTimeout(() => { + this.setState({ + outsideClickDisabled: this.state.isCollapsed ? true : false, + toolTipsEnabled: this.state.isCollapsed ? true : false, + }); + }, 150); + }; + + expandDrawer = () => { + this.setState({ + isCollapsed: false, + outsideClickDisabled: false, + }); + + setTimeout(() => { + this.setState({ + toolTipsEnabled: false, + }); + }, 150); + }; + + collapseDrawer = () => { + this.setState({ + isCollapsed: true, + outsideClickDisabled: this.state.flyoutIsCollapsed ? true : false, + toolTipsEnabled: true, + }); + + // Scrolls the menu and flyout back to top when the nav drawer collapses + setTimeout(() => { + document.getElementById('navDrawerMenu').scrollTop = 0; + }, 50); + }; + + manageFocus = () => { + // This prevents the drawer from collapsing when tabbing through children + // by clearing the timeout thus cancelling the onBlur event (see focusOut). + // This means isManagingFocus remains true as long as a child element + // has focus. This is the case since React bubbles up onFocus and onBlur + // events from the child elements. + clearTimeout(this.timeoutID); + + if (!this.state.isManagingFocus) { + this.setState({ + isManagingFocus: true, + }); + } + } + + focusOut = () => { + // This collapses the drawer when no children have focus (i.e. tabbed out). + // In other words, if focus does not bubble up from a child element, then + // the drawer will collapse. See the corresponding block in expandDrawer + // (called by onFocus) which cancels this operation via clearTimeout. + this.timeoutID = setTimeout(() => { + if (this.state.isManagingFocus) { + this.setState({ + isManagingFocus: false, + }); + + this.closeBoth(); + } + }, 0); + } + + expandFlyout = (links, title) => { + const content = links; + + if (this.state.navFlyoutTitle === title) { + this.collapseFlyout(); + } else { + this.setState({ + flyoutIsCollapsed: false, + navFlyoutTitle: title, + navFlyoutContent: content, + isCollapsed: true, + toolTipsEnabled: false, + outsideClickDisabled: false, + }); + } + }; + + collapseFlyout = () => { + this.setState({ + flyoutIsCollapsed: true, + navFlyoutTitle: null, + navFlyoutContent: null, + toolTipsEnabled: true, + }); + }; + + closeBoth = () => { + this.collapseDrawer(); + this.collapseFlyout(); + } + + render() { + const { + children, + className, + showExpandButton, + showToolTips, + ...rest + } = this.props; + + const classes = classNames( + 'euiNavDrawer', + { + 'euiNavDrawer-isCollapsed': this.state.isCollapsed, + 'euiNavDrawer-isExpanded': !this.state.isCollapsed, + 'euiNavDrawer-flyoutIsCollapsed': this.state.flyoutIsCollapsed, + 'euiNavDrawer-flyoutIsExpanded': !this.state.flyoutIsCollapsed, + }, + className + ); + + let footerContent; + if (showExpandButton) { + footerContent = ( + + + {([sideNavCollapse, sideNavExpand]) => ( + {this.expandDrawer(); this.collapseFlyout();} : () => this.collapseDrawer()} + data-test-subj={this.state.isCollapsed ? 'navDrawerExpandButton-isCollapsed' : 'navDrawerExpandButton-isExpanded'} + /> + )} + + + ); + } + + const flyoutContent = ( + + ); + + // Add an onClick that expands the flyout sub menu for any list items (links) + // that have a flyoutMenu prop (sub links) + let modifiedChildren = children; + + // 1. Loop through the EuiNavDrawer children (EuiListGroup, EuiHorizontalRules, etc) + modifiedChildren = React.Children.map(this.props.children, child => { + // 2. Check if child is an EuiNavDrawerGroup and if it does have a flyout, add the expand function + if (child.type.name === 'EuiNavDrawerGroup') { + const item = React.cloneElement(child, { + flyoutMenuButtonClick: this.expandFlyout, + showToolTips: this.state.toolTipsEnabled && showToolTips, + }); + return item; + } else { + return child; + } + }); + + const menuClasses = classNames( + 'euiNavDrawerMenu', { 'euiNavDrawerMenu-hasFooter': footerContent, }, + ); + + return ( + this.closeBoth()} + isDisabled={this.state.outsideClickDisabled} + > +
    + + + + + {flyoutContent} +
    +
    + ); + } +} EuiNavDrawer.propTypes = { + children: PropTypes.node, className: PropTypes.string, /** - * Toggle the nav drawer between collapsed (docked) and expanded + * Adds fixed toggle button to bottom of menu area */ - isCollapsed: PropTypes.bool, - mobileIsHidden: PropTypes.bool, + showExpandButton: PropTypes.bool, /** - * Toggle the flyout menu between collapsed and expanded + * Display tooltips on side nav items */ - flyoutIsCollapsed: PropTypes.bool, - flyoutIsAnimating: PropTypes.bool, - - showScrollbar: PropTypes.bool, + showToolTips: PropTypes.bool, }; EuiNavDrawer.defaultProps = { - isCollapsed: true, - mobileIsHidden: true, - flyoutIsCollapsed: true, - flyoutIsAnimating: false, - showScrollbar: false, -}; \ No newline at end of file + showExpandButton: true, + showToolTips: true, +}; diff --git a/src/components/nav_drawer/nav_drawer_flyout.js b/src/components/nav_drawer/nav_drawer_flyout.js index dcdc6327ab4..01b5477aaae 100644 --- a/src/components/nav_drawer/nav_drawer_flyout.js +++ b/src/components/nav_drawer/nav_drawer_flyout.js @@ -3,7 +3,8 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { EuiTitle } from '../title'; -import { EuiListGroup } from '../list_group'; +import { EuiNavDrawerGroup } from './nav_drawer_group'; +import { EuiListGroup } from '../list_group/list_group'; export const EuiNavDrawerFlyout = ({ className, title, isCollapsed, listItems, wrapText, ...rest }) => { const classes = classNames( @@ -21,8 +22,8 @@ export const EuiNavDrawerFlyout = ({ className, title, isCollapsed, listItems, w aria-labelledby="navDrawerFlyoutTitle" {...rest} > - - + + ); }; @@ -45,4 +46,4 @@ EuiNavDrawerFlyout.propTypes = { EuiNavDrawerFlyout.defaultProps = { isCollapsed: true, -}; \ No newline at end of file +}; diff --git a/src/components/nav_drawer/nav_drawer_group.js b/src/components/nav_drawer/nav_drawer_group.js new file mode 100644 index 00000000000..ae25750c593 --- /dev/null +++ b/src/components/nav_drawer/nav_drawer_group.js @@ -0,0 +1,53 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +import { EuiListGroup } from '../list_group/list_group'; + +export const EuiNavDrawerGroup = ({ className, listItems, flyoutMenuButtonClick, ...rest }) => { + const classes = classNames( + 'euiNavDrawerGroup', + className + ); + + const listItemsExists = listItems && !!listItems.length; + + // Alter listItems object with prop flyoutMenu and extra props + const newListItems = !listItemsExists ? undefined : listItems.map((item) => { + // If the flyout menu exists, pass back the list of times and the title with the onClick handler of the item + const { flyoutMenu, ...itemProps } = item; + if (flyoutMenu && flyoutMenuButtonClick) { + const items = [...flyoutMenu.listItems]; + const title = `${flyoutMenu.title}`; + itemProps.onClick = () => flyoutMenuButtonClick(items, title); + } + + // Make some declarations of props for the side nav implementation + itemProps.className = classNames('euiNavDrawerGroup__item', item.className); + itemProps.size = item.size || 's'; + itemProps['aria-label'] = item['aria-label'] || item.label; + + // And return the item with conditional `onClick` and without `flyoutMenu` + return { ...itemProps }; + }); + + + return ( + + ); +}; + +EuiNavDrawerGroup.propTypes = { + listItems: PropTypes.arrayOf(PropTypes.shape({ + ...EuiListGroup.propTypes.listItems[0], + flyoutMenu: PropTypes.shape({ + title: PropTypes.string.isRequired, + listItems: EuiListGroup.propTypes.listItems.isRequired, + }), + })), + /** + * While not normally required, it is required to pass a function for handling + * of the flyout menu button click + */ + flyoutMenuButtonClick: PropTypes.func, +}; diff --git a/src/components/nav_drawer/nav_drawer_menu.js b/src/components/nav_drawer/nav_drawer_menu.js deleted file mode 100644 index ac75d0388b5..00000000000 --- a/src/components/nav_drawer/nav_drawer_menu.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; - -export const EuiNavDrawerMenu = ({ children, className, ...rest }) => { - const classes = classNames( - 'euiNavDrawerMenu', - className - ); - - return ( -
    - {children} -
    - ); -}; - -EuiNavDrawerMenu.propTypes = { - className: PropTypes.string, - children: PropTypes.node, -}; \ No newline at end of file From 89a341f0400824a1285d7275132978383ffe8e24 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Tue, 12 Mar 2019 12:34:37 -0700 Subject: [PATCH 2/3] 9.3.0 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 475f805fc0e..7226863ccf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## [`master`](https://github.com/elastic/eui/tree/master) +No public interface changes since `9.3.0`. + +## [`9.3.0`](https://github.com/elastic/eui/tree/v9.3.0) + - Added `footerLink` and `showToolTips` to `EuiNavDrawer` and added `EuiNavDrawerGroup` ([#1701](https://github.com/elastic/eui/pull/1701)) **Bug fixes** diff --git a/package.json b/package.json index 35105402349..d3a21db5446 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@elastic/eui", "description": "Elastic UI Component Library", - "version": "9.2.1", + "version": "9.3.0", "license": "Apache-2.0", "main": "lib", "module": "es", From f78790dc65a4943bdbfd6b27daf27c9c5a9d8899 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Tue, 12 Mar 2019 12:46:40 -0700 Subject: [PATCH 3/3] Updated documentation. --- docs/bundle.js | 3690 ++++++++++++++++++++++++++++++++------------ docs/bundle.js.map | 2 +- 2 files changed, 2686 insertions(+), 1006 deletions(-) diff --git a/docs/bundle.js b/docs/bundle.js index 2697b9cadfc..e817fbc888b 100644 --- a/docs/bundle.js +++ b/docs/bundle.js @@ -45246,6 +45246,25 @@ __webpack_require__(/*! ./_object-sap */ "../../node_modules/core-js/modules/_ob }); +/***/ }), + +/***/ "../../node_modules/core-js/modules/es6.object.is-extensible.js": +/*!************************************************************************************!*\ + !*** /Users/snide/es/eui/node_modules/core-js/modules/es6.object.is-extensible.js ***! + \************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.11 Object.isExtensible(O) +var isObject = __webpack_require__(/*! ./_is-object */ "../../node_modules/core-js/modules/_is-object.js"); + +__webpack_require__(/*! ./_object-sap */ "../../node_modules/core-js/modules/_object-sap.js")('isExtensible', function ($isExtensible) { + return function isExtensible(it) { + return isObject(it) ? $isExtensible ? $isExtensible(it) : true : false; + }; +}); + + /***/ }), /***/ "../../node_modules/core-js/modules/es6.object.keys.js": @@ -45266,6 +45285,26 @@ __webpack_require__(/*! ./_object-sap */ "../../node_modules/core-js/modules/_ob }); +/***/ }), + +/***/ "../../node_modules/core-js/modules/es6.object.prevent-extensions.js": +/*!*****************************************************************************************!*\ + !*** /Users/snide/es/eui/node_modules/core-js/modules/es6.object.prevent-extensions.js ***! + \*****************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.15 Object.preventExtensions(O) +var isObject = __webpack_require__(/*! ./_is-object */ "../../node_modules/core-js/modules/_is-object.js"); +var meta = __webpack_require__(/*! ./_meta */ "../../node_modules/core-js/modules/_meta.js").onFreeze; + +__webpack_require__(/*! ./_object-sap */ "../../node_modules/core-js/modules/_object-sap.js")('preventExtensions', function ($preventExtensions) { + return function preventExtensions(it) { + return $preventExtensions && isObject(it) ? $preventExtensions(meta(it)) : it; + }; +}); + + /***/ }), /***/ "../../node_modules/core-js/modules/es6.object.set-prototype-of.js": @@ -47607,7 +47646,7 @@ exports.push([module.i, "@import url(https://fonts.googleapis.com/css?family=Rob exports.push([module.i, "@import url(https://rsms.me/inter/inter-ui.css);", ""]); // module -exports.push([module.i, "@-webkit-keyframes euiAnimFadeIn {\n 0% {\n opacity: 0; }\n 100% {\n opacity: 1; } }\n@keyframes euiAnimFadeIn {\n 0% {\n opacity: 0; }\n 100% {\n opacity: 1; } }\n\n@-webkit-keyframes euiGrow {\n 0% {\n opacity: 0; }\n 1% {\n opacity: 0;\n -webkit-transform: scale(0);\n transform: scale(0); }\n 100% {\n opacity: 1;\n -webkit-transform: scale(1);\n transform: scale(1); } }\n\n@keyframes euiGrow {\n 0% {\n opacity: 0; }\n 1% {\n opacity: 0;\n -webkit-transform: scale(0);\n transform: scale(0); }\n 100% {\n opacity: 1;\n -webkit-transform: scale(1);\n transform: scale(1); } }\n\n@-webkit-keyframes focusRingAnimate {\n 0% {\n -webkit-box-shadow: 0 0 0 6px rgba(27, 169, 245, 0);\n box-shadow: 0 0 0 6px rgba(27, 169, 245, 0); }\n 100% {\n -webkit-box-shadow: 0 0 0 2px rgba(27, 169, 245, 0.3);\n box-shadow: 0 0 0 2px rgba(27, 169, 245, 0.3); } }\n\n@keyframes focusRingAnimate {\n 0% {\n -webkit-box-shadow: 0 0 0 6px rgba(27, 169, 245, 0);\n box-shadow: 0 0 0 6px rgba(27, 169, 245, 0); }\n 100% {\n -webkit-box-shadow: 0 0 0 2px rgba(27, 169, 245, 0.3);\n box-shadow: 0 0 0 2px rgba(27, 169, 245, 0.3); } }\n\n@-webkit-keyframes focusRingAnimateLarge {\n 0% {\n -webkit-box-shadow: 0 0 0 10px rgba(27, 169, 245, 0);\n box-shadow: 0 0 0 10px rgba(27, 169, 245, 0); }\n 100% {\n -webkit-box-shadow: 0 0 0 4px rgba(27, 169, 245, 0.3);\n box-shadow: 0 0 0 4px rgba(27, 169, 245, 0.3); } }\n\n@keyframes focusRingAnimateLarge {\n 0% {\n -webkit-box-shadow: 0 0 0 10px rgba(27, 169, 245, 0);\n box-shadow: 0 0 0 10px rgba(27, 169, 245, 0); }\n 100% {\n -webkit-box-shadow: 0 0 0 4px rgba(27, 169, 245, 0.3);\n box-shadow: 0 0 0 4px rgba(27, 169, 245, 0.3); } }\n\n.eui-alignBaseline {\n vertical-align: baseline !important; }\n\n.eui-alignBottom {\n vertical-align: bottom !important; }\n\n.eui-alignMiddle {\n vertical-align: middle !important; }\n\n.eui-alignTop {\n vertical-align: top !important; }\n\n.eui-displayBlock {\n display: block !important; }\n\n.eui-displayInline {\n display: inline !important; }\n\n.eui-displayInlineBlock {\n display: inline-block !important; }\n\n.eui-fullWidth {\n display: block !important;\n width: 100% !important; }\n\n.eui-textCenter {\n text-align: center !important; }\n\n.eui-textLeft {\n text-align: left !important; }\n\n.eui-textRight {\n text-align: right !important; }\n\n.eui-textNoWrap {\n white-space: nowrap !important; }\n\n.eui-textInheritColor {\n color: inherit !important; }\n\n.eui-textBreakWord {\n word-break: break-all !important;\n word-break: break-word !important; }\n\n.eui-textBreakAll {\n word-break: break-all !important; }\n\n.eui-textBreakNormal {\n word-break: normal !important; }\n\n.eui-textOverflowWrap {\n overflow-wrap: break-word !important; }\n @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {\n .eui-textOverflowWrap {\n word-break: break-all !important; } }\n\n.eui-textTruncate {\n max-width: 100%;\n /* 1 */\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n white-space: nowrap !important;\n word-wrap: normal !important;\n /* 2 */ }\n\n/**\n * Responsive\n *\n * 3. Be sure to hide/show the element initially\n */\n[class*='eui-hideFor'] {\n display: inline !important;\n /* 3 */ }\n\n[class*='eui-showFor'] {\n display: none !important;\n /* 3 */ }\n\n@media only screen and (max-width: 574px) {\n .eui-hideFor--xs {\n display: none !important; } }\n\n@media only screen and (max-width: 574px) {\n .eui-showFor--xs {\n display: inline !important; } }\n\n@media only screen and (min-width: 575px) and (max-width: 767px) {\n .eui-hideFor--s {\n display: none !important; } }\n\n@media only screen and (min-width: 575px) and (max-width: 767px) {\n .eui-showFor--s {\n display: inline !important; } }\n\n@media only screen and (min-width: 768px) and (max-width: 991px) {\n .eui-hideFor--m {\n display: none !important; } }\n\n@media only screen and (min-width: 768px) and (max-width: 991px) {\n .eui-showFor--m {\n display: inline !important; } }\n\n@media only screen and (min-width: 992px) and (max-width: 1199px) {\n .eui-hideFor--l {\n display: none !important; } }\n\n@media only screen and (min-width: 992px) and (max-width: 1199px) {\n .eui-showFor--l {\n display: inline !important; } }\n\n@media only screen and (min-width: 1200px) {\n .eui-hideFor--xl {\n display: none !important; } }\n\n@media only screen and (min-width: 1200px) {\n .eui-showFor--xl {\n display: inline !important; } }\n\n/**\n * IE doesn't properly wrap groups if it is within a flex-item of a flex-group.\n * Adding the following styles to the flex-item that contains the wrapping group, will fix IE.\n * https://github.com/philipwalton/flexbugs/issues/104\n */\n.euiIEFlexWrapFix {\n -webkit-box-flex: 1;\n -ms-flex-positive: 1;\n flex-grow: 1;\n -ms-flex-negative: 1;\n flex-shrink: 1;\n -ms-flex-preferred-size: 0%;\n flex-basis: 0%; }\n\n/**\n * Adapted from Eric Meyer's reset (http://meyerweb.com/eric/tools/css/reset/, v2.0 | 20110126).\n *\n */\n*, *:before, *:after {\n -webkit-box-sizing: border-box;\n box-sizing: border-box; }\n\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmenu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n margin: 0;\n padding: 0;\n border: none;\n vertical-align: baseline; }\n\ncode, pre {\n font-family: \"Roboto Mono\", Consolas, Menlo, Courier, monospace; }\n\ninput, textarea, select, button {\n font-family: \"Inter UI\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\"; }\n\nem {\n font-style: italic; }\n\nstrong {\n font-weight: 700; }\n\n/* HTML5 display-role reset for older browsers */\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, menu, nav, section {\n display: block; }\n\nhtml {\n font-family: \"Inter UI\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n font-weight: 400;\n letter-spacing: -.005em;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -webkit-font-kerning: normal;\n font-kerning: normal;\n font-size: 16px;\n color: #DFE5EF;\n height: 100%;\n background-color: #1a1b20; }\n\nbody {\n line-height: 1; }\n\n*:focus {\n outline: none; }\n\na {\n text-decoration: none;\n color: #1BA9F5; }\n a:hover {\n text-decoration: none; }\n a:focus {\n text-decoration: none;\n outline: none; }\n\na:hover, button, [role='button'] {\n cursor: pointer; }\n\ninput {\n margin: 0;\n padding: 0; }\n\nbutton {\n background: none;\n border: none;\n padding: 0;\n margin: 0;\n outline: none;\n font-size: 16px;\n font-size: inherit;\n color: inherit;\n border-radius: 0; }\n button:hover {\n cursor: pointer; }\n\nol, ul {\n list-style: none; }\n\nblockquote, q {\n quotes: none; }\n\nblockquote:before, blockquote:after,\nq:before, q:after {\n content: '';\n content: none; }\n\ntable {\n border-collapse: collapse;\n border-spacing: 0; }\n\nhr {\n margin: 0; }\n\nfieldset {\n min-inline-size: auto; }\n\nhtml {\n scrollbar-width: thin;\n scrollbar-color: rgba(152, 162, 179, 0.5) transparent; }\n\n.euiScreenReaderOnly {\n position: absolute;\n left: -10000px;\n top: auto;\n width: 1px;\n height: 1px;\n overflow: hidden; }\n\n.euiAccordion__button {\n text-align: left;\n width: 100%; }\n .euiAccordion__button:hover {\n text-decoration: underline;\n cursor: pointer; }\n .euiAccordion__button:focus .euiAccordion__iconWrapper {\n -webkit-animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate;\n animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate;\n color: #1BA9F5;\n border-radius: 4px; }\n\n.euiAccordion__childWrapper {\n visibility: hidden;\n height: 0;\n opacity: 0;\n overflow-y: hidden;\n -webkit-transform: translatez(0);\n transform: translatez(0);\n -webkit-transition: height 250ms cubic-bezier(0.694, 0.0482, 0.335, 1), opacity 250ms cubic-bezier(0.694, 0.0482, 0.335, 1);\n transition: height 250ms cubic-bezier(0.694, 0.0482, 0.335, 1), opacity 250ms cubic-bezier(0.694, 0.0482, 0.335, 1); }\n\n.euiAccordion__padding--xs {\n padding: 4px; }\n\n.euiAccordion__padding--s {\n padding: 8px; }\n\n.euiAccordion__padding--m {\n padding: 16px; }\n\n.euiAccordion__padding--l {\n padding: 24px; }\n\n.euiAccordion__padding--xl {\n padding: 32px; }\n\n.euiAccordion.euiAccordion-isOpen .euiAccordion__childWrapper {\n visibility: visible;\n opacity: 1;\n height: auto; }\n\n.euiAccordionForm__extraAction {\n opacity: 0;\n -webkit-transition: opacity 250ms cubic-bezier(0.694, 0.0482, 0.335, 1);\n transition: opacity 250ms cubic-bezier(0.694, 0.0482, 0.335, 1); }\n .euiAccordionForm__extraAction:focus {\n opacity: 1; }\n\n.euiAccordionForm__title {\n display: inline-block; }\n\n.euiAccordionForm__button {\n padding: 16px 16px 16px 0; }\n .euiAccordionForm__button:hover {\n text-decoration: none; }\n .euiAccordionForm__button:hover .euiAccordionForm__title {\n text-decoration: underline; }\n\n.euiAccordionForm {\n border-top: 1px solid #343741;\n border-bottom: 1px solid #343741; }\n .euiAccordionForm + .euiAccordionForm {\n border-top: none; }\n .euiAccordionForm:hover .euiAccordionForm__extraAction {\n opacity: 1;\n visibility: visible; }\n\n.euiAvatar {\n -ms-flex-negative: 0;\n flex-shrink: 0;\n display: inline-block;\n background-size: cover;\n text-align: center;\n vertical-align: middle;\n overflow-x: hidden;\n font-weight: 500; }\n\n.euiAvatar--user {\n position: relative;\n border-radius: 50%; }\n .euiAvatar--user:after {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n border-radius: 50%;\n content: '';\n pointer-events: none;\n border: 1px solid rgba(212, 218, 229, 0.05); }\n\n.euiAvatar--space {\n position: relative;\n border-radius: 4px; }\n .euiAvatar--space:after {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n border-radius: 4px;\n content: '';\n pointer-events: none;\n border: 1px solid rgba(212, 218, 229, 0.05); }\n\n.euiAvatar--s {\n width: 24px;\n height: 24px;\n line-height: 24px;\n font-size: 12px; }\n\n.euiAvatar--m {\n width: 32px;\n height: 32px;\n line-height: 32px;\n font-size: 14.4px; }\n\n.euiAvatar--l {\n width: 40px;\n height: 40px;\n line-height: 40px;\n font-size: 19.2px; }\n\n.euiAvatar--xl {\n width: 64px;\n height: 64px;\n line-height: 64px;\n font-size: 25.6px; }\n\n/**\n * 1. Accounts for the border\n */\n.euiBadge {\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n /* 1 */\n display: inline-block;\n text-decoration: none;\n -webkit-box-sizing: content-box;\n box-sizing: content-box;\n border-radius: 2px;\n border: solid 1px transparent;\n padding: 0 8px;\n background-color: transparent;\n white-space: nowrap;\n vertical-align: middle;\n text-align: center;\n overflow: hidden; }\n .euiBadge + .euiBadge {\n margin-left: 4px; }\n .euiBadge .euiBadge__content {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n overflow: hidden; }\n .euiBadge .euiBadge__text {\n overflow: hidden;\n text-overflow: ellipsis;\n -webkit-box-flex: 1;\n -ms-flex: 1 1 auto;\n flex: 1 1 auto; }\n .euiBadge:focus {\n -webkit-animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate;\n animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate; }\n .euiBadge .euiBadge__icon {\n -webkit-box-flex: 0;\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n margin-right: 4px; }\n .euiBadge .euiBadge__icon:focus {\n background-color: rgba(255, 255, 255, 0.8);\n color: #000;\n border-radius: 2px; }\n .euiBadge.euiBadge--iconRight .euiBadge__content {\n -webkit-box-orient: horizontal;\n -webkit-box-direction: reverse;\n -ms-flex-direction: row-reverse;\n flex-direction: row-reverse; }\n .euiBadge.euiBadge--iconRight .euiBadge__content .euiBadge__icon {\n margin-left: 4px;\n margin-right: 0; }\n\n.euiBadge--default {\n background-color: #343741;\n color: #FFF; }\n\n.euiBadge--primary {\n background-color: #388ebc;\n color: #FFF; }\n\n.euiBadge--secondary {\n background-color: #9dc2bc;\n color: #000; }\n\n.euiBadge--warning {\n background-color: #ebc98e;\n color: #000; }\n\n.euiBadge--danger {\n background-color: #e65c5c;\n color: #000; }\n\n.euiBadge--accent {\n background-color: #e2a7c2;\n color: #000; }\n\n.euiBadge--hollow {\n background-color: #1D1E24;\n border-color: #343741;\n color: #DFE5EF; }\n\n/**\n * 1. Extend beta badges to at least 40% of the container's width\n * 2. Fix for IE to ensure badges are visible outside of a