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 playground stories for remaining C components #7467

Merged
merged 7 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/upcoming/7467.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**Deprecations**

- Remove unused public `EuiCommentTimeline` subcomponent export. Use the parent `EuiComment` or `EuiCommentList` components instead.
26 changes: 23 additions & 3 deletions src/components/collapsible_nav/collapsible_nav.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,38 @@
* Side Public License, v 1.
*/

import type { Meta, StoryObj } from '@storybook/react';
import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { disableStorybookControls } from '../../../.storybook/utils';

import { EuiButton } from '../button';
import { EuiCollapsibleNav, EuiCollapsibleNavProps } from './collapsible_nav';

const meta: Meta<EuiCollapsibleNavProps> = {
title: 'EuiCollapsibleNav',
component: EuiCollapsibleNav,
argTypes: {
...disableStorybookControls(['button']),
Copy link
Member

Choose a reason for hiding this comment

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

Would this be better as text?

diff --git a/src/components/collapsible_nav/collapsible_nav.stories.tsx b/src/components/collapsible_nav/collapsible_nav.stories.tsx
index 777f63732..1250f1140 100644
--- a/src/components/collapsible_nav/collapsible_nav.stories.tsx
+++ b/src/components/collapsible_nav/collapsible_nav.stories.tsx
@@ -18,9 +18,10 @@ const meta: Meta<EuiCollapsibleNavProps> = {
   title: 'EuiCollapsibleNav',
   component: EuiCollapsibleNav,
   argTypes: {
-    ...disableStorybookControls(['button']),
+    ...disableStorybookControls([]),
     as: { options: ['nav', 'div'], control: 'radio' },
     maxWidth: { control: 'number' }, // TODO: also accepts bool | string
+    button: { control: 'tex
<img width="1561" alt="Screenshot 2024-01-17 at 4 49 46 PM" src="https://github.com/elastic/eui/assets/1427475/d470b54f-b1b8-4343-980b-d9be6eae7dd9">
t' },
   },
   args: {
     // Component defaults
@@ -38,6 +39,7 @@ const meta: Meta<EuiCollapsibleNavProps> = {
     includeFixedHeadersInFocusTrap: true,
     outsideClickCloses: true,
     ownFocus: true,
+    button: 'Toggle nav',
   },
   // TODO: Improve props inherited from EuiFlyout, ideally through
   // a DRY import from `flyout.stories.tsx` once that's created
@@ -48,13 +50,14 @@ type Story = StoryObj<EuiCollapsibleNavProps>;
 
 const StatefulCollapsibleNav = (props: Partial<EuiCollapsibleNavProps>) => {
   const [isOpen, setIsOpen] = useState(props.isOpen);
+  const button = props.button;
   return (
     <EuiCollapsibleNav
       {...props}
       isOpen={isOpen}
       button={
         <EuiButton onClick={() => setIsOpen((isOpen) => !isOpen)}>
-          Toggle nav
+          {button}
         </EuiButton>
       }
       onClose={(...args) => {
Screenshot 2024-01-17 at 4 49 46 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Personally, I don't think so. IMO, it's confusing/not a good example of what a consumer would actually pass to the button prop, which would be something like: button={<EuiButton onClick={toggleCollapsibleNav} />}. The controls should try to provide code examples for consumers if possible, and setting this to a string would indicate a button automagically renders if they pass button="Open me", which is not the case.

as: { options: ['nav', 'div'], control: 'radio' },
maxWidth: { control: 'number' }, // TODO: also accepts bool | string
},
args: {
// Component defaults
as: 'nav',
side: 'left',
size: 320,
paddingSize: 'none',
pushAnimation: false,
pushMinBreakpoint: 'l',
isDocked: false,
dockedBreakpoint: 'l',
showButtonIfDocked: false,
size: 320,
closeButtonPosition: 'outside',
hideCloseButton: false,
includeFixedHeadersInFocusTrap: true,
outsideClickCloses: true,
ownFocus: true,
},
// TODO: Improve props inherited from EuiFlyout, ideally through
// a DRY import from `flyout.stories.tsx` once that's created
Expand All @@ -40,7 +57,10 @@ const StatefulCollapsibleNav = (props: Partial<EuiCollapsibleNavProps>) => {
Toggle nav
</EuiButton>
}
onClose={() => setIsOpen(false)}
onClose={(...args) => {
setIsOpen(false);
action('onClose')(...args);
}}
/>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/collapsible_nav/collapsible_nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { euiCollapsibleNavStyles } from './collapsible_nav.styles';

// Extend all the flyout props except `onClose` because we handle this internally
export type EuiCollapsibleNavProps = Omit<
EuiFlyoutProps,
EuiFlyoutProps<'nav' | 'div'>,
'type' | 'pushBreakpoint'
> & {
/**
Expand Down Expand Up @@ -64,7 +64,7 @@ export const EuiCollapsibleNav: FunctionComponent<EuiCollapsibleNavProps> = ({
showButtonIfDocked = false,
dockedBreakpoint = 'l',
// Setting different EuiFlyout defaults
as = 'nav' as EuiCollapsibleNavProps['as'],
as = 'nav',
size = 320,
side = 'left',
ownFocus = true,
Expand Down
56 changes: 44 additions & 12 deletions src/components/combo_box/combo_box.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
* Side Public License, v 1.
*/

import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import React, { useCallback, useState } from 'react';
import { action } from '@storybook/addon-actions';

import { EuiComboBox, EuiComboBoxProps } from './combo_box';

Expand All @@ -23,34 +24,64 @@ const meta: Meta<EuiComboBoxProps<{}>> = {
title: 'EuiComboBox',
// @ts-ignore typescript shenanigans
component: EuiComboBox,
args: {
options: options,
selectedOptions: [options[0]],
singleSelection: false,
},
argTypes: {
singleSelection: {
control: 'radio',
options: [false, true, 'asPlainText'],
},
append: { control: 'text' },
prepend: { control: 'text' },
// Storybook is skipping the Pick<> props from EuiComboBoxList for some annoying reason
onCreateOption: { control: 'boolean' }, // Set to a true/false for ease of testing
JasonStoltz marked this conversation as resolved.
Show resolved Hide resolved
customOptionText: { control: 'text' },
renderOption: { control: 'function' },
},
args: {
// Pass options in by default for ease of testing
options: options,
selectedOptions: [options[0]],
// Component defaults
delimiter: ',',
sortMatchesBy: 'none',
singleSelection: false,
noSuggestions: false,
async: false,
isCaseSensitive: false,
isClearable: true,
isDisabled: false,
isInvalid: false,
isLoading: false,
autoFocus: false,
compressed: false,
fullWidth: false,
onCreateOption: undefined, // Override Storybook's default callback
},
};

export default meta;
type Story = StoryObj<EuiComboBoxProps<{}>>;

export const Playground: Story = {
// The render function is a component, eslint just doesn't know it
/* eslint-disable react-hooks/rules-of-hooks */
render: ({ singleSelection, ...args }) => {
render: function Render({ singleSelection, onCreateOption, ...args }) {
const [selectedOptions, setSelectedOptions] = useState(
args.selectedOptions
);
const onChange = useCallback((newOptions: any[]) => {
setSelectedOptions(newOptions);
}, []);
const onChange: EuiComboBoxProps<{}>['onChange'] = (options, ...args) => {
setSelectedOptions(options);
action('onChange')(options, ...args);
};
const _onCreateOption: EuiComboBoxProps<{}>['onCreateOption'] = (
searchValue,
...args
) => {
const createdOption = { label: searchValue };
setSelectedOptions((prevState) =>
!prevState || singleSelection
? [createdOption]
: [...prevState, createdOption]
);
action('onCreateOption')(searchValue, ...args);
};
return (
<EuiComboBox
singleSelection={
Expand All @@ -62,6 +93,7 @@ export const Playground: Story = {
{...args}
selectedOptions={selectedOptions}
onChange={onChange}
onCreateOption={onCreateOption ? _onCreateOption : undefined}
/>
);
},
Expand Down
78 changes: 78 additions & 0 deletions src/components/comment_list/comment.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 { EuiButtonIcon } from '../button';

import { EuiComment, EuiCommentProps } from './comment';

/**
* Shared comment story utils/arg types
*/

export const _eventColorArgType = {
options: [
undefined,
'subdued',
'transparent',
'plain',
'warning',
'danger',
'success',
'primary',
'accent',
],
control: { type: 'radio' },
};
export const _actionsExampleArgType = {
control: 'radio',
options: ['Example action', 'No actions'],
mapping: {
'Example action': (
<EuiButtonIcon
title="Custom action"
aria-label="Custom action"
color="text"
iconType="copy"
/>
),
'No actions': null,
},
defaultValue: 'Example action',
};

/**
* Rendered stories
*/

const meta: Meta<EuiCommentProps> = {
title: 'EuiComment',
component: EuiComment,
argTypes: {
eventColor: _eventColorArgType,
actions: _actionsExampleArgType,
},
excludeStories: /^_/, // Do not render the shared argTypes as stories
};

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

export const Playground: Story = {
args: {
username: 'User',
timelineAvatar: 'user',
event: 'posted',
eventIcon: 'pencil',
timestamp: 'on Jan 1, 2020',
actions: 'Example action',
children: 'A user message or any custom component',
},
};
35 changes: 3 additions & 32 deletions src/components/comment_list/comment_event.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
* Side Public License, v 1.
*/

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

import { EuiButtonIcon } from '../button';
import { _eventColorArgType, _actionsExampleArgType } from './comment.stories';
import { EuiCommentEvent, EuiCommentEventProps } from './comment_event';

const meta: Meta<EuiCommentEventProps> = {
Expand All @@ -19,36 +18,8 @@ const meta: Meta<EuiCommentEventProps> = {
username: 'janed',
},
argTypes: {
eventColor: {
options: [
undefined,
'subdued',
'transparent',
'plain',
'warning',
'danger',
'success',
'primary',
'accent',
],
control: { type: 'radio' },
defaultValue: undefined,
},
actions: {
control: 'radio',
options: ['Example action', 'No actions'],
mapping: {
'Example action': (
<EuiButtonIcon
title="Custom action"
aria-label="Custom action"
color="text"
iconType="copy"
/>
),
'No actions': null,
},
},
eventColor: _eventColorArgType,
actions: _actionsExampleArgType,
},
};

Expand Down
Loading
Loading