Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Storybook] Add stories for more components (letter P) - Part 2 #7674

Merged
merged 11 commits into from
Apr 26, 2024
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[not a change request, just a note for future me] I'd like to eventually add stories for container, insert, repositionOnScroll as well! I'm too lazy for now so I just added a quick story to demo how panelPaddingSize affects child titles & footers

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();
cee-chen marked this conversation as resolved.
Show resolved Hide resolved
}

// 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
Loading