Skip to content

Commit

Permalink
Expandable flyout width (#170078)
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilippeOberti authored Nov 16, 2023
1 parent d6a285b commit c3ac89c
Show file tree
Hide file tree
Showing 22 changed files with 563 additions and 73 deletions.
8 changes: 6 additions & 2 deletions packages/kbn-expandable-flyout/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ The flyout is composed of 3 sections:
The expandable-flyout package is designed to render a single flyout for an entire plugin. While displaying multiple flyouts might be feasible, it will be a bit complicated, and we recommend instead to build multiple panels, with each their own context to manage their data (for example, take a look at the Security Solution [setup](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout)).

The expandable-flyout is making some strict UI design decisions:
- when in collapsed mode (i.e. when only the right/preview section is open), the flyout's width is fixed to the EUI `s` size
- when in expanded mode (i.e. when the left section is opened), the flyout's width is fixed to the EUI `l` size. Internally the right, left and preview sections' widths are set to a hardcoded percentage (40%, 60$ and 40% respectively)
- when in collapsed mode (i.e. when only the right/preview section is open), the flyout's width linearly grows from its minimum value of 380px to its maximum value of 750px
- when in expanded mode (i.e. when the left section is opened), the flyout's width changes depending on the browser's width:
- if the window is smaller than 1600px, the flyout takes the entire browser window (minus 48px of padding on the left)
- for windows bigger than 1600px, the flyout's width is 80% of the entire browser window (with a max width of 1500px for the left section, and 750px for the right section)

> While the expandable-flyout will work on very small screens, having both the right and left sections visible at the same time will not be a good experience to the user. We recommend only showing the right panel, and therefore handling this situation when you build your panels by considering hiding the actions that could open the left panel (like the expand details button in the [FlyoutNavigation](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx)).
## Package API

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface LeftSectionProps {
*/
export const LeftSection: React.FC<LeftSectionProps> = ({ component, width }: LeftSectionProps) => {
const style = useMemo<React.CSSProperties>(
() => ({ height: '100%', width: `${width * 100}%` }),
() => ({ height: '100%', width: `${width}px` }),
[width]
);
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

import React from 'react';
import { render } from '@testing-library/react';
import { PreviewSection } from './preview_section';
import { PreviewBanner, PreviewSection } from './preview_section';
import {
PREVIEW_SECTION_BACK_BUTTON_TEST_ID,
PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID,
PREVIEW_SECTION_TEST_ID,
} from './test_ids';
import { ExpandableFlyoutContext } from '../context';

Expand All @@ -28,31 +29,59 @@ describe('PreviewSection', () => {
},
} as unknown as ExpandableFlyoutContext;

const component = <div>{'component'}</div>;
const left = 500;

it('should render close button in header', () => {
const component = <div>{'component'}</div>;
const width = 500;
const showBackButton = false;

const { getByTestId } = render(
<ExpandableFlyoutContext.Provider value={context}>
<PreviewSection component={component} width={width} showBackButton={showBackButton} />
<PreviewSection component={component} leftPosition={left} showBackButton={showBackButton} />
</ExpandableFlyoutContext.Provider>
);

expect(getByTestId(PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID)).toBeInTheDocument();
});

it('should render back button in header', () => {
const component = <div>{'component'}</div>;
const width = 500;
const showBackButton = true;

const { getByTestId } = render(
<ExpandableFlyoutContext.Provider value={context}>
<PreviewSection component={component} width={width} showBackButton={showBackButton} />
<PreviewSection component={component} leftPosition={left} showBackButton={showBackButton} />
</ExpandableFlyoutContext.Provider>
);

expect(getByTestId(PREVIEW_SECTION_BACK_BUTTON_TEST_ID)).toBeInTheDocument();
});

it('should render banner', () => {
const showBackButton = false;
const title = 'test';
const banner: PreviewBanner = {
title,
backgroundColor: 'primary',
textColor: 'red',
};

const { getByTestId, getByText } = render(
<ExpandableFlyoutContext.Provider value={context}>
<PreviewSection
component={component}
leftPosition={left}
showBackButton={showBackButton}
banner={banner}
/>
</ExpandableFlyoutContext.Provider>
);

expect(getByTestId(`${PREVIEW_SECTION_TEST_ID}BannerPanel`)).toHaveClass(
`euiPanel--${banner.backgroundColor}`
);
expect(getByTestId(`${PREVIEW_SECTION_TEST_ID}BannerText`)).toHaveStyle(
`color: ${banner.textColor}`
);
expect(getByText(title)).toBeInTheDocument();
});
});
40 changes: 26 additions & 14 deletions packages/kbn-expandable-flyout/src/components/preview_section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ interface PreviewSectionProps {
*/
component: React.ReactElement;
/**
* Width used when rendering the panel
* Left position used when rendering the panel
*/
width: number;
leftPosition: number;
/**
* Display the back button in the header
*/
Expand All @@ -85,12 +85,13 @@ interface PreviewSectionProps {
export const PreviewSection: React.FC<PreviewSectionProps> = ({
component,
showBackButton,
width,
leftPosition,
banner,
}: PreviewSectionProps) => {
const { euiTheme } = useEuiTheme();
const { closePreviewPanel, previousPreviewPanel } = useExpandableFlyoutContext();
const left = `${(1 - width) * 100}%`;

const left = leftPosition + 4;

const closeButton = (
<EuiFlexItem grow={false}>
Expand All @@ -103,7 +104,7 @@ export const PreviewSection: React.FC<PreviewSectionProps> = ({
</EuiFlexItem>
);
const header = showBackButton ? (
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexGroup justifyContent="spaceBetween" responsive={false}>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="xs"
Expand All @@ -119,32 +120,43 @@ export const PreviewSection: React.FC<PreviewSectionProps> = ({
{closeButton}
</EuiFlexGroup>
) : (
<EuiFlexGroup justifyContent="flexEnd">{closeButton}</EuiFlexGroup>
<EuiFlexGroup justifyContent="flexEnd" responsive={false}>
{closeButton}
</EuiFlexGroup>
);

return (
<div
css={css`
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: ${left};
top: 4px;
bottom: 12px;
right: 4px;
left: ${left}px;
z-index: 1000;
`}
>
<EuiSplitPanel.Outer
css={css`
margin: ${euiTheme.size.xs};
height: 99%;
box-shadow: 0px 0px 5px 5px ${euiTheme.colors.darkShade};
box-shadow: 0 0 4px 4px ${euiTheme.colors.darkShade};
`}
className="eui-yScroll"
data-test-subj={PREVIEW_SECTION_TEST_ID}
>
{isPreviewBanner(banner) && (
<EuiSplitPanel.Inner grow={false} color={banner.backgroundColor} paddingSize="none">
<EuiText textAlign="center" color={banner.textColor} size="s">
<EuiSplitPanel.Inner
grow={false}
color={banner.backgroundColor}
paddingSize="none"
data-test-subj={`${PREVIEW_SECTION_TEST_ID}BannerPanel`}
>
<EuiText
textAlign="center"
color={banner.textColor}
size="s"
data-test-subj={`${PREVIEW_SECTION_TEST_ID}BannerText`}
>
{banner.title}
</EuiText>
</EuiSplitPanel.Inner>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const RightSection: React.FC<RightSectionProps> = ({
width,
}: RightSectionProps) => {
const style = useMemo<React.CSSProperties>(
() => ({ height: '100%', width: `${width * 100}%` }),
() => ({ height: '100%', width: `${width}px` }),
[width]
);

Expand Down
Loading

0 comments on commit c3ac89c

Please sign in to comment.