Skip to content

Commit

Permalink
[Storybook] Add stories for more components (letter P) - Part 2 (elas…
Browse files Browse the repository at this point in the history
…tic#7674)

Co-authored-by: Cee Chen <[email protected]>
  • Loading branch information
mgadewoll and cee-chen committed May 3, 2024
1 parent de42633 commit 061f3fa
Show file tree
Hide file tree
Showing 8 changed files with 565 additions and 1 deletion.
125 changes: 125 additions & 0 deletions src/components/popover/input_popover.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';

import {
disableStorybookControls,
enableFunctionToggleControls,
moveStorybookControlsToCategory,
} from '../../../.storybook/utils';
import { EuiFieldText } from '../form';
import { EuiInputPopover, EuiInputPopoverProps } from './input_popover';

const meta: Meta<EuiInputPopoverProps> = {
title: 'Layout/EuiInputPopover',
component: EuiInputPopover,
args: {
anchorPosition: 'downLeft',
attachToAnchor: true,
repositionToCrossAxis: false,
display: 'block',
panelPaddingSize: 's',
closeOnScroll: false,
ownFocus: false,
disableFocusTrap: false,
fullWidth: false,
panelMinWidth: 0,
offset: undefined,
buffer: undefined,
hasDragDrop: false,
panelClassName: '',
popoverScreenReaderText: '',
},
};
moveStorybookControlsToCategory(
meta,
[
'attachToAnchor',
'buffer',
'closePopover',
'disableFocusTrap',
'display',
'hasDragDrop',
'isOpen',
'offset',
'onPositionChange',
'ownFocus',
'panelClassName',
'panelPaddingSize',
'popoverScreenReaderText',
'repositionToCrossAxis',
],
'EuiPopover props'
);
disableStorybookControls(meta, ['input', 'inputRef']);

export default meta;
type Story = StoryObj<EuiInputPopoverProps>;

export const Playground: Story = {
args: {
children: 'Popover content',
isOpen: true,
},
render: (args) => <StatefulInputPopover {...args} />,
};
enableFunctionToggleControls(Playground, [
'closePopover',
'onPanelResize',
'onPositionChange',
]);

const StatefulInputPopover = ({
children,
input,
closePopover,
isOpen: _isOpen,
...rest
}: EuiInputPopoverProps) => {
const [isOpen, setOpen] = useState(_isOpen);

const handleOnClose = () => {
setOpen(false);
closePopover?.();
};

return (
<EuiInputPopover
isOpen={isOpen}
closePopover={handleOnClose}
input={
<EuiFieldText
onFocus={() => setOpen(true)}
placeholder="Focus me to toggle an input popover"
aria-label="Popover attached to input element"
/>
}
{...rest}
>
{children}
</EuiInputPopover>
);
};

export const AnchorPosition: Story = {
parameters: {
controls: { include: ['anchorPosition', 'panelMinWidth'] },
},
args: {
children: 'Popover content',
isOpen: true,
panelMinWidth: 500,
},
render: (args) => (
<div css={{ display: 'flex', justifyContent: 'center' }}>
<StatefulInputPopover {...args} />
</div>
),
};
123 changes: 123 additions & 0 deletions src/components/popover/popover.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React, { useState } from 'react';
import { css } from '@emotion/react';
import type { Meta, StoryObj } from '@storybook/react';

import {
disableStorybookControls,
enableFunctionToggleControls,
} from '../../../.storybook/utils';
import { EuiButton } from '../button';
import { EuiFlexGroup } from '../flex';
import { EuiText } from '../text';

import { EuiPopoverTitle } from './popover_title';
import { EuiPopoverFooter } from './popover_footer';
import { EuiPopover, EuiPopoverProps } from './popover';

const meta: Meta<EuiPopoverProps> = {
title: 'Layout/EuiPopover/EuiPopover',
component: EuiPopover,
parameters: {
layout: 'fullscreen',
},
args: {
isOpen: false,
ownFocus: true,
panelPaddingSize: 'm',
buffer: 16,
hasArrow: true,
anchorPosition: 'downCenter',
display: 'inline-block',
repositionToCrossAxis: true,
repositionOnScroll: false,
// adding defaults for quicker/easier QA
arrowChildren: '',
attachToAnchor: false,
hasDragDrop: false,
panelClassName: '',
popoverScreenReaderText: '',
},
argTypes: {
buffer: { control: 'number' }, // For ease of QA
},
};
disableStorybookControls(meta, ['panelRef', 'popoverRef', 'closePopover']);

export default meta;
type Story = StoryObj<EuiPopoverProps>;

export const Playground: Story = {
args: {
children: 'This is a popover',
button: 'popover trigger',
isOpen: true,
},
render: (args) => <StatefulPopover {...args} />,
};
enableFunctionToggleControls(Playground, ['onPositionChange']);

const StatefulPopover = ({
button,
closePopover,
isOpen: _isOpen,
...rest
}: EuiPopoverProps) => {
const [isOpen, setOpen] = useState(_isOpen);

const handleOnClose = () => {
setOpen(false);
closePopover?.();
};

const trigger = (
<EuiButton onClick={() => setOpen(!isOpen)}>
{button || 'trigger'}
</EuiButton>
);

return (
<EuiFlexGroup
alignItems="center"
justifyContent="center"
css={css`
block-size: 100vh;
`}
>
<EuiPopover
isOpen={isOpen}
button={trigger}
closePopover={handleOnClose}
{...rest}
/>
</EuiFlexGroup>
);
};

export const PanelPaddingSize: Story = {
parameters: {
controls: { include: ['panelPaddingSize'] },
},
args: {
children: (
<>
<EuiPopoverTitle>Popover title</EuiPopoverTitle>
<EuiText>
Panel padding size will cascade down to its child{' '}
<strong>EuiPopoverTitle</strong> and <strong>EuiPopoverFooter</strong>
</EuiText>
<EuiPopoverFooter>Popover footer</EuiPopoverFooter>
</>
),
button: 'popover trigger',
isOpen: true,
},
render: (args) => <StatefulPopover {...args} />,
};
13 changes: 12 additions & 1 deletion src/components/popover/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export interface EuiPopoverProps extends PropsWithChildren, CommonProps {
/**
* Minimum distance between the popover and the bounding container;
* Pass an array of 4 values to adjust each side differently: `[top, right, bottom, left]`
* Default is 16
* @default 16
*/
buffer?: number | [number, number, number, number];
/**
Expand Down Expand Up @@ -455,6 +455,17 @@ export class EuiPopover extends Component<Props, State> {
this.onOpenPopover();
}

// ensure recalculation of panel position on prop updates
if (
this.props.isOpen &&
(prevProps.anchorPosition !== this.props.anchorPosition ||
prevProps.buffer !== this.props.buffer ||
prevProps.offset !== this.props.offset ||
prevProps.panelPaddingSize !== this.props.panelPaddingSize)
) {
this.positionPopoverFluid();
}

// update scroll listener
if (prevProps.repositionOnScroll !== this.props.repositionOnScroll) {
if (this.props.repositionOnScroll) {
Expand Down
42 changes: 42 additions & 0 deletions src/components/popover/popover_footer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';

import { PADDING_SIZES } from '../../global_styling';
import { EuiButton } from '../button';
import { EuiPopover } from './popover';
import { EuiPopoverFooter, EuiPopoverFooterProps } from './popover_footer';

const meta: Meta<EuiPopoverFooterProps> = {
title: 'Layout/EuiPopover/EuiPopoverFooter',
component: EuiPopoverFooter,
decorators: [
(Story) => (
<EuiPopover isOpen button={<EuiButton>trigger</EuiButton>}>
<Story />
</EuiPopover>
),
],
argTypes: {
paddingSize: {
control: 'select',
options: [undefined, ...PADDING_SIZES],
},
},
};

export default meta;
type Story = StoryObj<EuiPopoverFooterProps>;

export const Playground: Story = {
args: {
children: 'Popover footer',
},
};
42 changes: 42 additions & 0 deletions src/components/popover/popover_title.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';

import { PADDING_SIZES } from '../../global_styling';
import { EuiButton } from '../button';
import { EuiPopover } from './popover';
import { EuiPopoverTitle, EuiPopoverTitleProps } from './popover_title';

const meta: Meta<EuiPopoverTitleProps> = {
title: 'Layout/EuiPopover/EuiPopoverTitle',
component: EuiPopoverTitle,
decorators: [
(Story) => (
<EuiPopover isOpen button={<EuiButton>trigger</EuiButton>}>
<Story />
</EuiPopover>
),
],
argTypes: {
paddingSize: {
control: 'select',
options: [undefined, ...PADDING_SIZES],
},
},
};

export default meta;
type Story = StoryObj<EuiPopoverTitleProps>;

export const Playground: Story = {
args: {
children: 'Popover title',
},
};
Loading

0 comments on commit 061f3fa

Please sign in to comment.