Skip to content

Commit

Permalink
[EuiFlyout] Performance cleanup (#7462)
Browse files Browse the repository at this point in the history
Co-authored-by: Cee Chen <constance.chen@elastic.co>
  • Loading branch information
davismcphee and cee-chen authored Mar 14, 2024
1 parent 6c86d6e commit f4e7570
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 20 deletions.
3 changes: 3 additions & 0 deletions changelogs/upcoming/7462.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**Bug fixes**

- Fixed `EuiFlyout` to not repeatedly remove/add a body class on resize
2 changes: 1 addition & 1 deletion src/components/flyout/__snapshots__/flyout.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,7 @@ Array [

exports[`EuiFlyout renders extra screen reader instructions when fixed EuiHeaders headers exist on the page 1`] = `
<body
class="euiBody--headerIsFixed euiBody--hasFlyout"
class="euiBody--hasFlyout euiBody--headerIsFixed"
>
<div>
<div
Expand Down
29 changes: 29 additions & 0 deletions src/components/flyout/flyout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,34 @@ describe('EuiFlyout', () => {
).toMatchSnapshot();
});
});

describe('body class', () => {
it('adds `.euiBody--hasFlyout` class on mount', () => {
render(<EuiFlyout onClose={() => {}} />);
expect(document.body).toHaveClass('euiBody--hasFlyout');
});

it('removes `.euiBody--hasFlyout` class on unmount', () => {
const { unmount } = render(<EuiFlyout onClose={() => {}} />);
unmount();
expect(document.body).not.toHaveClass('euiBody--hasFlyout');
});

// Regression testing
it('should not remove and re-add `.euiBody--hasFlyout` class on resize', async () => {
const add = jest.spyOn(document.body.classList, 'add');
const remove = jest.spyOn(document.body.classList, 'remove');
const { rerender } = render(
<EuiFlyout onClose={() => {}} size={500} />
);

expect(add).toHaveBeenCalledTimes(1);
expect(add).toHaveBeenLastCalledWith('euiBody--hasFlyout');

rerender(<EuiFlyout onClose={() => {}} size={600} />);
expect(add).toHaveBeenCalledTimes(1);
expect(remove).not.toHaveBeenCalled();
});
});
});
});
35 changes: 16 additions & 19 deletions src/components/flyout/flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,36 +214,33 @@ export const EuiFlyout = forwardRef(
null
);
const setRef = useCombinedRefs([setResizeRef, ref]);
// TODO: Allow this hook to be conditional
const dimensions = useResizeObserver(resizeRef);
const { width } = useResizeObserver(isPushed ? resizeRef : null, 'width');

useEffect(() => {
// This class doesn't actually do anything by EUI, but is nice to add for consumers (JIC)
document.body.classList.add('euiBody--hasFlyout');

/**
* Accomodate for the `isPushed` state by adding padding to the body equal to the width of the element
*/
if (isPushed) {
if (side === 'right') {
document.body.style.paddingInlineEnd = `${dimensions.width}px`;
} else if (side === 'left') {
document.body.style.paddingInlineStart = `${dimensions.width}px`;
}
const paddingSide =
side === 'left' ? 'paddingInlineStart' : 'paddingInlineEnd';

document.body.style[paddingSide] = `${width}px`;
return () => {
document.body.style[paddingSide] = '';
};
}
}, [isPushed, side, width]);

/**
* This class doesn't actually do anything by EUI, but is nice to add for consumers (JIC)
*/
useEffect(() => {
document.body.classList.add('euiBody--hasFlyout');
return () => {
// Remove the hasFlyout class when the flyout is unmounted
document.body.classList.remove('euiBody--hasFlyout');

if (isPushed) {
if (side === 'right') {
document.body.style.paddingInlineEnd = '';
} else if (side === 'left') {
document.body.style.paddingInlineStart = '';
}
}
};
}, [side, dimensions, isPushed]);
}, []);

/**
* ESC key closes flyout (always?)
Expand Down

0 comments on commit f4e7570

Please sign in to comment.