Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiFlyout] Allow push flyouts to have slide in animations #7239

Merged
merged 6 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ exports[`EuiCollapsibleNav props isDocked 1`] = `
data-focus-lock-disabled="disabled"
>
<nav
class="euiFlyout euiCollapsibleNav emotion-euiFlyout-none-noMaxWidth-push-left-left-euiCollapsibleNav-push"
class="euiFlyout euiCollapsibleNav emotion-euiFlyout-none-noMaxWidth-push-left-noAnimation-left-euiCollapsibleNav-push"
id="id"
style="inline-size: 320px;"
/>
Expand Down Expand Up @@ -353,7 +353,7 @@ exports[`EuiCollapsibleNav props showButtonIfDocked 1`] = `
data-focus-lock-disabled="disabled"
>
<nav
class="euiFlyout euiCollapsibleNav emotion-euiFlyout-none-noMaxWidth-push-left-left-euiCollapsibleNav-push"
class="euiFlyout euiCollapsibleNav emotion-euiFlyout-none-noMaxWidth-push-left-noAnimation-left-euiCollapsibleNav-push"
id="id"
style="inline-size: 320px;"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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-isPush-euiTestCss"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta testClass1 testClass2 emotion-euiFlyout-none-noMaxWidth-push-left-noAnimation-left-euiCollapsibleNavBeta-left-isPush-euiTestCss"
data-test-subj="nav"
id="generated-id_euiCollapsibleNav"
style="inline-size: 248px;"
Expand Down Expand Up @@ -89,7 +89,7 @@ exports[`EuiCollapsibleNavBeta renders initialIsCollapsed 1`] = `
>
<nav
aria-label="Site menu"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta emotion-euiFlyout-none-noMaxWidth-push-left-left-euiCollapsibleNavBeta-left-isPush-isPushCollapsed"
class="euiFlyout euiCollapsibleNav euiCollapsibleNavBeta emotion-euiFlyout-none-noMaxWidth-push-left-noAnimation-left-euiCollapsibleNavBeta-left-isPush-isPushCollapsed"
data-test-subj="nav"
id="generated-id_euiCollapsibleNav"
style="inline-size: 48px;"
Expand Down
57 changes: 21 additions & 36 deletions src/components/flyout/__snapshots__/flyout.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,27 @@ Array [
]
`;

exports[`EuiFlyout props push flyouts renders 1`] = `
<div
class="euiFlyout emotion-euiFlyout-l-m-noMaxWidth-push-right-noAnimation-right"
data-test-subj="flyout"
>
<button
aria-label="Close this dialog"
class="euiButtonIcon euiFlyout__closeButton emotion-euiButtonIcon-xs-empty-text-euiFlyout__closeButton-inside"
data-test-subj="euiFlyoutCloseButton"
type="button"
>
<span
aria-hidden="true"
class="euiButtonIcon__icon"
color="inherit"
data-euiicon-type="cross"
/>
</button>
</div>
`;

exports[`EuiFlyout props sides left is rendered 1`] = `
Array [
<div>
Expand Down Expand Up @@ -1047,42 +1068,6 @@ Array [
]
`;

exports[`EuiFlyout props type=push is rendered 1`] = `
Array [
<div
data-focus-guard="true"
style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;"
tabindex="-1"
/>,
<div
data-focus-lock-disabled="disabled"
>
<div
class="euiFlyout emotion-euiFlyout-l-m-noMaxWidth-push-right-right"
>
<button
aria-label="Close this dialog"
class="euiButtonIcon euiFlyout__closeButton emotion-euiButtonIcon-xs-empty-text-euiFlyout__closeButton-inside"
data-test-subj="euiFlyoutCloseButton"
type="button"
>
<span
aria-hidden="true"
class="euiButtonIcon__icon"
color="inherit"
data-euiicon-type="cross"
/>
</button>
</div>
</div>,
<div
data-focus-guard="true"
style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;"
tabindex="-1"
/>,
]
`;

exports[`EuiFlyout renders extra screen reader instructions when fixed EuiHeaders headers exist on the page 1`] = `
<body
class="euiBody--headerIsFixed euiBody--hasFlyout"
Expand Down
102 changes: 102 additions & 0 deletions src/components/flyout/flyout.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* 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 type { Meta, StoryObj } from '@storybook/react';
import React, { useState } from 'react';
import { hideStorybookControls } from '../../../.storybook/utils';

import { EuiButton, EuiText } from '../index';

import { EuiFlyout, EuiFlyoutProps, EuiFlyoutBody } from './index';

const meta: Meta<EuiFlyoutProps> = {
title: 'EuiFlyout',
component: EuiFlyout,
args: {
// Component defaults
type: 'overlay',
side: 'right',
size: 'm',
paddingSize: 'l',
pushMinBreakpoint: 'l',
closeButtonPosition: 'inside',
hideCloseButton: false,
ownFocus: true,
},
};

export default meta;
type Story = StoryObj<EuiFlyoutProps>;

const StatefulFlyout = (props: Partial<EuiFlyoutProps>) => {
const [isOpen, setIsOpen] = useState(true);
return (
<>
<EuiButton size="s" onClick={() => setIsOpen(!isOpen)}>
Toggle flyout
</EuiButton>
{isOpen && <EuiFlyout {...props} onClose={() => setIsOpen(false)} />}
</>
);
};

export const Playground: Story = {
render: ({ ...args }) => <StatefulFlyout {...args} />,
};

export const PushFlyouts: Story = {
render: ({ ...args }) => {
const fillerText = (
<EuiText>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eu
condimentum ipsum, nec ornare metus. Sed egestas elit nec placerat
suscipit. Cras pulvinar nisi eget enim sodales fringilla. Aliquam
lobortis lorem at ornare aliquet. Mauris laoreet laoreet mollis.
Pellentesque aliquet tortor dui, non luctus turpis pulvinar vitae.
Nunc ultrices scelerisque erat eu rutrum. Nam at ligula enim. Ut nec
nisl faucibus, euismod neque ut, aliquam nisl. Donec eu ante ut arcu
rutrum blandit nec ac nisl. In elementum id enim vitae aliquam. In
sagittis, neque vitae ultricies interdum, sapien justo efficitur
ligula, sit amet fermentum nisl magna sit amet turpis. Nulla facilisi.
Proin nec viverra mi. Morbi dolor arcu, ornare non consequat et,
viverra dapibus tellus.
</p>
</EuiText>
);
return (
<>
<StatefulFlyout {...args}>
<EuiFlyoutBody>{fillerText}</EuiFlyoutBody>
</StatefulFlyout>
{fillerText}
</>
);
},
args: {
type: 'push',
pushAnimation: false,
pushMinBreakpoint: 'xs',
},
argTypes: hideStorybookControls([
'onClose',
'aria-label',
'as',
'closeButtonPosition',
'closeButtonProps',
'focusTrapProps',
'hideCloseButton',
'includeFixedHeadersInFocusTrap',
'maskProps',
'maxWidth',
'outsideClickCloses',
'ownFocus',
'paddingSize',
'style',
]),
};
18 changes: 10 additions & 8 deletions src/components/flyout/flyout.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,20 +158,22 @@ export const euiFlyoutStyles = (euiThemeContext: UseEuiTheme) => {
overlay: css`
${euiShadowXLarge(euiThemeContext)}
`,
push: css`
clip-path: none;
/* Don't animate on loading a docked nav */
animation-duration: 0s !important; /* stylelint-disable-line declaration-no-important */
/* Make sure the header shadows are above */
z-index: ${Number(euiTheme.levels.flyout) - 1};
`,
pushSide: {
push: {
push: css`
clip-path: none;
/* Make sure the header shadows are above */
z-index: ${Number(euiTheme.levels.flyout) - 1};
`,
right: css`
${logicalCSS('border-left', euiTheme.border.thick)}
`,
left: css`
${logicalCSS('border-right', euiTheme.border.thick)}
`,
noAnimation: css`
/* Don't animate on loading a docked nav */
animation-duration: 0s !important; /* stylelint-disable-line declaration-no-important */
`,
},

// Padding
Expand Down
33 changes: 26 additions & 7 deletions src/components/flyout/flyout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,34 @@ describe('EuiFlyout', () => {
});
});

describe('type=push', () => {
test('is rendered', () => {
const component = mount(
<EuiFlyout onClose={() => {}} type="push" pushMinBreakpoint="xs" />
describe('push flyouts', () => {
it('renders', () => {
const { getByTestSubject } = render(
<EuiFlyout
data-test-subj="flyout"
onClose={() => {}}
type="push"
pushMinBreakpoint="xs"
/>
);

expect(
takeMountedSnapshot(component, { hasArrayOutput: true })
).toMatchSnapshot();
expect(getByTestSubject('flyout')).toMatchSnapshot();
});

it('can render with animations', () => {
const { getByTestSubject } = render(
<EuiFlyout
data-test-subj="flyout"
onClose={() => {}}
type="push"
pushMinBreakpoint="xs"
pushAnimation={true}
/>
);

expect(getByTestSubject('flyout').className).not.toContain(
'noAnimation'
);
});
});

Expand Down
27 changes: 16 additions & 11 deletions src/components/flyout/flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ interface _EuiFlyoutProps {
* @default l
*/
pushMinBreakpoint?: EuiBreakpointSize;
/**
* Enables a slide in animation on push flyouts
* @default false
*/
pushAnimation?: boolean;
style?: CSSProperties;
/**
* Object of props passed to EuiFocusTrap.
Expand Down Expand Up @@ -181,6 +186,7 @@ export const EuiFlyout = forwardRef(
type = 'overlay',
outsideClickCloses,
pushMinBreakpoint = 'l',
pushAnimation = false,
focusTrapProps: _focusTrapProps = {},
includeFixedHeadersInFocusTrap = true,
'aria-describedby': _ariaDescribedBy,
Expand Down Expand Up @@ -216,28 +222,26 @@ export const EuiFlyout = forwardRef(
/**
* Accomodate for the `isPushed` state by adding padding to the body equal to the width of the element
*/
if (type === 'push') {
if (isPushed) {
if (side === 'right') {
document.body.style.paddingRight = `${dimensions.width}px`;
} else if (side === 'left') {
document.body.style.paddingLeft = `${dimensions.width}px`;
}
if (isPushed) {
if (side === 'right') {
document.body.style.paddingRight = `${dimensions.width}px`;
} else if (side === 'left') {
document.body.style.paddingLeft = `${dimensions.width}px`;
}
}

return () => {
document.body.classList.remove('euiBody--hasFlyout');

if (type === 'push') {
if (isPushed) {
if (side === 'right') {
document.body.style.paddingRight = '';
} else if (side === 'left') {
document.body.style.paddingLeft = '';
}
}
};
}, [type, side, dimensions, isPushed]);
}, [side, dimensions, isPushed]);

/**
* ESC key closes flyout (always?)
Expand Down Expand Up @@ -268,8 +272,9 @@ export const EuiFlyout = forwardRef(
styles.paddingSizes[paddingSize],
isEuiFlyoutSizeNamed(size) && styles[size],
maxWidth === false && styles.noMaxWidth,
styles[type],
type === 'push' && styles.pushSide[side],
isPushed ? styles.push.push : styles.overlay,
isPushed && styles.push[side],
isPushed && !pushAnimation && styles.push.noAnimation,
styles[side],
];

Expand Down
1 change: 1 addition & 0 deletions upcoming_changelogs/7239.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Added new `pushAnimation` prop to push `EuiFlyout`s, which enables a slide in animation
Loading