mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Security Solution] expanded flyout using dynamic width (#154114)
This commit is contained in:
parent
ac621ab49c
commit
fef2cbd0db
9 changed files with 29 additions and 41 deletions
|
@ -61,6 +61,5 @@ A set of properties defining what's displayed in one of the flyout section.
|
||||||
|
|
||||||
## Future work
|
## Future work
|
||||||
|
|
||||||
- currently the panels are aware of their width. This should be changed and the width of the left, right and preview sections should be handled by the flyout itself
|
- add the feature to save the flyout state (layout) to the url (https://github.com/elastic/security-team/issues/6119)
|
||||||
- add the feature to save the flyout state (layout) to the url
|
|
||||||
- introduce the notion of scope to be able to handle more than one flyout per plugin??
|
- introduce the notion of scope to be able to handle more than one flyout per plugin??
|
|
@ -26,10 +26,8 @@ interface LeftSectionProps {
|
||||||
*/
|
*/
|
||||||
export const LeftSection: React.FC<LeftSectionProps> = ({ component, width }: LeftSectionProps) => {
|
export const LeftSection: React.FC<LeftSectionProps> = ({ component, width }: LeftSectionProps) => {
|
||||||
return (
|
return (
|
||||||
<EuiFlexItem grow data-test-subj={LEFT_SECTION}>
|
<EuiFlexItem grow data-test-subj={LEFT_SECTION} style={{ width: `${width * 100}%` }}>
|
||||||
<EuiFlexGroup direction="column" style={{ maxWidth: width, width: 'auto' }}>
|
<EuiFlexGroup direction="column">{component}</EuiFlexGroup>
|
||||||
{component}
|
|
||||||
</EuiFlexGroup>
|
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ interface PreviewSectionProps {
|
||||||
/**
|
/**
|
||||||
* Width used when rendering the panel
|
* Width used when rendering the panel
|
||||||
*/
|
*/
|
||||||
width: number | undefined;
|
width: number;
|
||||||
/**
|
/**
|
||||||
* Display the back button in the header
|
* Display the back button in the header
|
||||||
*/
|
*/
|
||||||
|
@ -50,8 +50,7 @@ export const PreviewSection: React.FC<PreviewSectionProps> = ({
|
||||||
}: PreviewSectionProps) => {
|
}: PreviewSectionProps) => {
|
||||||
const { euiTheme } = useEuiTheme();
|
const { euiTheme } = useEuiTheme();
|
||||||
const { closePreviewPanel, previousPreviewPanel } = useExpandableFlyoutContext();
|
const { closePreviewPanel, previousPreviewPanel } = useExpandableFlyoutContext();
|
||||||
|
const left = `${(1 - width) * 100}%`;
|
||||||
const previewWith: string = width ? `${width}px` : '0px';
|
|
||||||
|
|
||||||
const closeButton = (
|
const closeButton = (
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
|
@ -91,7 +90,7 @@ export const PreviewSection: React.FC<PreviewSectionProps> = ({
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: ${previewWith};
|
left: ${left};
|
||||||
background-color: ${euiTheme.colors.shadow};
|
background-color: ${euiTheme.colors.shadow};
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
`}
|
`}
|
||||||
|
@ -102,7 +101,7 @@ export const PreviewSection: React.FC<PreviewSectionProps> = ({
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
left: ${previewWith};
|
left: ${left};
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
|
|
|
@ -29,10 +29,12 @@ export const RightSection: React.FC<RightSectionProps> = ({
|
||||||
width,
|
width,
|
||||||
}: RightSectionProps) => {
|
}: RightSectionProps) => {
|
||||||
return (
|
return (
|
||||||
<EuiFlexItem grow={false} style={{ height: '100%' }} data-test-subj={RIGHT_SECTION}>
|
<EuiFlexItem
|
||||||
<EuiFlexGroup direction="column" style={{ width }}>
|
grow={false}
|
||||||
{component}
|
style={{ height: '100%', width: `${width * 100}%` }}
|
||||||
</EuiFlexGroup>
|
data-test-subj={RIGHT_SECTION}
|
||||||
|
>
|
||||||
|
<EuiFlexGroup direction="column">{component}</EuiFlexGroup>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,6 @@ describe('ExpandableFlyout', () => {
|
||||||
const registeredPanels: Panel[] = [
|
const registeredPanels: Panel[] = [
|
||||||
{
|
{
|
||||||
key: 'key',
|
key: 'key',
|
||||||
width: 500,
|
|
||||||
component: () => <div>{'component'}</div>,
|
component: () => <div>{'component'}</div>,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -30,6 +30,9 @@ export interface ExpandableFlyoutProps extends EuiFlyoutProps {
|
||||||
/**
|
/**
|
||||||
* Expandable flyout UI React component.
|
* Expandable flyout UI React component.
|
||||||
* Displays 3 sections (right, left, preview) depending on the panels in the context.
|
* Displays 3 sections (right, left, preview) depending on the panels in the context.
|
||||||
|
*
|
||||||
|
* The behavior expects that the left and preview sections should only be displayed is a right section
|
||||||
|
* is already rendered.
|
||||||
*/
|
*/
|
||||||
export const ExpandableFlyout: React.FC<ExpandableFlyoutProps> = ({
|
export const ExpandableFlyout: React.FC<ExpandableFlyoutProps> = ({
|
||||||
registeredPanels,
|
registeredPanels,
|
||||||
|
@ -67,7 +70,10 @@ export const ExpandableFlyout: React.FC<ExpandableFlyoutProps> = ({
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const width: number = (leftSection?.width ?? 0) + (rightSection?.width ?? 0);
|
const flyoutWidth: string = leftSection && rightSection ? 'l' : 's';
|
||||||
|
const rightSectionWidth: number = leftSection ? 0.4 : 1;
|
||||||
|
const leftSectionWidth: number = 0.6;
|
||||||
|
const previewSectionWidth: number = leftSection ? 0.4 : 1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiFlyout
|
<EuiFlyout
|
||||||
|
@ -75,7 +81,7 @@ export const ExpandableFlyout: React.FC<ExpandableFlyoutProps> = ({
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
`}
|
`}
|
||||||
{...flyoutProps}
|
{...flyoutProps}
|
||||||
size={width}
|
size={flyoutWidth}
|
||||||
ownFocus={false}
|
ownFocus={false}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
>
|
>
|
||||||
|
@ -88,13 +94,13 @@ export const ExpandableFlyout: React.FC<ExpandableFlyoutProps> = ({
|
||||||
{leftSection && left ? (
|
{leftSection && left ? (
|
||||||
<LeftSection
|
<LeftSection
|
||||||
component={leftSection.component({ ...(left as FlyoutPanel) })}
|
component={leftSection.component({ ...(left as FlyoutPanel) })}
|
||||||
width={leftSection.width}
|
width={leftSectionWidth}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{rightSection && right ? (
|
{rightSection && right ? (
|
||||||
<RightSection
|
<RightSection
|
||||||
component={rightSection.component({ ...(right as FlyoutPanel) })}
|
component={rightSection.component({ ...(right as FlyoutPanel) })}
|
||||||
width={rightSection.width}
|
width={rightSectionWidth}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
|
@ -103,7 +109,7 @@ export const ExpandableFlyout: React.FC<ExpandableFlyoutProps> = ({
|
||||||
<PreviewSection
|
<PreviewSection
|
||||||
component={previewSection.component({ ...(mostRecentPreview as FlyoutPanel) })}
|
component={previewSection.component({ ...(mostRecentPreview as FlyoutPanel) })}
|
||||||
showBackButton={showBackButton}
|
showBackButton={showBackButton}
|
||||||
width={leftSection?.width}
|
width={previewSectionWidth}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</EuiFlyout>
|
</EuiFlyout>
|
||||||
|
|
|
@ -36,8 +36,4 @@ export interface Panel {
|
||||||
* Component to be rendered
|
* Component to be rendered
|
||||||
*/
|
*/
|
||||||
component: (props: FlyoutPanel) => React.ReactElement;
|
component: (props: FlyoutPanel) => React.ReactElement;
|
||||||
/**
|
|
||||||
* Width used when rendering the panel
|
|
||||||
*/
|
|
||||||
width: number; // TODO remove this, see https://github.com/elastic/security-team/issues/6247
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,6 @@ import type { LeftPanelProps } from './left';
|
||||||
import { LeftPanel, LeftPanelKey } from './left';
|
import { LeftPanel, LeftPanelKey } from './left';
|
||||||
import { LeftPanelProvider } from './left/context';
|
import { LeftPanelProvider } from './left/context';
|
||||||
|
|
||||||
// TODO these should be replaced by a more dynamic solution
|
|
||||||
// see https://github.com/elastic/security-team/issues/6247
|
|
||||||
export const RIGHT_SECTION_WIDTH = 500;
|
|
||||||
export const LEFT_SECTION_WIDTH = 1000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of all panels that will be used within the document details expandable flyout.
|
* List of all panels that will be used within the document details expandable flyout.
|
||||||
* This needs to be passed to the expandable flyout registeredPanels property.
|
* This needs to be passed to the expandable flyout registeredPanels property.
|
||||||
|
@ -26,7 +21,6 @@ export const LEFT_SECTION_WIDTH = 1000;
|
||||||
export const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels'] = [
|
export const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels'] = [
|
||||||
{
|
{
|
||||||
key: RightPanelKey,
|
key: RightPanelKey,
|
||||||
width: RIGHT_SECTION_WIDTH,
|
|
||||||
component: (props) => (
|
component: (props) => (
|
||||||
<RightPanelProvider {...(props as RightPanelProps).params}>
|
<RightPanelProvider {...(props as RightPanelProps).params}>
|
||||||
<RightPanel path={props.path as RightPanelProps['path']} />
|
<RightPanel path={props.path as RightPanelProps['path']} />
|
||||||
|
@ -35,7 +29,6 @@ export const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredP
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: LeftPanelKey,
|
key: LeftPanelKey,
|
||||||
width: LEFT_SECTION_WIDTH,
|
|
||||||
component: (props) => (
|
component: (props) => (
|
||||||
<LeftPanelProvider {...(props as LeftPanelProps).params}>
|
<LeftPanelProvider {...(props as LeftPanelProps).params}>
|
||||||
<LeftPanel path={props.path as LeftPanelProps['path']} />
|
<LeftPanel path={props.path as LeftPanelProps['path']} />
|
||||||
|
|
|
@ -8,13 +8,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css } from '@emotion/react';
|
import { css } from '@emotion/react';
|
||||||
import type { Story } from '@storybook/react';
|
import type { Story } from '@storybook/react';
|
||||||
import { RIGHT_SECTION_WIDTH } from '../..';
|
|
||||||
import { Description } from './description';
|
import { Description } from './description';
|
||||||
import { RightPanelContext } from '../context';
|
import { RightPanelContext } from '../context';
|
||||||
|
|
||||||
const PADDING = 24;
|
|
||||||
const WIDTH = RIGHT_SECTION_WIDTH - 2 * PADDING;
|
|
||||||
|
|
||||||
const ruleUuid = {
|
const ruleUuid = {
|
||||||
category: 'kibana',
|
category: 'kibana',
|
||||||
field: 'kibana.alert.rule.uuid',
|
field: 'kibana.alert.rule.uuid',
|
||||||
|
@ -46,7 +42,7 @@ export const RuleExpand: Story<void> = () => {
|
||||||
<RightPanelContext.Provider value={panelContextValue}>
|
<RightPanelContext.Provider value={panelContextValue}>
|
||||||
<div
|
<div
|
||||||
css={css`
|
css={css`
|
||||||
width: ${WIDTH}px; // this mimics the current 500 width of the right panel
|
width: 500px;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Description />
|
<Description />
|
||||||
|
@ -64,7 +60,7 @@ export const RuleCollapse: Story<void> = () => {
|
||||||
<RightPanelContext.Provider value={panelContextValue}>
|
<RightPanelContext.Provider value={panelContextValue}>
|
||||||
<div
|
<div
|
||||||
css={css`
|
css={css`
|
||||||
width: ${WIDTH}px; // this mimics the current 500 width of the right panel
|
width: 500px;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Description expanded={true} />
|
<Description expanded={true} />
|
||||||
|
@ -90,7 +86,7 @@ export const Document: Story<void> = () => {
|
||||||
<RightPanelContext.Provider value={panelContextValue}>
|
<RightPanelContext.Provider value={panelContextValue}>
|
||||||
<div
|
<div
|
||||||
css={css`
|
css={css`
|
||||||
width: ${WIDTH}px; // this mimics the current 500 width of the right panel
|
width: 500px;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Description />
|
<Description />
|
||||||
|
@ -116,7 +112,7 @@ export const EmptyDescription: Story<void> = () => {
|
||||||
<RightPanelContext.Provider value={panelContextValue}>
|
<RightPanelContext.Provider value={panelContextValue}>
|
||||||
<div
|
<div
|
||||||
css={css`
|
css={css`
|
||||||
width: ${WIDTH}px; // this mimics the current 500 width of the right panel
|
width: 500px;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Description expanded={true} />
|
<Description expanded={true} />
|
||||||
|
@ -131,7 +127,7 @@ export const Empty: Story<void> = () => {
|
||||||
<RightPanelContext.Provider value={panelContextValue}>
|
<RightPanelContext.Provider value={panelContextValue}>
|
||||||
<div
|
<div
|
||||||
css={css`
|
css={css`
|
||||||
width: ${WIDTH}px; // this mimics the current 500 width of the right panel
|
width: 500px;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<Description expanded={true} />
|
<Description expanded={true} />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue