From 329a56f3a286e2e134d494897ddb6a6f3bd69466 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Tue, 16 Jul 2024 15:00:30 -0400 Subject: [PATCH 01/17] chore(storybook): update v1 syntax to use Storybook v6 - while the deps used Storybook v6, the configuration and stories themselves were still on a legacy v5 format - v6 had backward compat for v5, but v7 does not, so this needs upgrading/migrating - or well, v7 has some legacy mode for it that can be enabled with some config, but it is entirely gone in v8 - migrate `storiesOf` to CSF per https://storybook.js.org/docs/7/migration-guide#storiesof-to-csf - then had to do a bunch of manual changes to get back mostly the same previous indentation (with some minor differences where there were mistakes or inconsistencies) - tried to keep the diff as small as possible - CSF is still valid through to latest v8 Signed-off-by: Anton Gilgur --- stories/data-loader.tsx | 19 +- stories/dropdown.tsx | 46 ++-- stories/forms.tsx | 43 ++-- stories/logs-viewer.tsx | 32 +-- stories/notifications.tsx | 40 ++-- stories/page.tsx | 178 +++++++++------ stories/popup.tsx | 455 +++++++++++++++++++++----------------- stories/select.tsx | 32 ++- stories/table.tsx | 11 +- stories/tabs.tsx | 16 +- 10 files changed, 504 insertions(+), 368 deletions(-) diff --git a/stories/data-loader.tsx b/stories/data-loader.tsx index 6c4b3b6b..0ca69ef9 100644 --- a/stories/data-loader.tsx +++ b/stories/data-loader.tsx @@ -1,4 +1,3 @@ -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import { App } from './utils'; @@ -9,10 +8,14 @@ function loadData(input: string): Promise { return new Promise((resolve) => window.setTimeout(() => resolve(`hello ${input}`), 50)); } -storiesOf('Data Loader', module) - .add('loading data asynchronously', () => { - const [input, setInput] = React.useState('world'); - return +export default { + title: 'Data Loader', +}; + +export const LoadingDataAsynchronously = () => { + const [input, setInput] = React.useState('world'); + return ( + {() => ( setInput(e.target.value)}/> @@ -26,4 +29,8 @@ storiesOf('Data Loader', module) )} - }); + ); +}; +LoadingDataAsynchronously.story = { + name: 'loading data asynchronously', +}; diff --git a/stories/dropdown.tsx b/stories/dropdown.tsx index 07a285f2..96203caf 100644 --- a/stories/dropdown.tsx +++ b/stories/dropdown.tsx @@ -1,21 +1,35 @@ -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import { DropDown } from '../src/components/dropdown/dropdown'; import { DropDownMenu } from '../src/components/dropdown-menu'; -storiesOf('Dropdown', module) - .add('default', () => Click me}>

Dropdown content here

) - .add('menu', () => ( - Click me}> - - - )).add('menu wrapper', () => ( - Click me} items={[{ - title: 'menu item 1', - action: () => window.alert('Clicked!'), - }]} /> - )); +export default { + title: 'Dropdown', +}; + +export const Default = () => ( Click me}>

Dropdown content here

); +Default.story = { + name: 'default', +}; + +export const Menu = () => ( + Click me}> + + +); +Menu.story = { + name: 'menu', +}; + +export const MenuWrapper = () => ( + Click me} items={[{ + title: 'menu item 1', + action: () => window.alert('Clicked!'), + }]} /> +); +MenuWrapper.story = { + name: 'menu wrapper', +}; diff --git a/stories/forms.tsx b/stories/forms.tsx index 9227ab4c..0e2e097f 100644 --- a/stories/forms.tsx +++ b/stories/forms.tsx @@ -1,24 +1,29 @@ -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import { Form, Text } from 'react-form'; import { FormField, FormSelect } from '../src/components/form-field/form-field'; -storiesOf('Forms', module) - .add('default', () => ( -
- {(api) => ( - -
- -
-
- -
-
- -
-
- )} - - )); +export default { + title: 'Forms', +}; + +export const Default = () => ( +
+ {(api) => ( + +
+ +
+
+ +
+
+ +
+
+ )} + +); +Default.story = { + name: 'default', +}; diff --git a/stories/logs-viewer.tsx b/stories/logs-viewer.tsx index 9354285c..8938b30d 100644 --- a/stories/logs-viewer.tsx +++ b/stories/logs-viewer.tsx @@ -1,18 +1,24 @@ -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import { Observable } from 'rxjs'; import { LogsViewer } from '../src/components/logs-viewer/logs-viewer'; -storiesOf('LogsViewer', module).add('default', () => ( -
- new Observable((observer) => { - const interval = setInterval(() => observer.next('test\n'), 1000); - return () => clearInterval(interval); - }), - shouldRepeat: () => false, - }}/> -
-)); +export default { + title: 'LogsViewer', +}; + +export const Default = () => ( +
+ new Observable((observer) => { + const interval = setInterval(() => observer.next('test\n'), 1000); + return () => clearInterval(interval); + }), + shouldRepeat: () => false, + }}/> +
+); +Default.story = { + name: 'default', +}; diff --git a/stories/notifications.tsx b/stories/notifications.tsx index 939ccc75..26211aa0 100644 --- a/stories/notifications.tsx +++ b/stories/notifications.tsx @@ -1,4 +1,3 @@ -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import { NotificationType } from '../src/components/notifications/notifications'; @@ -15,20 +14,25 @@ function getMessage() { return messages[Math.floor(Math.random() * messages.length)]; } -storiesOf('Notifications', module) - .add('default', () => ( - - {(apis) => ( - [ - {type: NotificationType.Success, title: 'Success'}, - {type: NotificationType.Warning, title: 'Warning'}, - {type: NotificationType.Error, title: 'Error'}, - ].map((item) => ( - - )) - )} - - )); +export default { + title: 'Notifications', +}; + +export const Default = () => ( + + {(apis) => [ + {type: NotificationType.Success, title: 'Success'}, + {type: NotificationType.Warning, title: 'Warning'}, + {type: NotificationType.Error, title: 'Error'}, + ].map((item) => ( + + ))} + +); +Default.story = { + name: 'default', +}; diff --git a/stories/page.tsx b/stories/page.tsx index 6e86c55e..79b66de4 100644 --- a/stories/page.tsx +++ b/stories/page.tsx @@ -1,4 +1,3 @@ -import { storiesOf } from '@storybook/react'; import createHistory from 'history/createBrowserHistory'; import * as React from 'react'; import { Route, Router } from 'react-router'; @@ -54,33 +53,41 @@ function ensureSelected(vals: string[], selected: string[]): string[] { return Array.from(res); } -storiesOf('Page', module) - .add('default', () => { - const [selectedFilter, setSelectedFilter] = React.useState([]); - return +export default { + title: 'Page', +}; + +export const Default = () => { + const [selectedFilter, setSelectedFilter] = React.useState([]); + return ( + - ( - - Filter type one: changeSelection(ensureSelected(['1', '2'], selectedFilter))}>all - - )}, - {label: 'filter 1', value: '1' }, - {label: 'filter 2', value: '2' }, - { content: (changeSelection) => ( - - Filter type two: changeSelection(ensureSelected(['3', '4'], selectedFilter))}>all - - )}, - {label: 'filter 3', value: '3' }, - {label: 'filter 4', value: '4' }, + { + content: (changeSelection) => ( + + Filter type one: changeSelection(ensureSelected(['1', '2'], selectedFilter))}>all + + ), + }, + { label: 'filter 1', value: '1' }, + { label: 'filter 2', value: '2' }, + { + content: (changeSelection) => ( + + Filter type two: changeSelection(ensureSelected(['3', '4'], selectedFilter))}>all + + ), + }, + { label: 'filter 3', value: '3' }, + { label: 'filter 4', value: '4' }, ], selectedValues: selectedFilter, selectionChanged: setSelectedFilter, }}}> -
+
Hello world!
@@ -89,12 +96,42 @@ storiesOf('Page', module) - }).add('dynamic toolbar', () => ( + ) +}; +Default.story = { + name: 'default', +}; + +export const DynamicToolbar = () => ( + + + + ({breadcrumbs: [ + { title: 'hello ' + new Date().toLocaleTimeString() }, + ]})))}> +
+
Hello world!
+
+
+
+
+
+); +DynamicToolbar.story = { + name: 'dynamic toolbar', +}; + +export const CompactNavBar = () => { + const manyNavItems = []; + for (let i = 0; i < 10; i++) { + manyNavItems.push({path: location.pathname + '/' + i, title: 'Sample', iconClassName: 'argo-icon-docs'}); + } + return ( - - ({ breadcrumbs: [{title: 'hello ' + new Date().toLocaleTimeString()}] })))}> -
+ + +
Hello world!
@@ -103,52 +140,49 @@ storiesOf('Page', module) - )).add('compact nav bar', () => { - const manyNavItems = []; - for (let i = 0; i < 10; i++) { - manyNavItems.push({ path: location.pathname + '/' + i, title: 'Sample', iconClassName: 'argo-icon-docs' }); - } - return ( - - - - -
-
- Hello world! -
-
-
-
-
-
- ); - }).add('custom top bar title', () => ( - - - - -
-
- Test -
+ ); +}; +CompactNavBar.story = { + name: 'compact nav bar', +}; + +export const CustomTopBarTitle = () => ( + + + + +
+
+ Test
- - - - - )).add('background color', () => ( - - - - -
-
- Hello world! -
+
+
+
+
+
+); +CustomTopBarTitle.story = { + name: 'custom top bar title', +}; + +export const BackgroundColor = () => ( + + + + +
+
+ Hello world!
- - - - - )); +
+
+
+
+
+); +BackgroundColor.story = { + name: 'background color', +}; diff --git a/stories/popup.tsx b/stories/popup.tsx index da6124c7..c6b6eff5 100644 --- a/stories/popup.tsx +++ b/stories/popup.tsx @@ -1,29 +1,36 @@ import { action } from '@storybook/addon-actions'; -import { storiesOf } from '@storybook/react'; import * as React from 'react'; -import { Checkbox as ReactCheckbox} from 'react-form'; +import { Checkbox as ReactCheckbox } from 'react-form'; import { Text } from 'react-form'; import { Checkbox } from '../src/components/checkbox'; import { FormField } from '../src/components/form-field/form-field'; import { App } from './utils'; -storiesOf('Popup', module) - .add('confirmation', () => ( +export default { + title: 'Popup', +}; + +export const Confirmation = () => ( + + {(apis) => ( + + )} + +); +Confirmation.story = { + name: 'confirmation', +}; + +export const ConfirmationWithCustomFormInside = () => { + const [checked, setChecked] = React.useState(false); + return ( {(apis) => ( - - )} - - )).add('confirmation with custom form inside', () => { - const [checked, setChecked] = React.useState(false); - return ( - - {(apis) => ( -
+

Checked?: {JSON.stringify(checked)}

-
- )} - - ) - }).add('prompt', () => ( - - {(apis) => ( -
+ )} +
+ ) +}; +ConfirmationWithCustomFormInside.story = { + name: 'confirmation with custom form inside', +}; + +export const Prompt = () => ( + + {(apis) => ( + - )} - - )).add('prompt with custom submit', () => ( - - {(apis) => ( - + )} + +); +Prompt.story = { + name: 'prompt', +}; + +export const PromptWithCustomSubmit = () => ( + + {(apis) => ( + - )} - - )).add('prompt with red title and icon, with custom submit', () => ( - - {(apis) => ( - + )} + +); +PromptWithCustomSubmit.story = { + name: 'prompt with custom submit', +}; + +export const PromptWithRedTitleAndIconWithCustomSubmit = () => ( + + {(apis) => ( + - )} - - )).add('prompt with yellow title and icon, three fields and custom submit. Vertical center layout of icon', () => ( - - {(apis) => ( - + )} + +); +PromptWithRedTitleAndIconWithCustomSubmit.story = { + name: 'prompt with red title and icon, with custom submit', +}; + +export const PromptWithYellowTitleAndIconThreeFieldsAndCustomSubmitVerticalCenterLayoutOfIcon = () => ( + + {(apis) => ( + - )} - - )).add('prompt with green clock icon and custom submit', () => ( - - {(apis) => ( - + )} + +); +PromptWithYellowTitleAndIconThreeFieldsAndCustomSubmitVerticalCenterLayoutOfIcon.story = { + name: 'prompt with yellow title and icon, three fields and custom submit. Vertical center layout of icon', +}; + +export const PromptWithGreenClockIconAndCustomSubmit = () => ( + + {(apis) => ( + - )} - - )).add('prompt with just headers and paragraphs', () => ( - - {(apis) => ( - + )} + +); +PromptWithGreenClockIconAndCustomSubmit.story = { + name: 'prompt with green clock icon and custom submit', +}; + +export const PromptWithJustHeadersAndParagraphs = () => ( + + {(apis) => ( + + )} + +); +PromptWithJustHeadersAndParagraphs.story = { + name: 'prompt with just headers and paragraphs', +}; + +export const PromptWithOnlyParagraphsAdditionalTopPaddingIsOptionalForTheFirstParagraph = () => ( + + {(apis) => ( + + )} + +); +PromptWithOnlyParagraphsAdditionalTopPaddingIsOptionalForTheFirstParagraph.story = { + name: 'prompt with only paragraphs. Additional top padding is optional for the first paragraph', +}; + +export const PromptWithReactCheckboxThatIsCheckedByDefaultUsernameDefaultSetToAdmin = () => ( + + {(apis) => ( + - )} - - )).add('prompt with only paragraphs. Additional top padding is optional for the first paragraph', () => ( - - {(apis) => ( - - )} - - )).add('prompt with React Checkbox that is checked by default; Username default set to admin', () => ( - - {(apis) => ( - - )} - - )); +
+ {' '} + +
+ + ), { + validate: (vals) => ({ + username: !vals.username && 'Username is required', + password: !vals.password && 'Password is required', + }), + submit: (vals, api, close) => { + if (vals.username === 'admin' && vals.password === 'test') { + close(); + action('Prompt values')(vals); + } else { + api.setError('password', 'Username or password is invalid'); + } + }, + }, + undefined, + undefined, + { checkboxField: true, username: 'admin' }); + action('Prompt values')(values); + }}>Click me + )} + +); +PromptWithReactCheckboxThatIsCheckedByDefaultUsernameDefaultSetToAdmin.story = { + name: 'prompt with React Checkbox that is checked by default; Username default set to admin', +}; diff --git a/stories/select.tsx b/stories/select.tsx index 4b2fe51e..0e0ef0b2 100644 --- a/stories/select.tsx +++ b/stories/select.tsx @@ -1,12 +1,14 @@ -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import { Select } from '../src/components/select/select'; -storiesOf('Select', module) - .add('default', () => { - const [selected, setSelected] = React.useState('option1'); - return ( +export default { + title: 'Select', +}; + +export const Default = () => { + const [selected, setSelected] = React.useState('option1'); + return (

Selected option value: {selected} @@ -19,10 +21,15 @@ storiesOf('Select', module) onChange={(option) => setSelected(option.value)} />

- )}, - ).add('multi-select', () => { - const [selected, setSelected] = React.useState(['option1']); - return ( + ) +}; +Default.story = { + name: 'default', +}; + +export const MultiSelect = () => { + const [selected, setSelected] = React.useState(['option1']); + return (