diff --git a/src-docs/src/components/guide_components.scss b/src-docs/src/components/guide_components.scss
index 3950197f7de..249c88f7ff0 100644
--- a/src-docs/src/components/guide_components.scss
+++ b/src-docs/src/components/guide_components.scss
@@ -5,6 +5,10 @@ $guideZLevelHighest: $euiZLevel9 + 1000;
.guideBody {
background: linear-gradient(90deg, $euiPageBackgroundColor 50%, $euiColorEmptyShade 50%);
+
+ &--overflowHidden {
+ overflow: hidden;
+ }
}
.guidePage {
diff --git a/src-docs/src/services/full_screen/full_screen.tsx b/src-docs/src/services/full_screen/full_screen.tsx
index b28db7f134c..716e0e93c1a 100644
--- a/src-docs/src/services/full_screen/full_screen.tsx
+++ b/src-docs/src/services/full_screen/full_screen.tsx
@@ -4,6 +4,7 @@ import React, {
FunctionComponent,
ReactElement,
ReactNode,
+ useEffect,
} from 'react';
import { EuiFocusTrap } from '../../../../src/components/focus_trap';
@@ -20,6 +21,16 @@ export const GuideFullScreen: FunctionComponent<{
}) => {
const [fullScreen, setFullScreen] = useState(isFullScreen);
+ // Watch for fullScreen status and appropriately add/remove body classes for hiding scroll
+ useEffect(() => {
+ if (fullScreen) {
+ document.body.classList.add('guideBody--overflowHidden');
+ }
+ return () => {
+ document.body.classList.remove('guideBody--overflowHidden');
+ };
+ }, [fullScreen]);
+
return (
setFullScreen(true)} iconType="fullScreen">
diff --git a/src-docs/src/views/collapsible_nav/collapsible_nav.tsx b/src-docs/src/views/collapsible_nav/collapsible_nav.tsx
index 10ad5cec714..1846d214457 100644
--- a/src-docs/src/views/collapsible_nav/collapsible_nav.tsx
+++ b/src-docs/src/views/collapsible_nav/collapsible_nav.tsx
@@ -4,6 +4,8 @@ import { EuiCollapsibleNav } from '../../../../src/components/collapsible_nav';
import { EuiButton, EuiButtonToggle } from '../../../../src/components/button';
import { EuiTitle } from '../../../../src/components/title';
import { EuiSpacer } from '../../../../src/components/spacer';
+import { EuiText } from '../../../../src/components/text';
+import { EuiCode } from '../../../../src/components/code';
export default () => {
const [navIsOpen, setNavIsOpen] = useState(false);
@@ -11,34 +13,37 @@ export default () => {
return (
<>
- setNavIsOpen(!navIsOpen)}
- aria-label="Toggle main navigation"
- aria-controls="guideCollapsibleNavExampleNav"
- aria-expanded={navIsOpen}
- aria-pressed={navIsOpen}>
- Toggle nav
-
- {navIsOpen && (
- setNavIsOpen(false)}>
-
-
- I am some nav
-
-
- {
- setNavIsDocked(!navIsDocked);
- }}
- />
-
-
+ setNavIsOpen(!navIsOpen)}>
+ Toggle nav
+
+ }
+ isDocked={navIsDocked}
+ onClose={() => setNavIsOpen(false)}>
+
+
+ I am some nav
+
+
+ {
+ setNavIsDocked(!navIsDocked);
+ }}
+ />
+
+
+
+ {navIsDocked && (
+
+
+ The button gets hidden by default when nav is docked unless you set{' '}
+ hideButtonIfDocked = false .
+
+
)}
>
);
diff --git a/src-docs/src/views/collapsible_nav/collapsible_nav_all.tsx b/src-docs/src/views/collapsible_nav/collapsible_nav_all.tsx
index 1f378e0be34..4f663f4830f 100644
--- a/src-docs/src/views/collapsible_nav/collapsible_nav_all.tsx
+++ b/src-docs/src/views/collapsible_nav/collapsible_nav_all.tsx
@@ -3,7 +3,6 @@ import _ from 'lodash';
import {
EuiCollapsibleNav,
- EuiCollapsibleNavToggle,
EuiCollapsibleNavGroup,
} from '../../../../src/components/collapsible_nav';
import {
@@ -30,8 +29,15 @@ import {
} from './collapsible_nav_list';
import { EuiShowFor } from '../../../../src/components/responsive';
-const TopLinks = [
- { label: 'Home', iconType: 'home', isActive: true, 'aria-current': true },
+const TopLinks: EuiPinnableListGroupItemProps[] = [
+ {
+ label: 'Home',
+ iconType: 'home',
+ isActive: true,
+ 'aria-current': true,
+ href: '#/navigation/collapsible-nav',
+ pinnable: false,
+ },
];
const KibanaLinks: EuiPinnableListGroupItemProps[] = KibanaNavLinks.map(
link => {
@@ -132,17 +138,115 @@ export default () => {
return `Unpin ${listItem.label}`;
}
+ const collapsibleNav = (
+ setNavIsOpen(!navIsOpen)}>
+
+
+ }
+ onClose={() => 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'}
+ />
+
+
+
+
+ );
+
const leftSectionItems = [
-
- setNavIsOpen(!navIsOpen)}>
-
-
- ,
+ collapsibleNav,
Elastic ,
];
@@ -169,109 +273,6 @@ export default () => {
]}
/>
- {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 e94d31b86c0..b8fe9777d8b 100644
--- a/src-docs/src/views/collapsible_nav/collapsible_nav_example.js
+++ b/src-docs/src/views/collapsible_nav/collapsible_nav_example.js
@@ -40,7 +40,7 @@ export const CollapsibleNavExample = {
EuiNavDrawer
{' '}
- which will be deprecated in the coming months.
+ which will be deprecated soon.
@@ -77,13 +77,12 @@ export const CollapsibleNavExample = {
),
props: { EuiCollapsibleNav },
demo: ,
- snippet: ` setNavIsOpen(!navIsOpen)}>Toggle nav
-{navIsOpen && (
- setNavIsOpen(false)}
- />
-)}`,
+ snippet: ` setNavIsOpen(!navIsOpen)}>Toggle nav}
+ isOpen={navIsOpen}
+ isDocked={navIsDocked}
+ onClose={() => setNavIsOpen(false)}
+/>`,
},
{
title: 'Collapsible nav group',
@@ -163,6 +162,7 @@ export const CollapsibleNavExample = {
isCollapsible={true}
initialIsOpen={true}>
- 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
index dda87842154..c64b3661cf3 100644
--- a/src-docs/src/views/collapsible_nav/collapsible_nav_list.tsx
+++ b/src-docs/src/views/collapsible_nav/collapsible_nav_list.tsx
@@ -30,6 +30,7 @@ export const TopNavLinks: EuiPinnableListGroupItemProps[] = [
label: 'Home',
iconType: 'home',
isActive: true,
+ pinnable: false,
},
{ label: 'Dashboards', pinned: true },
{ label: 'Dev tools', pinned: true },
@@ -103,7 +104,7 @@ export default () => (
listItems={TopNavLinks}
onPinClick={() => {}}
maxWidth="none"
- color="subdued"
+ color="text"
gutterSize="none"
size="s"
/>
diff --git a/src-docs/src/views/list_group/pinnable_list_group.tsx b/src-docs/src/views/list_group/pinnable_list_group.tsx
index 8f0ba4f7564..4716de39ef8 100644
--- a/src-docs/src/views/list_group/pinnable_list_group.tsx
+++ b/src-docs/src/views/list_group/pinnable_list_group.tsx
@@ -34,6 +34,10 @@ const someListItems: EuiPinnableListGroupItemProps[] = [
'aria-label': 'bell',
},
},
+ {
+ label: 'Item with pinnability turned off',
+ pinnable: false,
+ },
];
export default () => (
diff --git a/src/components/collapsible_nav/__snapshots__/collapsible_nav.test.tsx.snap b/src/components/collapsible_nav/__snapshots__/collapsible_nav.test.tsx.snap
index 81f4736c38b..9c6136cdc25 100644
--- a/src/components/collapsible_nav/__snapshots__/collapsible_nav.test.tsx.snap
+++ b/src/components/collapsible_nav/__snapshots__/collapsible_nav.test.tsx.snap
@@ -1,6 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`EuiCollapsibleNav can be docked 1`] = `
+exports[`EuiCollapsibleNav is rendered 1`] = `null`;
+
+exports[`EuiCollapsibleNav props button 1`] = `
+
+`;
+
+exports[`EuiCollapsibleNav props hideButtonIfDocked 1`] = `
+
+`;
+
+exports[`EuiCollapsibleNav props isDocked 1`] = `
`;
-exports[`EuiCollapsibleNav is rendered 1`] = `
+exports[`EuiCollapsibleNav props isOpen 1`] = `
Array [
,
@@ -66,10 +86,8 @@ Array [
data-focus-lock-disabled="false"
>
,
]
`;
+
+exports[`EuiCollapsibleNav props onClose 1`] = `null`;
diff --git a/src/components/collapsible_nav/__snapshots__/collapsible_nav_toggle.test.tsx.snap b/src/components/collapsible_nav/__snapshots__/collapsible_nav_toggle.test.tsx.snap
deleted file mode 100644
index 3e3f52c81f3..00000000000
--- a/src/components/collapsible_nav/__snapshots__/collapsible_nav_toggle.test.tsx.snap
+++ /dev/null
@@ -1,13 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`EuiCollapsibleNavToggle is rendered 1`] = `
-
-`;
-
-exports[`EuiCollapsibleNavToggle is rendered when navIsDocked is true 1`] = `
-
-`;
diff --git a/src/components/collapsible_nav/_collapsible_nav.scss b/src/components/collapsible_nav/_collapsible_nav.scss
index 042ec41f4e1..f15d58a6b49 100644
--- a/src/components/collapsible_nav/_collapsible_nav.scss
+++ b/src/components/collapsible_nav/_collapsible_nav.scss
@@ -31,7 +31,7 @@
}
}
- .euiCollapsibleNavToggle--navIsDocked {
+ .euiCollapsibleNav__toggle--navIsDocked {
display: none;
}
diff --git a/src/components/collapsible_nav/collapsible_nav.test.tsx b/src/components/collapsible_nav/collapsible_nav.test.tsx
index 38dd806e1fe..e2cd94f2348 100644
--- a/src/components/collapsible_nav/collapsible_nav.test.tsx
+++ b/src/components/collapsible_nav/collapsible_nav.test.tsx
@@ -10,18 +10,50 @@ jest.mock('../overlay_mask', () => ({
describe('EuiCollapsibleNav', () => {
test('is rendered', () => {
- const component = render(
- {}} {...requiredProps} />
- );
+ const component = render( );
expect(component).toMatchSnapshot();
});
- test('can be docked', () => {
- const component = render(
- {}} />
- );
+ describe('props', () => {
+ test('onClose', () => {
+ const component = render(
+ {}} />
+ );
- expect(component).toMatchSnapshot();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('isDocked', () => {
+ const component = render( );
+
+ expect(component).toMatchSnapshot();
+ });
+
+ test('isOpen', () => {
+ const component = render( );
+
+ expect(component).toMatchSnapshot();
+ });
+
+ test('button', () => {
+ const component = render(
+ } />
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+
+ test('hideButtonIfDocked', () => {
+ const component = render(
+ }
+ hideButtonIfDocked={false}
+ />
+ );
+
+ expect(component).toMatchSnapshot();
+ });
});
});
diff --git a/src/components/collapsible_nav/collapsible_nav.tsx b/src/components/collapsible_nav/collapsible_nav.tsx
index 5a92a0e985a..3d76d5fdf2c 100644
--- a/src/components/collapsible_nav/collapsible_nav.tsx
+++ b/src/components/collapsible_nav/collapsible_nav.tsx
@@ -3,16 +3,18 @@ import React, {
ReactNode,
useEffect,
useState,
- Fragment,
HTMLAttributes,
+ ReactElement,
+ cloneElement,
} from 'react';
import classNames from 'classnames';
import { throttle } from '../color_picker/utils';
-import { EuiWindowEvent, keyCodes } from '../../services';
+import { EuiWindowEvent, keyCodes, htmlIdGenerator } from '../../services';
import { EuiFocusTrap } from '../focus_trap';
import { EuiOverlayMask } from '../overlay_mask';
import { CommonProps } from '../common';
import { EuiButtonEmpty } from '../button';
+import { EuiI18n } from '../i18n';
export type EuiCollapsibleNavProps = CommonProps &
HTMLAttributes & {
@@ -20,21 +22,38 @@ export type EuiCollapsibleNavProps = CommonProps &
/**
* Keep navigation flyout visible and push `` content via padding
*/
- docked?: boolean;
- onClose: () => void;
+ isDocked?: boolean;
+ /**
+ * Shows the navigation flyout
+ */
+ isOpen?: boolean;
+ /**
+ * Button for controlling visible state of the nav
+ */
+ button?: ReactElement;
+ /**
+ * Removes display of toggle button when in docked state
+ */
+ hideButtonIfDocked?: boolean;
+ onClose?: () => void;
};
export const EuiCollapsibleNav: FunctionComponent = ({
children,
className,
- docked = false,
+ isDocked = false,
+ isOpen = false,
onClose,
+ button,
+ hideButtonIfDocked = true,
+ id,
...rest
}) => {
+ const [flyoutID] = useState(id || htmlIdGenerator()('euiCollapsibleNav'));
const [windowIsLargeEnoughToDock, setWindowIsLargeEnoughToDock] = useState(
window.innerWidth >= 992
);
- const isDocked = docked && windowIsLargeEnoughToDock;
+ const navIsDocked = isDocked && windowIsLargeEnoughToDock;
const functionToCallOnWindowResize = throttle(() => {
if (window.innerWidth < 992) {
@@ -47,7 +66,7 @@ export const EuiCollapsibleNav: FunctionComponent = ({
// Watch for docked status and appropriately add/remove body classes and resize handlers
useEffect(() => {
- if (docked) {
+ if (isDocked) {
document.body.classList.add('euiBody--collapsibleNavIsDocked');
window.addEventListener('resize', functionToCallOnWindowResize);
}
@@ -55,7 +74,7 @@ export const EuiCollapsibleNav: FunctionComponent = ({
document.body.classList.remove('euiBody--collapsibleNavIsDocked');
window.removeEventListener('resize', functionToCallOnWindowResize);
};
- }, [docked, functionToCallOnWindowResize]);
+ }, [isDocked, functionToCallOnWindowResize]);
const onKeyDown = (event: KeyboardEvent) => {
if (event.keyCode === keyCodes.ESCAPE) {
@@ -65,29 +84,44 @@ export const EuiCollapsibleNav: FunctionComponent = ({
};
const collapse = () => {
- if (!isDocked) {
- onClose();
+ if (!navIsDocked) {
+ onClose && onClose();
}
};
const classes = classNames(
'euiCollapsibleNav',
- { 'euiCollapsibleNav--isDocked': isDocked },
+ { 'euiCollapsibleNav--isDocked': navIsDocked },
className
);
let optionalOverlay;
- if (!isDocked) {
+ if (!navIsDocked) {
optionalOverlay = ;
}
- return (
-
+ // Show a trigger button if one was passed but
+ // not if hideButtonIfDocked and navIsDocked
+ const trigger =
+ button &&
+ !(hideButtonIfDocked && navIsDocked) &&
+ cloneElement(button as ReactElement, {
+ 'aria-controls': flyoutID,
+ 'aria-expanded': isOpen,
+ 'aria-pressed': isOpen,
+ className: classNames(
+ button.props.className,
+ 'euiCollapsibleNav__toggle'
+ ),
+ });
+
+ const flyout = (
+ <>
{optionalOverlay}
- {/* Trap focus only when isDocked={false} */}
-
-
+ {/* Trap focus only when docked={false} */}
+
+
{children}
= ({
size="xs"
iconType="cross"
className="euiCollapsibleNav__closeButton">
- close
+
-
+ >
+ );
+
+ return (
+ <>
+ {trigger}
+ {(isOpen || navIsDocked) && flyout}
+ >
);
};
diff --git a/src/components/collapsible_nav/collapsible_nav_toggle.test.tsx b/src/components/collapsible_nav/collapsible_nav_toggle.test.tsx
deleted file mode 100644
index c15efc39fcc..00000000000
--- a/src/components/collapsible_nav/collapsible_nav_toggle.test.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-import { render } from 'enzyme';
-import { EuiCollapsibleNavToggle } from './collapsible_nav_toggle';
-
-describe('EuiCollapsibleNavToggle', () => {
- test('is rendered', () => {
- const component = render(
-
-
-
- );
-
- expect(component).toMatchSnapshot();
- });
-
- test('is rendered when navIsDocked is true', () => {
- const component = render(
-
-
-
- );
-
- expect(component).toMatchSnapshot();
- });
-});
diff --git a/src/components/collapsible_nav/collapsible_nav_toggle.tsx b/src/components/collapsible_nav/collapsible_nav_toggle.tsx
deleted file mode 100644
index fac4dd98686..00000000000
--- a/src/components/collapsible_nav/collapsible_nav_toggle.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { ReactElement, FunctionComponent, cloneElement } from 'react';
-import classNames from 'classnames';
-
-export interface EuiCollapsibleNavToggleProps {
- children: ReactElement;
- /**
- * The docked state must be passed in order to hide/show the toggle appropriately
- */
- navIsDocked: boolean;
-}
-
-export const EuiCollapsibleNavToggle: FunctionComponent<
- EuiCollapsibleNavToggleProps
-> = ({ children, navIsDocked }) => {
- const classes = classNames(
- 'euiCollapsibleNavToggle',
- {
- 'euiCollapsibleNavToggle--navIsDocked': navIsDocked,
- },
- children.props.className
- );
-
- const props = {
- ...children.props,
- className: classes,
- };
-
- return cloneElement(children, props);
-};
diff --git a/src/components/collapsible_nav/index.ts b/src/components/collapsible_nav/index.ts
index 3a6172213a0..846e72f558f 100644
--- a/src/components/collapsible_nav/index.ts
+++ b/src/components/collapsible_nav/index.ts
@@ -3,9 +3,4 @@ export {
EuiCollapsibleNavGroupProps,
} from './collapsible_nav_group';
-export {
- EuiCollapsibleNavToggle,
- EuiCollapsibleNavToggleProps,
-} from './collapsible_nav_toggle';
-
export { EuiCollapsibleNav, EuiCollapsibleNavProps } from './collapsible_nav';
diff --git a/src/components/header/_header.scss b/src/components/header/_header.scss
index 389fb60f949..e87910bd6c1 100644
--- a/src/components/header/_header.scss
+++ b/src/components/header/_header.scss
@@ -20,5 +20,5 @@
}
.euiBody--headerIsFixed {
- padding-top: $euiHeaderChildSize + $euiSizeS; // Extra padding to accound for the shadow
+ padding-top: $euiHeaderHeight + $euiSizeS; // Extra padding to accound for the shadow
}
diff --git a/src/components/index.js b/src/components/index.js
index 04e4b3b0b5f..9dcc3991767 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -37,11 +37,7 @@ export { EuiCode, EuiCodeBlock, EuiCodeBlockImpl } from './code';
export { EuiCodeEditor } from './code_editor';
-export {
- EuiCollapsibleNav,
- EuiCollapsibleNavGroup,
- EuiCollapsibleNavToggle,
-} from './collapsible_nav';
+export { EuiCollapsibleNav, EuiCollapsibleNavGroup } from './collapsible_nav';
export {
EuiColorPicker,
diff --git a/src/components/list_group/pinnable_list_group/__snapshots__/pinnable_list_group.test.tsx.snap b/src/components/list_group/pinnable_list_group/__snapshots__/pinnable_list_group.test.tsx.snap
index b9af555a921..75048f15230 100644
--- a/src/components/list_group/pinnable_list_group/__snapshots__/pinnable_list_group.test.tsx.snap
+++ b/src/components/list_group/pinnable_list_group/__snapshots__/pinnable_list_group.test.tsx.snap
@@ -142,6 +142,21 @@ exports[`EuiPinnableListGroup can have custom pin icon titles 1`] = `
/>
+
+
+
+ Not pinnable
+
+
+
`;
@@ -169,9 +184,9 @@ exports[`EuiPinnableListGroup is rendered 1`] = `