Skip to content

Commit

Permalink
[EuiCollapsibleNavBeta] Final collapsed/docked icon & popover behavior (
Browse files Browse the repository at this point in the history
  • Loading branch information
cee-chen authored Aug 7, 2023
1 parent 5ab7824 commit 8dcf472
Show file tree
Hide file tree
Showing 30 changed files with 1,286 additions and 275 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ exports[`EuiCollapsibleNavBeta renders 1`] = `
aria-expanded="true"
aria-label="Toggle navigation closed"
aria-pressed="true"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text-euiCollapsibleNavButton"
data-test-subj="euiCollapsibleNavButton"
type="button"
>
Expand All @@ -36,7 +36,7 @@ exports[`EuiCollapsibleNavBeta renders 1`] = `
>
<nav
aria-label="aria-label"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta testClass1 testClass2 emotion-euiFlyout-none-noMaxWidth-push-left-left-euiCollapsibleNavBeta-left-euiTestCss"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta testClass1 testClass2 emotion-euiFlyout-none-noMaxWidth-push-left-left-euiCollapsibleNavBeta-left-isPush-euiTestCss"
data-autofocus="true"
data-test-subj="nav"
id="generated-id_euiCollapsibleNav"
Expand Down Expand Up @@ -70,7 +70,7 @@ exports[`EuiCollapsibleNavBeta renders initialIsCollapsed 1`] = `
aria-expanded="false"
aria-label="Toggle navigation open"
aria-pressed="false"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text-euiCollapsibleNavButton"
data-test-subj="euiCollapsibleNavButton"
type="button"
>
Expand All @@ -91,7 +91,7 @@ exports[`EuiCollapsibleNavBeta renders initialIsCollapsed 1`] = `
data-focus-lock-disabled="disabled"
>
<nav
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta emotion-euiFlyout-none-noMaxWidth-push-left-left-euiCollapsibleNavBeta-left"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta emotion-euiFlyout-none-noMaxWidth-push-left-left-euiCollapsibleNavBeta-left-isPush-isPushCollapsed"
data-autofocus="true"
data-test-subj="nav"
id="generated-id_euiCollapsibleNav"
Expand Down Expand Up @@ -125,7 +125,7 @@ exports[`EuiCollapsibleNavBeta responsive behavior collapses from a push flyout
aria-expanded="false"
aria-label="Toggle navigation open"
aria-pressed="false"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text-euiCollapsibleNavButton"
data-test-subj="euiCollapsibleNavButton"
type="button"
>
Expand Down Expand Up @@ -155,7 +155,7 @@ exports[`EuiCollapsibleNavBeta responsive behavior makes the overlay flyout full
aria-expanded="true"
aria-label="Toggle navigation closed"
aria-pressed="true"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text"
class="euiButtonIcon euiCollapsibleNavButton emotion-euiButtonIcon-s-empty-text-euiCollapsibleNavButton"
data-test-subj="euiCollapsibleNavButton"
type="button"
>
Expand Down Expand Up @@ -183,7 +183,7 @@ exports[`EuiCollapsibleNavBeta responsive behavior makes the overlay flyout full
>
<nav
aria-describedby="generated-id"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta emotion-euiFlyout-none-noMaxWidth-overlay-left-euiCollapsibleNavBeta-left-isSmallestScreen"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta emotion-euiFlyout-none-noMaxWidth-overlay-left-euiCollapsibleNavBeta-left-isOverlayFullWidth"
data-autofocus="true"
id="generated-id_euiCollapsibleNav"
role="dialog"
Expand Down
32 changes: 30 additions & 2 deletions src/components/collapsible_nav_beta/collapsible_nav_beta.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,26 @@

import { css } from '@emotion/react';
import { UseEuiTheme } from '../../services';
import { logicalCSS } from '../../global_styling';
import { logicalCSS, euiYScroll } from '../../global_styling';
import { euiShadowFlat } from '../../themes';

export const euiCollapsibleNavBetaStyles = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;

return {
euiCollapsibleNavBeta: css`
/* This extra padding is needed for EuiPopovers to have enough
space to render with the right anchorPosition */
${logicalCSS('padding-bottom', euiTheme.size.xs)}
/* Allow the nav to scroll, in case consumers don't use EuiFlyoutBody/EuiFyoutFooter */
${euiYScroll(euiThemeContext)}
/* 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)}
Expand All @@ -26,7 +39,22 @@ export const euiCollapsibleNavBetaStyles = (euiThemeContext: UseEuiTheme) => {
right: css`
${logicalCSS('border-left', euiTheme.border.thin)}
`,
isSmallestScreen: css`
isPush: css`
${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 */
}
}
`,
isOverlayFullWidth: css`
/* Override EuiFlyout's max-width */
&.euiFlyout {
${logicalCSS('max-width', '100% !important')}
Expand Down
53 changes: 27 additions & 26 deletions src/components/collapsible_nav_beta/collapsible_nav_beta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { CommonProps } from '../common';
import { EuiFlyout, EuiFlyoutProps } from '../flyout';
import { euiHeaderVariables } from '../header/header.styles';

import { EuiCollapsibleNavContext } from './context';
import { EuiCollapsibleNavButton } from './collapsible_nav_button';
import { euiCollapsibleNavBetaStyles } from './collapsible_nav_beta.styles';

Expand Down Expand Up @@ -87,16 +88,21 @@ export const EuiCollapsibleNavBeta: FunctionComponent<
const onClose = useCallback(() => setIsCollapsed(true), []);

/**
* Mobile behavior
* Responsive behavior
* By default on large enough screens, the nav is always a push flyout,
* but on smaller/mobile screens, the nav overlays the page instead
*/
const [isSmallScreen, setIsSmallScreen] = useState(false);
const [isSmallestScreen, setIsSmallestScreen] = useState(false);
const [isOverlay, setIsOverlay] = useState(false);
const [isOverlayFullWidth, setIsOverlayFullWidth] = useState(false);

// Add a window resize listener that determines breakpoint behavior
const flyoutType = isOverlay ? 'overlay' : 'push';
const isPush = !isOverlay;

// Set up a window resize listener that determines breakpoint behavior
useEffect(() => {
const getBreakpoints = () => {
setIsSmallScreen(window.innerWidth < _width * 3);
setIsSmallestScreen(window.innerWidth < _width * 1.5);
setIsOverlay(window.innerWidth < _width * 3);
setIsOverlayFullWidth(window.innerWidth < _width * 1.5);
};
getBreakpoints();

Expand All @@ -105,22 +111,17 @@ export const EuiCollapsibleNavBeta: FunctionComponent<
return () => window.removeEventListener('resize', onWindowResize);
}, [_width]);

// If the screen was previously uncollapsed and shrinks down to
// a smaller mobile view, default that view to a collapsed state
// If the nav was previously uncollapsed and shrinks down to the
// overlay flyout, default to its hidden/collapsed state
useEffect(() => {
if (isSmallScreen) setIsCollapsed(true);
}, [isSmallScreen]);

// On small screens, the flyout becomes an overlay rather than a push
const flyoutType = isSmallScreen ? 'overlay' : 'push';
const isMobileCollapsed = isSmallScreen && isCollapsed;
if (isOverlay) setIsCollapsed(true);
}, [isOverlay]);

const width = useMemo(() => {
if (isSmallestScreen) return '100%';
if (isSmallScreen) return _width;
if (isCollapsed) return headerHeight;
if (isOverlayFullWidth) return '100%';
if (isPush && isCollapsed) return headerHeight;
return _width;
}, [_width, isSmallScreen, isSmallestScreen, isCollapsed, headerHeight]);
}, [_width, isOverlayFullWidth, isPush, isCollapsed, headerHeight]);

/**
* Header affordance
Expand Down Expand Up @@ -174,7 +175,9 @@ export const EuiCollapsibleNavBeta: FunctionComponent<
const cssStyles = [
styles.euiCollapsibleNavBeta,
styles[side],
isSmallestScreen && styles.isSmallestScreen,
isPush && styles.isPush,
isPush && isCollapsed && styles.isPushCollapsed,
isOverlayFullWidth && styles.isOverlayFullWidth,
];

// Wait for any fixed headers to be queried before rendering (prevents position jumping)
Expand All @@ -199,18 +202,16 @@ export const EuiCollapsibleNavBeta: FunctionComponent<
</EuiFlyout>
);

const hideFlyout = isOverlay && isCollapsed;

return (
// TODO: Context for sharing state to all children
<>
<EuiCollapsibleNavContext.Provider value={{ isPush, isCollapsed, side }}>
<EuiCollapsibleNavButton
ref={buttonRef}
onClick={toggleCollapsed}
isCollapsed={isCollapsed}
isSmallScreen={isSmallScreen}
side={side}
aria-controls={flyoutID}
/>
{!isMobileCollapsed && flyout}
</>
{!hideFlyout && flyout}
</EuiCollapsibleNavContext.Provider>
);
};
Loading

0 comments on commit 8dcf472

Please sign in to comment.