[Security Solution][Expandable flyout] minor performance improvements (#218503)

## Summary

This PR performs some very minor performance improvements to the
`expandable-flyout` package:
- prevent unnecessary re-renders by extracting styles to const
- better use of `useCallback`

No UI or behavior changes are introduced.


https://github.com/user-attachments/assets/c7f55a4e-7f98-4c18-bb22-f8b81a11e626
This commit is contained in:
Philippe Oberti 2025-04-17 20:07:46 +02:00 committed by GitHub
parent c9b3a3e27b
commit a7be37e1cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 51 additions and 48 deletions

View file

@ -191,6 +191,16 @@ export const Container: React.FC<ContainerProps> = memo(
[dispatch, showCollapsed, showExpanded]
);
const onClose = useCallback(
(e: MouseEvent | TouchEvent | KeyboardEvent) => {
closeFlyout();
if (flyoutProps.onClose) {
flyoutProps.onClose(e);
}
},
[closeFlyout, flyoutProps]
);
// don't need to render if the windowWidth is 0 or if nothing needs to be rendered
if (!showExpanded && !showCollapsed && !showPreview) {
return null;
@ -204,12 +214,7 @@ export const Container: React.FC<ContainerProps> = memo(
type={flyoutType}
size={flyoutWidth}
ownFocus={false}
onClose={(e) => {
closeFlyout();
if (flyoutProps.onClose) {
flyoutProps.onClose(e);
}
}}
onClose={onClose}
css={customStyles}
onResize={onResize}
minWidth={minFlyoutWidth}

View file

@ -9,6 +9,8 @@ import { EuiFlexItem } from '@elastic/eui';
import React, { memo } from 'react';
import { LEFT_SECTION_TEST_ID } from './test_ids';
const styles = { height: '100%' };
interface LeftSectionProps {
/**
* Component to be rendered
@ -20,7 +22,7 @@ interface LeftSectionProps {
* Left section of the expanded flyout rendering a panel
*/
export const LeftSection: React.FC<LeftSectionProps> = memo(({ component }: LeftSectionProps) => (
<EuiFlexItem grow data-test-subj={LEFT_SECTION_TEST_ID} style={{ height: '100%' }}>
<EuiFlexItem grow data-test-subj={LEFT_SECTION_TEST_ID} css={styles}>
{component}
</EuiFlexItem>
));

View file

@ -18,6 +18,7 @@ import {
import React, { memo, useMemo } from 'react';
import { css } from '@emotion/react';
import { has } from 'lodash';
import { i18n } from '@kbn/i18n';
import {
selectDefaultWidths,
selectPushVsOverlay,
@ -31,7 +32,19 @@ import {
PREVIEW_SECTION_TEST_ID,
} from './test_ids';
import { useExpandableFlyoutApi } from '../..';
import { BACK_BUTTON, CLOSE_BUTTON } from './translations';
const BACK_BUTTON = i18n.translate(
'securitySolutionPackages.expandableFlyout.previewSection.backButton',
{
defaultMessage: 'Back',
}
);
const CLOSE_BUTTON = i18n.translate(
'securitySolutionPackages.expandableFlyout.previewSection.closeButton',
{
defaultMessage: 'Close',
}
);
export interface PreviewBanner {
/**
@ -108,7 +121,7 @@ export const PreviewSection: React.FC<PreviewSectionProps> = memo(
<EuiFlexItem grow={false}>
<EuiButtonIcon
iconType="cross"
onClick={() => closePreviewPanel()}
onClick={closePreviewPanel}
data-test-subj={PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID}
aria-label={CLOSE_BUTTON}
/>
@ -121,7 +134,7 @@ export const PreviewSection: React.FC<PreviewSectionProps> = memo(
size="xs"
iconType="arrowLeft"
iconSide="left"
onClick={() => previousPreviewPanel()}
onClick={previousPreviewPanel}
data-test-subj={PREVIEW_SECTION_BACK_BUTTON_TEST_ID}
aria-label={BACK_BUTTON}
>

View file

@ -9,6 +9,8 @@ import { EuiFlexItem } from '@elastic/eui';
import React, { memo } from 'react';
import { RIGHT_SECTION_TEST_ID } from './test_ids';
const styles = { height: '100%' };
interface RightSectionProps {
/**
* Component to be rendered
@ -21,7 +23,7 @@ interface RightSectionProps {
*/
export const RightSection: React.FC<RightSectionProps> = memo(
({ component }: RightSectionProps) => (
<EuiFlexItem grow={false} style={{ height: '100%' }} data-test-subj={RIGHT_SECTION_TEST_ID}>
<EuiFlexItem grow={false} css={styles} data-test-subj={RIGHT_SECTION_TEST_ID}>
{component}
</EuiFlexItem>
)

View file

@ -96,6 +96,21 @@ const FLYOUT_RESIZE_BUTTON = i18n.translate(
}
);
const OPTIONS = [
{
id: 'overlay',
label: FLYOUT_TYPE_OVERLAY_MODE,
'data-test-subj': SETTINGS_MENU_FLYOUT_TYPE_BUTTON_GROUP_OVERLAY_TEST_ID,
toolTipContent: FLYOUT_TYPE_OVERLAY_TOOLTIP,
},
{
id: 'push',
label: FLYOUT_TYPE_PUSH_MODE,
'data-test-subj': SETTINGS_MENU_FLYOUT_TYPE_BUTTON_GROUP_PUSH_TEST_ID,
toolTipContent: FLYOUT_TYPE_PUSH_TOOLTIP,
},
];
export interface FlyoutCustomProps {
/**
* Hide the gear icon and settings menu if true
@ -139,7 +154,8 @@ export interface SettingsMenuProps {
/**
* Renders a menu to allow the user to customize the flyout.
* Current customization are:
* - Flyout type: overlay or push
* - enable/disable push vs overlay
* - enable/disable reset size
*/
export const SettingsMenu: React.FC<SettingsMenuProps> = memo(
({ flyoutCustomProps }: SettingsMenuProps) => {
@ -194,20 +210,7 @@ export const SettingsMenu: React.FC<SettingsMenuProps> = memo(
<EuiSpacer size="s" />
<EuiButtonGroup
legend={FLYOUT_TYPE_TITLE}
options={[
{
id: 'overlay',
label: FLYOUT_TYPE_OVERLAY_MODE,
'data-test-subj': SETTINGS_MENU_FLYOUT_TYPE_BUTTON_GROUP_OVERLAY_TEST_ID,
toolTipContent: FLYOUT_TYPE_OVERLAY_TOOLTIP,
},
{
id: 'push',
label: FLYOUT_TYPE_PUSH_MODE,
'data-test-subj': SETTINGS_MENU_FLYOUT_TYPE_BUTTON_GROUP_PUSH_TEST_ID,
toolTipContent: FLYOUT_TYPE_PUSH_TOOLTIP,
},
]}
options={OPTIONS}
idSelected={flyoutType}
onChange={pushVsOverlayOnChange}
isDisabled={flyoutCustomProps?.pushVsOverlay?.disabled}

View file

@ -1,22 +0,0 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { i18n } from '@kbn/i18n';
export const BACK_BUTTON = i18n.translate(
'securitySolutionPackages.expandableFlyout.previewSection.backButton',
{
defaultMessage: 'Back',
}
);
export const CLOSE_BUTTON = i18n.translate(
'securitySolutionPackages.expandableFlyout.previewSection.closeButton',
{
defaultMessage: 'Close',
}
);