diff --git a/src-docs/src/views/collapsible_nav/collapsible_nav_all.tsx b/src-docs/src/views/collapsible_nav/collapsible_nav_all.tsx
new file mode 100644
index 00000000000..1f378e0be34
--- /dev/null
+++ b/src-docs/src/views/collapsible_nav/collapsible_nav_all.tsx
@@ -0,0 +1,280 @@
+import React, { useState } from 'react';
+import _ from 'lodash';
+
+import {
+ EuiCollapsibleNav,
+ EuiCollapsibleNavToggle,
+ EuiCollapsibleNavGroup,
+} from '../../../../src/components/collapsible_nav';
+import {
+ EuiHeaderSectionItemButton,
+ EuiHeaderLogo,
+ EuiHeader,
+} from '../../../../src/components/header';
+import { EuiIcon } from '../../../../src/components/icon';
+import { EuiButtonEmpty } from '../../../../src/components/button';
+import { EuiPage } from '../../../../src/components/page';
+import {
+ EuiPinnableListGroup,
+ EuiListGroupItem,
+ EuiPinnableListGroupItemProps,
+} from '../../../../src/components/list_group';
+import { EuiFlexItem } from '../../../../src/components/flex';
+import { EuiHorizontalRule } from '../../../../src/components/horizontal_rule';
+import { GuideFullScreen } from '../../services/full_screen/full_screen';
+
+import {
+ DeploymentsGroup,
+ KibanaNavLinks,
+ SecurityGroup,
+} from './collapsible_nav_list';
+import { EuiShowFor } from '../../../../src/components/responsive';
+
+const TopLinks = [
+ { label: 'Home', iconType: 'home', isActive: true, 'aria-current': true },
+];
+const KibanaLinks: EuiPinnableListGroupItemProps[] = KibanaNavLinks.map(
+ link => {
+ return {
+ ...link,
+ href: '#/navigation/collapsible-nav',
+ };
+ }
+);
+const LearnLinks: EuiPinnableListGroupItemProps[] = [
+ { label: 'Docs', href: '#/navigation/collapsible-nav' },
+ { label: 'Blogs', href: '#/navigation/collapsible-nav' },
+ { label: 'Webinars', href: '#/navigation/collapsible-nav' },
+ { label: 'Elastic.co', href: 'https://elastic.co' },
+];
+
+export default () => {
+ const [navIsOpen, setNavIsOpen] = useState(
+ JSON.parse(String(localStorage.getItem('navIsDocked'))) || false
+ );
+ const [navIsDocked, setNavIsDocked] = useState(
+ JSON.parse(String(localStorage.getItem('navIsDocked'))) || false
+ );
+
+ /**
+ * Accordion toggling
+ */
+ const [openGroups, setOpenGroups] = useState(
+ JSON.parse(String(localStorage.getItem('openNavGroups'))) || [
+ 'Kibana',
+ 'Learn',
+ ]
+ );
+
+ // Save which groups are open and which are not with state and local store
+ const toggleAccordion = (isOpen: boolean, title?: string) => {
+ if (!title) return;
+ const itExists = openGroups.includes(title);
+ if (isOpen) {
+ if (itExists) return;
+ openGroups.push(title);
+ } else {
+ const index = openGroups.indexOf(title);
+ if (index > -1) {
+ openGroups.splice(index, 1);
+ }
+ }
+ setOpenGroups([...openGroups]);
+ localStorage.setItem('openNavGroups', JSON.stringify(openGroups));
+ };
+
+ /**
+ * Pinning
+ */
+ const [pinnedItems, setPinnedItems] = useState<
+ EuiPinnableListGroupItemProps[]
+ >(JSON.parse(String(localStorage.getItem('pinnedItems'))) || []);
+
+ const addPin = (item: any) => {
+ if (!item || _.find(pinnedItems, { label: item.label })) {
+ return;
+ }
+ item.pinned = true;
+ const newPinnedItems = pinnedItems ? pinnedItems.concat(item) : [item];
+ setPinnedItems(newPinnedItems);
+ localStorage.setItem('pinnedItems', JSON.stringify(newPinnedItems));
+ };
+
+ const removePin = (item: any) => {
+ const pinIndex = _.findIndex(pinnedItems, { label: item.label });
+ if (pinIndex > -1) {
+ item.pinned = false;
+ const newPinnedItems = pinnedItems;
+ newPinnedItems.splice(pinIndex, 1);
+ setPinnedItems([...newPinnedItems]);
+ localStorage.setItem('pinnedItems', JSON.stringify(newPinnedItems));
+ }
+ };
+
+ function alterLinksWithCurrentState(
+ links: EuiPinnableListGroupItemProps[],
+ showPinned = false
+ ): EuiPinnableListGroupItemProps[] {
+ return links.map(link => {
+ const { pinned, ...rest } = link;
+ return {
+ pinned: showPinned ? pinned : false,
+ ...rest,
+ };
+ });
+ }
+
+ function addLinkNameToPinTitle(listItem: EuiPinnableListGroupItemProps) {
+ return `Pin ${listItem.label} to top`;
+ }
+
+ function addLinkNameToUnpinTitle(listItem: EuiPinnableListGroupItemProps) {
+ return `Unpin ${listItem.label}`;
+ }
+
+ const leftSectionItems = [
+
+ setNavIsOpen(!navIsOpen)}>
+
+
+ ,
+
Elastic ,
+ ];
+
+ return (
+
+ {setIsFullScreen => (
+
+ setIsFullScreen(false)}>
+ Exit full screen
+ ,
+ ],
+ },
+ ]}
+ />
+
+ {navIsOpen && (
+ setNavIsOpen(false)}>
+ {/* Dark deployments section */}
+
+ {DeploymentsGroup}
+
+
+ {/* Shaded pinned section always with a home item */}
+
+
+
+
+
+
+
+
+ {/* BOTTOM */}
+
+ {/* Kibana section */}
+
+ toggleAccordion(isOpen, 'Kibana')
+ }>
+
+
+
+ {/* Security callout */}
+ {SecurityGroup}
+
+ {/* Learn section */}
+
+ toggleAccordion(isOpen, 'Learn')
+ }>
+
+
+
+ {/* Docking button only for larger screens that can support it*/}
+
+
+ {
+ setNavIsDocked(!navIsDocked);
+ localStorage.setItem(
+ 'navIsDocked',
+ JSON.stringify(!navIsDocked)
+ );
+ }}
+ iconType={navIsDocked ? 'lock' : 'lockOpen'}
+ />
+
+
+
+
+ )}
+
+
+
+ )}
+
+ );
+};
diff --git a/src-docs/src/views/collapsible_nav/collapsible_nav_example.js b/src-docs/src/views/collapsible_nav/collapsible_nav_example.js
index 37ee299c83f..e94d31b86c0 100644
--- a/src-docs/src/views/collapsible_nav/collapsible_nav_example.js
+++ b/src-docs/src/views/collapsible_nav/collapsible_nav_example.js
@@ -22,6 +22,14 @@ import CollapsibleNavGroup from './collapsible_nav_group';
const collapsibleNavGroupSource = require('!!raw-loader!./collapsible_nav_group');
const collapsibleNavGroupHtml = renderToHtml(CollapsibleNavGroup);
+import CollapsibleNavList from './collapsible_nav_list';
+const collapsibleNavListSource = require('!!raw-loader!./collapsible_nav_list');
+const collapsibleNavListHtml = renderToHtml(CollapsibleNavList);
+
+import CollapsibleNavAll from './collapsible_nav_all';
+const collapsibleNavAllSource = require('!!raw-loader!./collapsible_nav_all');
+const collapsibleNavAllHtml = renderToHtml(CollapsibleNavAll);
+
export const CollapsibleNavExample = {
title: 'Collapsible nav',
intro: (
@@ -119,5 +127,95 @@ export const CollapsibleNavExample = {
background="none"
/>`,
},
+ {
+ title: 'Nav groups with lists and other content',
+ source: [
+ {
+ type: GuideSectionTypes.JS,
+ code: collapsibleNavListSource,
+ },
+ {
+ type: GuideSectionTypes.HTML,
+ code: collapsibleNavListHtml,
+ },
+ ],
+ text: (
+ <>
+
+ EuiCollapsibleNavGroups can contain any children.
+ They work well with{' '}
+
+ EuiListGroup, EuiPinnableListGroup
+ {' '}
+ and simple{' '}
+
+ EuiText
+
+ .
+
+
Below are a few established patterns to use.
+ >
+ ),
+ demo:
,
+ snippet: `
+ {}}
+ maxWidth="none"
+ color="subdued"
+ gutterSize="none"
+ size="s"
+ />
+ `,
+ },
+ {
+ title: 'Full pattern with header and saved pins',
+ source: [
+ {
+ type: GuideSectionTypes.JS,
+ code: collapsibleNavAllSource,
+ },
+ {
+ type: GuideSectionTypes.HTML,
+ code: collapsibleNavAllHtml,
+ },
+ ],
+ text: (
+ <>
+
Putting it all together
+
+ The button below will launch a full screen example that includes{' '}
+
+ EuiHeader
+ {' '}
+ with a toggle button to open an EuiCollapsibleNav .
+ The contents of which are multiple{' '}
+ EuiCollapsibleNavGroups and saves the
+ open/closed/pinned state for each section and item in local store.
+
+
+ This is just a pattern and should be treated as such. Consuming
+ applications will need to create the navigation groups according to
+ their context and save the states as is appropriate to their data
+ store.
+
+
EuiCollapsibleNavToggle
+
+ This example also introduces the{' '}
+ EuiCollapsibleNavToggle component, which is used to
+ simply wrap around your external nav trigger to show/hide in certain
+ docked and mobile states.
+
+ >
+ ),
+ demo:
,
+ },
],
};
diff --git a/src-docs/src/views/collapsible_nav/collapsible_nav_list.tsx b/src-docs/src/views/collapsible_nav/collapsible_nav_list.tsx
new file mode 100644
index 00000000000..dda87842154
--- /dev/null
+++ b/src-docs/src/views/collapsible_nav/collapsible_nav_list.tsx
@@ -0,0 +1,127 @@
+import React from 'react';
+
+import { EuiCollapsibleNavGroup } from '../../../../src/components/collapsible_nav';
+import { EuiText } from '../../../../src/components/text';
+import {
+ EuiListGroup,
+ EuiListGroupProps,
+ EuiPinnableListGroup,
+ EuiPinnableListGroupItemProps,
+} from '../../../../src/components/list_group';
+import { EuiSpacer } from '../../../../src/components/spacer';
+import { EuiButton, EuiButtonIcon } from '../../../../src/components/button';
+import { EuiLink } from '../../../../src/components/link';
+
+const deploymentsList: EuiListGroupProps['listItems'] = [
+ {
+ label: 'combining-binaries',
+ iconType: 'logoAzureMono',
+ size: 's',
+ },
+ {
+ label: 'stack-monitoring',
+ iconType: 'logoAWSMono',
+ size: 's',
+ },
+];
+
+export const TopNavLinks: EuiPinnableListGroupItemProps[] = [
+ {
+ label: 'Home',
+ iconType: 'home',
+ isActive: true,
+ },
+ { label: 'Dashboards', pinned: true },
+ { label: 'Dev tools', pinned: true },
+ { label: 'Maps', pinned: true },
+];
+
+export const KibanaNavLinks: EuiPinnableListGroupItemProps[] = [
+ { label: 'Discover' },
+ { label: 'Visualize' },
+ { label: 'Dashboards' },
+ { label: 'Canvas' },
+ { label: 'Maps' },
+ { label: 'Machine Learning' },
+ { label: 'Graph' },
+];
+
+export const DeploymentsGroup = (
+
+ Deployment
+ personal-databoard
+
+ }
+ iconType="logoGCPMono"
+ iconSize="xl"
+ isCollapsible={true}
+ initialIsOpen={false}
+ background="dark">
+
+
+
+
+ Manage deployments
+
+
+
+);
+
+export const SecurityGroup = (
+
+ }>
+
+
+ Threat prevention, detection, and response with SIEM and endpoint
+ security.
+
+ Learn more
+
+
+
+);
+
+export default () => (
+ <>
+ {DeploymentsGroup}
+
+ {}}
+ maxWidth="none"
+ color="subdued"
+ gutterSize="none"
+ size="s"
+ />
+
+
+ {}}
+ maxWidth="none"
+ color="subdued"
+ gutterSize="none"
+ size="s"
+ />
+
+ {SecurityGroup}
+ >
+);
diff --git a/src/components/accordion/__snapshots__/accordion.test.tsx.snap b/src/components/accordion/__snapshots__/accordion.test.tsx.snap
index 4f49249582f..d34f5210c31 100644
--- a/src/components/accordion/__snapshots__/accordion.test.tsx.snap
+++ b/src/components/accordion/__snapshots__/accordion.test.tsx.snap
@@ -35,7 +35,9 @@ exports[`EuiAccordion behavior closes when clicked twice 1`] = `
/>
-
+