diff --git a/CHANGELOG.md b/CHANGELOG.md
index c52426ad960..610df1454db 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
- Added `tableLayout` prop to `EuiTable`, `EuiBasicTable` and `EuiInMemoryTable` to provide the option of auto layout ([#2697](https://github.com/elastic/eui/pull/2697))
- Converted `EuiSuggest` to Typescript ([#2692](https://github.com/elastic/eui/pull/2692))
- Converted `EuiErrorBoundary` to Typescript ([#2690](https://github.com/elastic/eui/pull/2690))
+- Updated `EuiNavDrawer` to accept React fragments ([#2710](https://github.com/elastic/eui/pull/2710))
**Bug fixes**
diff --git a/src/components/nav_drawer/__snapshots__/nav_drawer.test.js.snap b/src/components/nav_drawer/__snapshots__/nav_drawer.test.js.snap
new file mode 100644
index 00000000000..62d0b4ff117
--- /dev/null
+++ b/src/components/nav_drawer/__snapshots__/nav_drawer.test.js.snap
@@ -0,0 +1,845 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EuiNavDrawer is rendered 1`] = `
+
+`;
+
+exports[`EuiNavDrawer renders with falsy children 1`] = `
+
+`;
+
+exports[`EuiNavDrawer renders with fragments 1`] = `
+
+`;
diff --git a/src/components/nav_drawer/nav_drawer.js b/src/components/nav_drawer/nav_drawer.js
index c8da6de6dfd..c9ccf97474d 100644
--- a/src/components/nav_drawer/nav_drawer.js
+++ b/src/components/nav_drawer/nav_drawer.js
@@ -212,6 +212,26 @@ export class EuiNavDrawer extends Component {
}
};
+ modifyChildren = children => {
+ // Loop through the EuiNavDrawer children (EuiListGroup, EuiHorizontalRules, etc)
+ // Filter out falsy items
+ const filteredChildren = React.Children.toArray(children);
+ return React.Children.map(filteredChildren, child => {
+ // Allow for Fragments by recursive modification
+ if (child.type === React.Fragment) {
+ return this.modifyChildren(child.props.children);
+ } else if (child.type === EuiNavDrawerGroup) {
+ // Check if child is an EuiNavDrawerGroup and if it does have a flyout, add the expand function
+ return React.cloneElement(child, {
+ flyoutMenuButtonClick: this.expandFlyout,
+ showToolTips: this.state.toolTipsEnabled && this.props.showToolTips,
+ });
+ } else {
+ return child;
+ }
+ });
+ };
+
render() {
const {
children,
@@ -312,19 +332,7 @@ export class EuiNavDrawer extends Component {
// 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 === EuiNavDrawerGroup) {
- const item = React.cloneElement(child, {
- flyoutMenuButtonClick: this.expandFlyout,
- showToolTips: this.state.toolTipsEnabled && showToolTips,
- });
- return item;
- } else {
- return child;
- }
- });
+ modifiedChildren = this.modifyChildren(this.props.children);
const menuClasses = classNames('euiNavDrawerMenu', {
'euiNavDrawerMenu-hasFooter': footerContent,
diff --git a/src/components/nav_drawer/nav_drawer.test.js b/src/components/nav_drawer/nav_drawer.test.js
new file mode 100644
index 00000000000..afa761a6511
--- /dev/null
+++ b/src/components/nav_drawer/nav_drawer.test.js
@@ -0,0 +1,154 @@
+import React from 'react';
+import { render } from 'enzyme';
+
+import { EuiNavDrawer } from './nav_drawer';
+import { EuiNavDrawerGroup } from './nav_drawer_group';
+
+const extraAction = {
+ color: 'subdued',
+ iconType: 'pin',
+ iconSize: 's',
+};
+
+const topLinks = [
+ {
+ label: 'Recently viewed',
+ iconType: 'clock',
+ flyoutMenu: {
+ title: 'Recent items',
+ listItems: [
+ {
+ label: 'My dashboard',
+ href: '#',
+ iconType: 'dashboardApp',
+ extraAction,
+ },
+ {
+ label: 'Workpad with title that wraps',
+ href: '#',
+ iconType: 'canvasApp',
+ extraAction,
+ },
+ {
+ label: 'My logs',
+ href: '#',
+ iconType: 'logsApp',
+ 'aria-label': 'This is an alternate aria-label',
+ extraAction,
+ },
+ ],
+ },
+ },
+ {
+ label: 'Favorites',
+ iconType: 'starEmpty',
+ flyoutMenu: {
+ title: 'Favorite items',
+ listItems: [
+ {
+ label: 'My workpad',
+ href: '#',
+ iconType: 'canvasApp',
+ extraAction: {
+ color: 'subdued',
+ iconType: 'starFilled',
+ iconSize: 's',
+ 'aria-label': 'Remove from favorites',
+ alwaysShow: true,
+ },
+ },
+ {
+ label: 'My logs',
+ href: '#',
+ iconType: 'logsApp',
+ extraAction: {
+ color: 'subdued',
+ iconType: 'starFilled',
+ iconSize: 's',
+ 'aria-label': 'Remove from favorites',
+ alwaysShow: true,
+ },
+ },
+ ],
+ },
+ },
+];
+
+const exploreLinks = [
+ {
+ label: 'Canvas',
+ href: '#',
+ iconType: 'canvasApp',
+ isActive: true,
+ extraAction,
+ },
+ {
+ label: 'Discover',
+ href: '#',
+ iconType: 'discoverApp',
+ extraAction,
+ },
+ {
+ label: 'Visualize',
+ href: '#',
+ iconType: 'visualizeApp',
+ extraAction,
+ },
+ {
+ label: 'Dashboard',
+ href: '#',
+ iconType: 'dashboardApp',
+ extraAction,
+ },
+ {
+ label: 'Machine learning',
+ href: '#',
+ iconType: 'machineLearningApp',
+ extraAction,
+ },
+ {
+ label: 'Custom Plugin (no icon)',
+ href: '#',
+ extraAction,
+ },
+];
+
+describe('EuiNavDrawer', () => {
+ test('is rendered', () => {
+ const component = render(
+
+
+
+
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+
+ describe('renders', () => {
+ test('with fragments', () => {
+ const component = render(
+
+ <>
+
+
+ >
+
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+
+ test('with falsy children', () => {
+ const component = render(
+
+ {false && }
+ {true ? undefined : }
+
+
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+ });
+});