diff --git a/src/components/collapsible_nav_beta/__snapshots__/collapsible_nav_body_footer.test.tsx.snap b/src/components/collapsible_nav_beta/__snapshots__/collapsible_nav_body_footer.test.tsx.snap
new file mode 100644
index 00000000000..4ef06f455f0
--- /dev/null
+++ b/src/components/collapsible_nav_beta/__snapshots__/collapsible_nav_body_footer.test.tsx.snap
@@ -0,0 +1,26 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EuiCollapsibleNavBody renders 1`] = `
+
+`;
+
+exports[`EuiCollapsibleNavFooter renders 1`] = `
+
+`;
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_beta.styles.ts b/src/components/collapsible_nav_beta/collapsible_nav_beta.styles.ts
index 5e93c634fa5..c7ed86ed0ae 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_beta.styles.ts
+++ b/src/components/collapsible_nav_beta/collapsible_nav_beta.styles.ts
@@ -12,6 +12,8 @@ import { logicalCSS, euiYScroll } from '../../global_styling';
import { euiShadowFlat } from '../../themes';
import { euiHeaderVariables } from '../header/header.styles';
+import { euiCollapsibleNavBodyStyles } from './collapsible_nav_body_footer.styles';
+
export const euiCollapsibleNavBetaStyles = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;
@@ -26,22 +28,12 @@ export const euiCollapsibleNavBetaStyles = (euiThemeContext: UseEuiTheme) => {
/* Fixed header affordance */
${logicalCSS('top', fixedHeaderOffset)}
- /* Allow the nav to scroll, in case consumers don't use EuiFlyoutBody/EuiFyoutFooter */
+ /* Allow the nav to scroll, in case consumers don't use the body or footer components */
${euiYScroll(euiThemeContext, { height: 'inherit' })}
/* This extra padding is needed for EuiPopovers to have enough
space to render with the right anchorPosition */
${logicalCSS('padding-bottom', euiTheme.size.xs)}
-
- /* In case things get really dire responsively, ensure the footer doesn't overtake the body */
- .euiFlyoutBody {
- ${logicalCSS('min-height', '50%')}
- }
-
- .euiFlyoutFooter {
- background-color: ${euiTheme.colors.emptyShade};
- ${logicalCSS('border-top', euiTheme.border.thin)}
- }
`,
left: css`
${logicalCSS('border-right', euiTheme.border.thin)}
@@ -53,16 +45,7 @@ export const euiCollapsibleNavBetaStyles = (euiThemeContext: UseEuiTheme) => {
${euiShadowFlat(euiThemeContext)}
`,
isPushCollapsed: css`
- /* Hide the scrollbar for docked mode (while still keeping the nav scrollable)
- Otherwise if scrollbars are visible, button icon visibility suffers */
- &,
- .euiFlyoutBody__overflow {
- scrollbar-width: none; /* Firefox */
-
- &::-webkit-scrollbar {
- display: none; /* Chrome, Edge, & Safari */
- }
- }
+ ${euiCollapsibleNavBodyStyles._isPushCollapsed}
`,
isOverlayFullWidth: css`
/* Override EuiFlyout's max-width */
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.ts b/src/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.ts
new file mode 100644
index 00000000000..260697f2992
--- /dev/null
+++ b/src/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.ts
@@ -0,0 +1,44 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { css } from '@emotion/react';
+import { UseEuiTheme } from '../../services';
+import { logicalCSS } from '../../global_styling';
+
+export const euiCollapsibleNavBodyStyles = {
+ // In case things get really dire responsively, ensure the footer doesn't overtake the body
+ euiCollapsibleNav__body: css`
+ ${logicalCSS('min-height', '50%')}
+ `,
+ get isPushCollapsed() {
+ return css`
+ .euiFlyoutBody__overflow {
+ ${this._isPushCollapsed}
+ }
+ `;
+ },
+ // CSS is reused by main euiCollapsibleNav styles in case the body component isn't used
+ _isPushCollapsed: `
+ /* Hide the scrollbar for docked mode (while still keeping the nav scrollable)
+ Otherwise if scrollbars are visible, button icon visibility suffers. */
+ scrollbar-width: none; /* Firefox */
+
+ &::-webkit-scrollbar {
+ display: none; /* Chrome, Edge, & Safari */
+ }
+ `,
+};
+
+export const euiCollapsibleNavFooterStyles = ({ euiTheme }: UseEuiTheme) => {
+ return {
+ euiCollapsibleNav__footer: css`
+ background-color: ${euiTheme.colors.emptyShade};
+ ${logicalCSS('border-top', euiTheme.border.thin)}
+ `,
+ };
+};
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_body_footer.test.tsx b/src/components/collapsible_nav_beta/collapsible_nav_body_footer.test.tsx
new file mode 100644
index 00000000000..8493fa725fe
--- /dev/null
+++ b/src/components/collapsible_nav_beta/collapsible_nav_body_footer.test.tsx
@@ -0,0 +1,50 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { render } from '../../test/rtl';
+import { shouldRenderCustomStyles } from '../../test/internal';
+import { requiredProps } from '../../test';
+
+import { EuiCollapsibleNavContext } from './context';
+import {
+ EuiCollapsibleNavBody,
+ EuiCollapsibleNavFooter,
+} from './collapsible_nav_body_footer';
+
+describe('EuiCollapsibleNavBody', () => {
+ shouldRenderCustomStyles();
+
+ it('renders', () => {
+ const { container } = render();
+ expect(container.firstChild).toMatchSnapshot();
+ });
+
+ it('renders with docked styles', () => {
+ const { container } = render(
+
+
+
+ );
+
+ expect(container.innerHTML).toContain('isPushCollapsed');
+ });
+});
+
+describe('EuiCollapsibleNavFooter', () => {
+ shouldRenderCustomStyles();
+
+ it('renders', () => {
+ const { container } = render(
+
+ );
+ expect(container.firstChild).toMatchSnapshot();
+ });
+});
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_body_footer.tsx b/src/components/collapsible_nav_beta/collapsible_nav_body_footer.tsx
new file mode 100644
index 00000000000..7bd6ebb9a39
--- /dev/null
+++ b/src/components/collapsible_nav_beta/collapsible_nav_body_footer.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { useContext } from 'react';
+import classNames from 'classnames';
+
+import { useEuiTheme } from '../../services';
+import {
+ EuiFlyoutBody,
+ EuiFlyoutBodyProps,
+ EuiFlyoutFooter,
+ EuiFlyoutFooterProps,
+} from '../flyout';
+
+import { EuiCollapsibleNavContext } from './context';
+import {
+ euiCollapsibleNavBodyStyles as bodyStyles,
+ euiCollapsibleNavFooterStyles,
+} from './collapsible_nav_body_footer.styles';
+
+/**
+ * These components are incredibly light wrappers around `EuiFlyoutBody`
+ * and `EuiFlyoutFooter` with collapsible nav-specific styling/considerations.
+ *
+ * Note: They are not intended to be used standalone outside of EuiCollapsibleNav
+ */
+
+export const EuiCollapsibleNavBody: EuiFlyoutBodyProps = ({
+ className,
+ ...props
+}) => {
+ const classes = classNames('euiCollapsibleNav__body', className);
+
+ const { isCollapsed, isPush } = useContext(EuiCollapsibleNavContext);
+ const cssStyles = [
+ bodyStyles.euiCollapsibleNav__body,
+ isCollapsed && isPush && bodyStyles.isPushCollapsed,
+ ];
+
+ return (
+
+ );
+};
+
+export const EuiCollapsibleNavFooter: EuiFlyoutFooterProps = ({
+ className,
+ ...props
+}) => {
+ const classes = classNames('euiCollapsibleNav__footer', className);
+
+ const euiTheme = useEuiTheme();
+ const styles = euiCollapsibleNavFooterStyles(euiTheme);
+ const cssStyles = [styles.euiCollapsibleNav__footer];
+
+ return ;
+};