Skip to content

Commit

Permalink
[9.0] [Security Solution][Expandable flyout] fix flyout flickering wh…
Browse files Browse the repository at this point in the history
…en opening/closing left panel (#210225) (#210287)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Security Solution][Expandable flyout] fix flyout flickering when
opening/closing left panel
(#210225)](#210225)

<!--- Backport version: 9.6.4 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Philippe
Oberti","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-02-07T22:34:27Z","message":"[Security
Solution][Expandable flyout] fix flyout flickering when opening/closing
left panel (#210225)\n\n## Summary\r\n\r\nWe recently improved the
expandable flyout by adding support for a\r\n[fully resizable
flyout](https://github.com/elastic/kibana/pull/192906).\r\nThis work
introduce a minor inconvenience, where the right panel
gets\r\nre-rendered every time the user expands or collapses the
flyout.\r\n\r\nThis PR fixes this issue by better using the EUI
resizable container\r\n(see how to externally control a resizable
container\r\n[here](https://eui.elastic.co/#/layout/resizable-container#collapsible-panels-with-external-control)).\r\nThe
flyout is now always showing a resizable container (even in\r\ncollapsed
mode) but EUI manages internally hiding the left section and\r\nthe
resize button.\r\n\r\n#### Old
behavior\r\n\r\n\r\nhttps://github.com/user-attachments/assets/4d7589ec-0edf-4690-9ce4-7b969ae0bb44\r\n\r\n####
New
behavior\r\n\r\n\r\nhttps://github.com/user-attachments/assets/7cf720b8-5b31-4cc9-b213-21472ea880d6\r\n\r\nThe
rest of the flyout's behavior remains untouched:\r\n- identical default
widths\r\n- user selected widths are still applied\r\n- no changes to
the preview behavior\r\n\r\n### Checklist\r\n\r\n- [ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"7a9bf1399c39e9306bbfb23e73a4d72fe8aae967","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Threat
Hunting:Investigations","backport:version","v8.18.0","v9.1.0","v8.17.3","v8.16.5"],"title":"[Security
Solution][Expandable flyout] fix flyout flickering when opening/closing
left
panel","number":210225,"url":"https://github.com/elastic/kibana/pull/210225","mergeCommit":{"message":"[Security
Solution][Expandable flyout] fix flyout flickering when opening/closing
left panel (#210225)\n\n## Summary\r\n\r\nWe recently improved the
expandable flyout by adding support for a\r\n[fully resizable
flyout](https://github.com/elastic/kibana/pull/192906).\r\nThis work
introduce a minor inconvenience, where the right panel
gets\r\nre-rendered every time the user expands or collapses the
flyout.\r\n\r\nThis PR fixes this issue by better using the EUI
resizable container\r\n(see how to externally control a resizable
container\r\n[here](https://eui.elastic.co/#/layout/resizable-container#collapsible-panels-with-external-control)).\r\nThe
flyout is now always showing a resizable container (even in\r\ncollapsed
mode) but EUI manages internally hiding the left section and\r\nthe
resize button.\r\n\r\n#### Old
behavior\r\n\r\n\r\nhttps://github.com/user-attachments/assets/4d7589ec-0edf-4690-9ce4-7b969ae0bb44\r\n\r\n####
New
behavior\r\n\r\n\r\nhttps://github.com/user-attachments/assets/7cf720b8-5b31-4cc9-b213-21472ea880d6\r\n\r\nThe
rest of the flyout's behavior remains untouched:\r\n- identical default
widths\r\n- user selected widths are still applied\r\n- no changes to
the preview behavior\r\n\r\n### Checklist\r\n\r\n- [ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"7a9bf1399c39e9306bbfb23e73a4d72fe8aae967"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.18","8.17","8.16"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/210225","number":210225,"mergeCommit":{"message":"[Security
Solution][Expandable flyout] fix flyout flickering when opening/closing
left panel (#210225)\n\n## Summary\r\n\r\nWe recently improved the
expandable flyout by adding support for a\r\n[fully resizable
flyout](https://github.com/elastic/kibana/pull/192906).\r\nThis work
introduce a minor inconvenience, where the right panel
gets\r\nre-rendered every time the user expands or collapses the
flyout.\r\n\r\nThis PR fixes this issue by better using the EUI
resizable container\r\n(see how to externally control a resizable
container\r\n[here](https://eui.elastic.co/#/layout/resizable-container#collapsible-panels-with-external-control)).\r\nThe
flyout is now always showing a resizable container (even in\r\ncollapsed
mode) but EUI manages internally hiding the left section and\r\nthe
resize button.\r\n\r\n#### Old
behavior\r\n\r\n\r\nhttps://github.com/user-attachments/assets/4d7589ec-0edf-4690-9ce4-7b969ae0bb44\r\n\r\n####
New
behavior\r\n\r\n\r\nhttps://github.com/user-attachments/assets/7cf720b8-5b31-4cc9-b213-21472ea880d6\r\n\r\nThe
rest of the flyout's behavior remains untouched:\r\n- identical default
widths\r\n- user selected widths are still applied\r\n- no changes to
the preview behavior\r\n\r\n### Checklist\r\n\r\n- [ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"7a9bf1399c39e9306bbfb23e73a4d72fe8aae967"}},{"branch":"8.17","label":"v8.17.3","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.16","label":"v8.16.5","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
  • Loading branch information
PhilippeOberti authored Feb 8, 2025
1 parent 5bddc08 commit 49596e7
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
useDispatch,
useSelector,
} from '../store/redux';
import { RightSection } from './right_section';
import { useSections } from '../hooks/use_sections';
import { useExpandableFlyoutState } from '../hooks/use_expandable_flyout_state';
import { useExpandableFlyoutApi } from '../hooks/use_expandable_flyout_api';
Expand Down Expand Up @@ -212,15 +211,12 @@ export const Container: React.FC<ContainerProps> = memo(
onResize={onResize}
minWidth={minFlyoutWidth}
>
{showCollapsed && <RightSection component={rightComponent as React.ReactElement} />}

{showExpanded && (
<ResizableContainer
leftComponent={leftComponent as React.ReactElement}
rightComponent={rightComponent as React.ReactElement}
showPreview={showPreview}
/>
)}
<ResizableContainer
leftComponent={leftComponent as React.ReactElement}
rightComponent={rightComponent as React.ReactElement}
showLeft={showExpanded}
showPreview={showPreview}
/>

{showPreview && (
<PreviewSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const leftComponent = <div>{'left component'}</div>;
const rightComponent = <div>{'right component'}</div>;

describe('ResizableContainer', () => {
it('should render left and right component as well as resize button', () => {
it('should render right section only', () => {
const state = {
...initialState,
ui: {
Expand All @@ -37,13 +37,86 @@ describe('ResizableContainer', () => {
<ResizableContainer
leftComponent={leftComponent}
rightComponent={rightComponent}
showLeft={false}
showPreview={false}
/>
</TestProvider>
);

expect(getByTestId(RESIZABLE_LEFT_SECTION_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RESIZABLE_BUTTON_TEST_ID)).toBeInTheDocument();
expect(getByTestId(RESIZABLE_RIGHT_SECTION_TEST_ID)).toBeInTheDocument();
const rightSection = getByTestId(RESIZABLE_RIGHT_SECTION_TEST_ID);
expect(rightSection).toBeInTheDocument();
expect(rightSection.parentElement).toHaveStyle('inline-size: 100%; block-size: auto;');

const resizeButton = getByTestId(RESIZABLE_BUTTON_TEST_ID);
expect(resizeButton).toBeInTheDocument();
expect(resizeButton).toBeDisabled();

const leftSection = getByTestId(RESIZABLE_LEFT_SECTION_TEST_ID);
expect(leftSection).toBeInTheDocument();
expect(leftSection.parentElement).toHaveStyle('inline-size: 0%; block-size: auto;');
});

it('should render left and right components with resize button enabled', () => {
const state = {
...initialState,
ui: {
...initialState.ui,
userSectionWidths: {
leftPercentage: 50,
rightPercentage: 50,
},
},
};

const { getByTestId } = render(
<TestProvider state={state}>
<ResizableContainer
leftComponent={leftComponent}
rightComponent={rightComponent}
showLeft={true}
showPreview={false}
/>
</TestProvider>
);

const rightSection = getByTestId(RESIZABLE_RIGHT_SECTION_TEST_ID);
expect(rightSection).toBeInTheDocument();
expect(rightSection.parentElement).toHaveStyle('inline-size: 50%; block-size: auto;');

const resizeButton = getByTestId(RESIZABLE_BUTTON_TEST_ID);
expect(resizeButton).toBeInTheDocument();
expect(resizeButton).not.toBeDisabled();

const leftSection = getByTestId(RESIZABLE_LEFT_SECTION_TEST_ID);
expect(leftSection).toBeInTheDocument();
expect(leftSection.parentElement).toHaveStyle('inline-size: 50%; block-size: auto;');
});

it('should disable the resize button if preview is rendered', () => {
const state = {
...initialState,
ui: {
...initialState.ui,
userSectionWidths: {
leftPercentage: 50,
rightPercentage: 50,
},
},
};

const { getByTestId } = render(
<TestProvider state={state}>
<ResizableContainer
leftComponent={leftComponent}
rightComponent={rightComponent}
showLeft={true}
showPreview={true}
/>
</TestProvider>
);

const resizeButton = getByTestId(RESIZABLE_BUTTON_TEST_ID);
expect(resizeButton).toBeInTheDocument();
expect(resizeButton).toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import {
import { LeftSection } from './left_section';
import { RightSection } from './right_section';

const RIGHT_SECTION_MIN_WIDTH = '380px';
const LEFT_SECTION_MIN_WIDTH = '380px';
const MIN_SECTION_WIDTH = '380px';
const LEFT_PANEL_ID = 'left';
const RIGHT_PANEL_ID = 'right';

Expand All @@ -37,6 +36,10 @@ interface ResizableContainerProps {
* The component to render on the right side of the flyout
*/
rightComponent: React.ReactElement;
/**
* If the left section is not shown we disable the resize button and hide the left size of the resizable panel
*/
showLeft: boolean;
/**
* If the preview section is shown we disable the resize button
*/
Expand All @@ -48,19 +51,19 @@ interface ResizableContainerProps {
* It allows the resizing of the sections, saving the percentages in local storage.
*/
export const ResizableContainer: React.FC<ResizableContainerProps> = memo(
({ leftComponent, rightComponent, showPreview }: ResizableContainerProps) => {
({ leftComponent, rightComponent, showLeft, showPreview }: ResizableContainerProps) => {
const dispatch = useDispatch();

const { leftPercentage, rightPercentage } = useSelector(selectUserSectionWidths);
const defaultPercentages = useSelector(selectDefaultWidths);

const initialLeftPercentage = useMemo(
() => leftPercentage || defaultPercentages.leftPercentage,
[defaultPercentages.leftPercentage, leftPercentage]
() => (showLeft ? leftPercentage || defaultPercentages.leftPercentage : 0),
[defaultPercentages, leftPercentage, showLeft]
);
const initialRightPercentage = useMemo(
() => rightPercentage || defaultPercentages.rightPercentage,
[defaultPercentages.rightPercentage, rightPercentage]
() => (showLeft ? rightPercentage || defaultPercentages.rightPercentage : 100),
[defaultPercentages, rightPercentage, showLeft]
);

const onWidthChange = useCallback(
Expand All @@ -86,19 +89,20 @@ export const ResizableContainer: React.FC<ResizableContainerProps> = memo(
<EuiResizablePanel
id={LEFT_PANEL_ID}
initialSize={initialLeftPercentage}
size={leftPercentage}
minSize={LEFT_SECTION_MIN_WIDTH}
paddingSize="none"
minSize={MIN_SECTION_WIDTH}
data-test-subj={RESIZABLE_LEFT_SECTION_TEST_ID}
>
<LeftSection component={leftComponent} />
</EuiResizablePanel>
<EuiResizableButton disabled={showPreview} data-test-subj={RESIZABLE_BUTTON_TEST_ID} />
<EuiResizableButton
disabled={showPreview || !showLeft}
data-test-subj={RESIZABLE_BUTTON_TEST_ID}
/>
<EuiResizablePanel
id={RIGHT_PANEL_ID}
initialSize={initialRightPercentage}
size={rightPercentage}
minSize={RIGHT_SECTION_MIN_WIDTH}
minSize={MIN_SECTION_WIDTH}
paddingSize="none"
data-test-subj={RESIZABLE_RIGHT_SECTION_TEST_ID}
>
Expand Down

0 comments on commit 49596e7

Please sign in to comment.