Skip to content

Commit

Permalink
chore: Default config for storybook-controls, add `storybook-action…
Browse files Browse the repository at this point in the history
…s` (#49239)

* Set some defaults for `storybook-controls` to prevent `userContext`
  Decorator showing as a Control for all Stories
* Add `@storybook/addon-actions` for displaying callbacks in UI, add to
  `shared/controls/*` stories
* Tidy some incorrect types/controls for `shared/controls/*` stories
  • Loading branch information
kiosion authored Nov 25, 2024
1 parent 864c057 commit c3c0381
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 53 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
},
"devDependencies": {
"@gravitational/build": "workspace:*",
"@storybook/addon-actions": "^8.3.4",
"@storybook/addon-controls": "^8.3.4",
"@storybook/addon-toolbars": "^8.3.4",
"@storybook/components": "^8.3.4",
"@storybook/preview-api": "^8.3.4",
"@storybook/react": "^8.3.4",
"@storybook/react-vite": "^8.3.4",
"@storybook/test-runner": "^0.19.1",
Expand Down
50 changes: 40 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion web/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ const config: StorybookConfig = {
options: { builder: { viteConfigPath: 'web/.storybook/vite.config.mts' } },
},
staticDirs: ['public'],
addons: ['@storybook/addon-toolbars', '@storybook/addon-controls'],
addons: [
'@storybook/addon-toolbars',
'@storybook/addon-controls',
'@storybook/addon-actions',
],
};

export default config;
2 changes: 2 additions & 0 deletions web/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ const preview: Preview = {
order: ['Teleport', 'TeleportE', 'Teleterm', 'Design', 'Shared'],
},
},
controls: { expanded: true, disableSaveFromUI: true },
},
argTypes: { userContext: { table: { disable: true } } },
loaders: [mswLoader],
decorators: [
(Story, meta) => (
Expand Down
9 changes: 3 additions & 6 deletions web/packages/design/src/Alert/Alert.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import React from 'react';
import { action } from '@storybook/addon-actions';

import { Restore } from 'design/Icon';

Expand Down Expand Up @@ -119,14 +120,10 @@ const commonProps: AlertProps = {
dismissible: true,
primaryAction: {
content: 'Primary Action',
onClick: () => {
alert('Primary button clicked');
},
onClick: action('primaryAction.onClick'),
},
secondaryAction: {
content: 'Secondary Action',
onClick: () => {
alert('Secondary button clicked');
},
onClick: action('secondaryAction.onClick'),
},
};
18 changes: 13 additions & 5 deletions web/packages/shared/components/Controls/MultiselectMenu.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
import { useArgs } from '@storybook/preview-api';
import { Flex } from 'design';

import { MultiselectMenu } from './MultiselectMenu';

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

type OptionValue = `option-${number}`;

const options: {
value: OptionValue;
label: string | React.ReactNode;
label: string | ReactNode;
disabled?: boolean;
disabledTooltip?: string;
}[] = [
Expand Down Expand Up @@ -99,16 +101,22 @@ export default {
args: {
label: 'Select Options',
tooltip: 'Choose multiple options',
selected: [],
buffered: false,
showIndicator: true,
showSelectControls: true,
onChange: action('onChange'),
},
parameters: { controls: { expanded: true, exclude: ['userContext'] } },
render: (args => {
const [selected, setSelected] = useState<string[]>([]);
const [{ selected }, updateArgs] =
useArgs<Meta<typeof MultiselectMenu<OptionValue>>['args']>();
const onChange = (value: OptionValue[]) => {
updateArgs({ selected: value });
args.onChange?.(value);
};
return (
<Flex alignItems="center" minHeight="100px">
<MultiselectMenu {...args} selected={selected} onChange={setSelected} />
<MultiselectMenu {...args} selected={selected} onChange={onChange} />
</Flex>
);
}) satisfies StoryFn<typeof MultiselectMenu<OptionValue>>,
Expand Down
54 changes: 36 additions & 18 deletions web/packages/shared/components/Controls/SortMenu.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
import { useArgs } from '@storybook/preview-api';
import { Flex } from 'design';

import { SortMenu } from './SortMenu';

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

const STUB_FIELDS = ['name', 'created', 'updated', 'status'] as const;

export default {
title: 'Shared/Controls/SortMenu',
component: SortMenu<any>,
argTypes: {
current: {
control: false,
control: { type: 'select' },
options: STUB_FIELDS.reduce(
(acc, v) => [...acc, `${v} (Asc)`, `${v} (Desc)`],
[]
),
mapping: STUB_FIELDS.reduce(
(acc, v) => ({
...acc,
[`${v} (Asc)`]: { fieldName: v, dir: 'ASC' },
[`${v} (Desc)`]: { fieldName: v, dir: 'DESC' },
}),
{}
),
description: 'Current sort',
table: {
type: {
summary:
"Array<{ fieldName: Exclude<keyof T, symbol | number>; dir: 'ASC' | 'DESC'>",
"Array<{ fieldName: Exclude<keyof T, symbol | number>; dir: 'ASC' | 'DESC' }>",
},
},
},
Expand All @@ -43,7 +58,7 @@ export default {
table: {
type: {
summary:
'{ value: Exclude<keyof T, symbol | number>; label: string }[]',
'Array<{ value: Exclude<keyof T, symbol | number>; label: string }>',
},
},
},
Expand All @@ -59,25 +74,28 @@ export default {
},
},
args: {
current: { fieldName: 'name', dir: 'ASC' },
fields: [
{ value: 'name', label: 'Name' },
{ value: 'created', label: 'Created' },
{ value: 'updated', label: 'Updated' },
],
current: { fieldName: STUB_FIELDS[0], dir: 'ASC' },
fields: STUB_FIELDS.map(v => ({
value: v,
label: `${v.charAt(0).toUpperCase()}${v.slice(1)}`,
})),
onChange: action('onChange'),
},
parameters: { controls: { expanded: true, exclude: ['userContext'] } },
} satisfies Meta<typeof SortMenu<any>>;

const Default: StoryObj<typeof SortMenu> = {
render: (({ current, fields }) => {
const [sort, setSort] = useState(current);
render: (args => {
const [{ current }, updateArgs] =
useArgs<Meta<typeof SortMenu<any>>['args']>();
const onChange = (value: typeof current) => {
updateArgs({ current: value });
args.onChange?.(value);
};
return (
<Flex alignItems="center" minHeight="100px">
<SortMenu current={sort} fields={fields} onChange={setSort} />
<SortMenu current={current} fields={args.fields} onChange={onChange} />
</Flex>
);
}) satisfies StoryFn<typeof SortMenu>,
};
} satisfies Meta<typeof SortMenu<any>>;

const Default: StoryObj<typeof SortMenu> = { args: {} };

export { Default as SortMenu };
Loading

0 comments on commit c3c0381

Please sign in to comment.