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

Docs: Created ArgTypes component and stories #20664

Merged
merged 10 commits into from
Jan 20, 2023
106 changes: 106 additions & 0 deletions code/ui/blocks/src/blocks/ArgTypes.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';

import { ArgTypes } from './ArgTypes';
import * as ButtonStories from '../examples/Button.stories';

const meta: Meta<typeof ArgTypes> = {
title: 'Blocks/ArgTypes',
tmeasday marked this conversation as resolved.
Show resolved Hide resolved
component: ArgTypes,
parameters: {
relativeCsfPaths: ['../examples/Button.stories', '../blocks/ArgTypes.stories'],
},
};
export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {};

export const OfComponent: Story = {
args: {
of: ButtonStories.default.component,
},
};

export const OfMeta: Story = {
args: {
of: ButtonStories.default,
},
};

export const OfStory: Story = {
args: {
of: ButtonStories.Primary,
},
};

// NOTE: this will throw with no of prop
export const OfStoryUnattached: Story = {
parameters: { attached: false },
args: {
of: ButtonStories.Primary,
},
};

export const Simple = {
tmeasday marked this conversation as resolved.
Show resolved Hide resolved
render: () => <div>Story for reference</div>,
argTypes: {
a: { type: { name: 'string' }, name: 'A', description: 'a' },
b: { type: { name: 'string', required: true }, name: 'B', description: 'b' },
},
};

export const IncludeProp: Story = {
args: {
of: Simple,
include: ['A'],
},
};

export const SimpleInclude = {
...Simple,
parameters: { docs: { argTypes: { include: ['A'] } } },
};

export const IncludeParameter: Story = {
args: {
of: SimpleInclude,
},
};

export const ExcludeProp: Story = {
tmeasday marked this conversation as resolved.
Show resolved Hide resolved
args: {
of: Simple,
exclude: ['A'],
},
};

export const SimpleExclude = {
...Simple,
parameters: { docs: { argTypes: { exclude: ['A'] } } },
};

export const ExcludeParameter: Story = {
args: {
of: SimpleExclude,
},
};

export const SortProp: Story = {
tmeasday marked this conversation as resolved.
Show resolved Hide resolved
args: {
of: Simple,
sort: 'requiredFirst',
},
};

export const SimpleSort = {
...Simple,
parameters: { docs: { argTypes: { sort: 'requiredFirst' } } },
};

export const SortParameter: Story = {
args: {
of: SimpleSort,
},
};
81 changes: 81 additions & 0 deletions code/ui/blocks/src/blocks/ArgTypes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* eslint-disable react/destructuring-assignment */
import type { Parameters, Renderer, StrictArgTypes } from '@storybook/csf';
import type { ModuleExports } from '@storybook/types';
import type { FC } from 'react';
import type { PropDescriptor } from '@storybook/preview-api';
import { combineParameters, filterArgTypes } from '@storybook/preview-api';
import type { ArgTypesExtractor } from '@storybook/docs-tools';
import React from 'react';

import type { SortType } from '../components';
import { ArgsTable as PureArgsTable, ArgsTableError } from '../components';
import { useOf } from './useOf';

type ArgTypesParameters = {
include?: PropDescriptor;
exclude?: PropDescriptor;
sort?: SortType;
};

type ArgTypesProps = ArgTypesParameters & {
of: Renderer['component'] | ModuleExports;
};

// TODO: generalize
function extractComponentArgTypes(
component: Renderer['component'],
parameters: Parameters
): StrictArgTypes {
const { extractArgTypes }: { extractArgTypes: ArgTypesExtractor } = parameters.docs || {};
if (!extractArgTypes) {
throw new Error(ArgsTableError.ARGS_UNSUPPORTED);
}
return extractArgTypes(component);
}

function getArgTypesFromResolved(resolved: ReturnType<typeof useOf>, props: ArgTypesProps) {
if (resolved.type === 'component') {
const {
component,
projectAnnotations: { parameters },
} = resolved;
return {
argTypes: extractComponentArgTypes(component, parameters),
parameters,
};
}

if (resolved.type === 'meta') {
const {
preparedMeta: { component, argTypes, parameters },
} = resolved;
const componentArgTypes = component && extractComponentArgTypes(component, parameters);
const metaArgTypes = filterArgTypes(argTypes, props.include, props.exclude);
return {
argTypes: combineParameters(componentArgTypes, metaArgTypes) as StrictArgTypes,
tmeasday marked this conversation as resolved.
Show resolved Hide resolved
parameters,
};
}

// In the case of the story, the enhanceArgs argTypeEnhancer has already added the extracted
// arg types from the component to the prepared story.
const {
story: { argTypes, parameters },
} = resolved;
return { argTypes, parameters };
}

export const ArgTypes: FC<ArgTypesProps> = (props) => {
const { of } = props;
const resolved = useOf(of || 'meta');
const { argTypes, parameters } = getArgTypesFromResolved(resolved, props);
const argTypesParameters = parameters.docs?.argTypes || ({} as ArgTypesParameters);

const include = props.include ?? argTypesParameters.include;
const exclude = props.exclude ?? argTypesParameters.exclude;
const sort = props.sort ?? argTypesParameters.sort;

const filteredArgTypes = filterArgTypes(argTypes, include, exclude);

return <PureArgsTable rows={filteredArgTypes} sort={sort} />;
};
1 change: 1 addition & 0 deletions code/ui/blocks/src/blocks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { ColorPalette, ColorItem, IconGallery, IconItem, Typeset } from '../components';

export * from './Anchor';
export * from './ArgTypes';
export * from './ArgsTable';
// eslint-disable-next-line import/export
export * from './Canvas';
Expand Down
16 changes: 16 additions & 0 deletions code/ui/blocks/src/examples/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ const meta = {
tags: ['autodocs'],
argTypes: {
backgroundColor: { control: 'color' },
// @ts-expect-error Meta type is trying to force us to use real props as args
extraMetaArgType: {
type: { name: 'string' },
name: 'Extra Meta',
description: 'An extra argtype added at the meta level',
table: { defaultValue: { summary: "'a default value'" } },
},
},
parameters: {
// Stop *this* story from being stacked in Chromatic
Expand All @@ -36,6 +43,15 @@ export const Primary: Story = {
primary: true,
label: 'Button',
},
argTypes: {
// @ts-expect-error Story type is trying to force us to use real props as args
extraStoryArgType: {
type: { name: 'string' },
name: 'Extra Story',
description: 'An extra argtype added at the story level',
table: { defaultValue: { summary: "'a default value'" } },
},
},
};

export const Secondary: Story = {
Expand Down