mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-21 05:02:39 +08:00
Merge pull request #11744 from storybookjs/11696-rename-doc-blocks
Addon-docs: Rename Preview/Props to Canvas/ArgsTable
This commit is contained in:
commit
df1b017c69
@ -8,6 +8,7 @@
|
||||
- [Args passed as first argument to story](#args-passed-as-first-argument-to-story)
|
||||
- [6.0 Docs breaking changes](#60-docs-breaking-changes)
|
||||
- [Remove framework-specific docs presets](#remove-framework-specific-docs-presets)
|
||||
- [Preview/Props renamed](#previewprops-renamed)
|
||||
- [Docs theme separated](#docs-theme-separated)
|
||||
- [DocsPage slots removed](#docspage-slots-removed)
|
||||
- [React prop tables with Typescript](#react-prop-tables-with-typescript)
|
||||
@ -227,6 +228,12 @@ export const parameters = {
|
||||
|
||||
In SB 5.2, each framework had its own preset, e.g. `@storybook/addon-docs/react/preset`. In 5.3 we [unified this into a single preset](#unified-docs-preset): `@storybook/addon-docs/preset`. In 6.0 we've removed the deprecated preset.
|
||||
|
||||
#### Preview/Props renamed
|
||||
|
||||
In 6.0 we renamed `Preview` to `Canvas`, `Props` to `ArgsTable`.
|
||||
|
||||
In addition to the rename, `<Props />` shows the current component, whereas `<ArgsTable />` shows the primary story for the current component. If you want the old behavior, pass `<ArgsTable of='.' />`.
|
||||
|
||||
#### Docs theme separated
|
||||
|
||||
In 6.0, you should theme Storybook Docs with the `docs.theme` parameter.
|
||||
|
@ -46,7 +46,7 @@ For more information on how it works, see the [`DocsPage` reference](./docs/docs
|
||||
Here's an example file:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
||||
import { Checkbox } from './Checkbox';
|
||||
|
||||
<Meta title="MDX/Checkbox" component={Checkbox} />
|
||||
@ -56,7 +56,7 @@ import { Checkbox } from './Checkbox';
|
||||
With `MDX` we can define a story for `Checkbox` right in the middle of our
|
||||
markdown documentation.
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="all checkboxes">
|
||||
<form>
|
||||
<Checkbox id="Unchecked" label="Unchecked" />
|
||||
@ -64,7 +64,7 @@ markdown documentation.
|
||||
<Checkbox appearance="secondary" id="second" label="Secondary" checked />
|
||||
</form>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
```
|
||||
|
||||
And here's how that's rendered in Storybook:
|
||||
|
@ -113,7 +113,7 @@ module.exports = {
|
||||
Finally, you can create MDX files like this:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
<Meta title='App Component' component={AppComponent} />
|
||||
@ -127,9 +127,9 @@ Some **markdown** description, or whatever you want.
|
||||
props: {},
|
||||
}}</Story>
|
||||
|
||||
## Props
|
||||
## ArgsTable
|
||||
|
||||
<Props of={AppComponent} />
|
||||
<ArgsTable of={AppComponent} />
|
||||
```
|
||||
|
||||
Yes, it's redundant to declare `component` twice. [Coming soon](https://github.com/storybookjs/storybook/issues/8673).
|
||||
@ -139,7 +139,7 @@ Also, to use the `Props` doc block, you need to set up Compodoc, [as described a
|
||||
When you are using `template`, `moduleMetadata` and/or `addDecorators` with `storiesOf` then you can easily translate your story to MDX, too:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { CheckboxComponent, RadioButtonComponent } from './my-components';
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
|
||||
|
@ -51,7 +51,7 @@ module.exports = {
|
||||
Finally, you can create MDX files like this:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title='App Component' />
|
||||
|
||||
|
@ -142,7 +142,7 @@ export default {
|
||||
<Subtitle />
|
||||
<Description />
|
||||
<Primary />
|
||||
<Props />
|
||||
<ArgsTable />
|
||||
<Stories />
|
||||
</>
|
||||
),
|
||||
|
@ -20,7 +20,7 @@
|
||||
Let's get started with an example that combines markdown with a single story:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
||||
import { Checkbox } from './Checkbox';
|
||||
|
||||
<Meta title="MDX/Checkbox" component={Checkbox} />
|
||||
@ -30,7 +30,7 @@ import { Checkbox } from './Checkbox';
|
||||
With `MDX` we can define a story for `Checkbox` right in the middle of our
|
||||
markdown documentation.
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="all checkboxes">
|
||||
<form>
|
||||
<Checkbox id="Unchecked" label="Unchecked" />
|
||||
@ -38,7 +38,7 @@ markdown documentation.
|
||||
<Checkbox appearance="secondary" id="second" label="Secondary" checked />
|
||||
</form>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
```
|
||||
|
||||
And here's how that's rendered in Storybook:
|
||||
@ -94,19 +94,19 @@ Let's define a story for our `Badge` component:
|
||||
<Badge status="positive">Positive</Badge>
|
||||
</Story>
|
||||
|
||||
We can drop it in a `Preview` to get a code snippet:
|
||||
We can drop it in a `Canvas` to get a code snippet:
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="negative">
|
||||
<Badge status="negative">Negative</Badge>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
We can even preview multiple stories in a block. This
|
||||
gets rendered as a group, but defines individual stories
|
||||
with unique URLs and isolated snapshot tests.
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="warning">
|
||||
<Badge status="warning">Warning</Badge>
|
||||
</Story>
|
||||
@ -122,7 +122,7 @@ with unique URLs and isolated snapshot tests.
|
||||
with icon
|
||||
</Badge>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
```
|
||||
|
||||
And here's how that gets rendered in Storybook:
|
||||
|
@ -47,7 +47,7 @@ import { MyComponent } from './MyComponent';
|
||||
|
||||
# My Component!
|
||||
|
||||
<Props of={MyComponent} />
|
||||
<ArgsTable of={MyComponent} />
|
||||
```
|
||||
|
||||
## Controls
|
||||
@ -80,7 +80,7 @@ export const WithControls = (args) => <MyComponent {...args} />;
|
||||
{args => <MyComponent {...args} />}
|
||||
</Story>
|
||||
|
||||
<Props story="Controls" />
|
||||
<ArgsTable story="Controls" />
|
||||
```
|
||||
|
||||
For a very detailed walkthrough of how to write stories that use controls, see the [addon-controls README](https://github.com/storybookjs/storybook/blob/next/addons/controls/README.md#writing-stories).
|
||||
@ -91,13 +91,13 @@ Props tables are automatically inferred from your components and stories, but so
|
||||
|
||||
Props tables are rendered from an internal data structure called `ArgTypes`. When you declare a story's `component` metadata, Docs automatically extracts `ArgTypes` based on the component's properties.
|
||||
|
||||
You can can customize what's shown in the props table by [customizing the `ArgTypes` data](#customizing-argtypes). This is currently available for `DocsPage` and `<Props story="xxx">` construct, but not for the `<Props of={component} />` construct,
|
||||
You can can customize what's shown in the props table by [customizing the `ArgTypes` data](#customizing-argtypes). This is currently available for `DocsPage` and `<ArgsTable story="xxx">` construct, but not for the `<ArgsTable of={component} />` construct,
|
||||
|
||||
### Customizing ArgTypes
|
||||
|
||||
> **NOTE:** This API is experimental and may change outside of the typical semver release cycle
|
||||
|
||||
When you declare a `component` in for your `DocsPage` [as described above](#docspage) or use the `<Props story="xxx" />` construct [in MDX](#controls), the props table shows the `story.argTypes` that gets extracted by Storybook.
|
||||
When you declare a `component` in for your `DocsPage` [as described above](#docspage) or use the `<ArgsTable story="xxx" />` construct [in MDX](#controls), the props table shows the `story.argTypes` that gets extracted by Storybook.
|
||||
|
||||
Consider the following input:
|
||||
|
||||
|
@ -95,7 +95,7 @@ module.exports = {
|
||||
Finally, you can create MDX files like this:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
<Meta title='App Component' component='AppComponent' />
|
||||
@ -109,9 +109,9 @@ Some **markdown** description, or whatever you want.
|
||||
context: { title: "Title" },
|
||||
}}</Story>
|
||||
|
||||
## Props
|
||||
## ArgsTable
|
||||
|
||||
<Props of='AppComponent' />
|
||||
<ArgsTable of='AppComponent' />
|
||||
```
|
||||
|
||||
Yes, it's redundant to declare `component` twice. [Coming soon](https://github.com/storybookjs/storybook/issues/8673).
|
||||
|
@ -84,7 +84,7 @@ module.exports = {
|
||||
Finally, you can create MDX files like this:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { Button } from './Button';
|
||||
|
||||
<Meta title='Button' component={Button} />
|
||||
@ -97,9 +97,9 @@ Some **markdown** description, or whatever you want.
|
||||
<Button>Label</Button>
|
||||
</Story>
|
||||
|
||||
## Props
|
||||
## ArgsTable
|
||||
|
||||
<Props of={Button} />
|
||||
<ArgsTable of={Button} />
|
||||
```
|
||||
|
||||
## Inline stories
|
||||
|
251
addons/docs/src/blocks/ArgsTable.tsx
Normal file
251
addons/docs/src/blocks/ArgsTable.tsx
Normal file
@ -0,0 +1,251 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import React, { FC, useContext, useEffect, useState, useCallback } from 'react';
|
||||
import mapValues from 'lodash/mapValues';
|
||||
import pickBy from 'lodash/pickBy';
|
||||
import {
|
||||
ArgsTable as PureArgsTable,
|
||||
ArgsTableProps as PureArgsTableProps,
|
||||
ArgsTableError,
|
||||
ArgTypes,
|
||||
TabbedArgsTable,
|
||||
} from '@storybook/components';
|
||||
import { Args } from '@storybook/addons';
|
||||
import { StoryStore } from '@storybook/client-api';
|
||||
import Events from '@storybook/core-events';
|
||||
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { Component, CURRENT_SELECTION, PRIMARY_STORY } from './types';
|
||||
import { getComponentName, getDocsStories } from './utils';
|
||||
import { ArgTypesExtractor } from '../lib/docgen/types';
|
||||
import { lookupStoryId } from './Story';
|
||||
|
||||
type PropDescriptor = string[] | RegExp;
|
||||
|
||||
interface BaseProps {
|
||||
include?: PropDescriptor;
|
||||
exclude?: PropDescriptor;
|
||||
}
|
||||
|
||||
type OfProps = BaseProps & {
|
||||
of: '.' | '^' | Component;
|
||||
};
|
||||
|
||||
type ComponentsProps = BaseProps & {
|
||||
components: {
|
||||
[label: string]: Component;
|
||||
};
|
||||
};
|
||||
|
||||
type StoryProps = BaseProps & {
|
||||
story: '.' | '^' | string;
|
||||
showComponent?: boolean;
|
||||
};
|
||||
|
||||
type ArgsTableProps = BaseProps | OfProps | ComponentsProps | StoryProps;
|
||||
|
||||
const useArgs = (
|
||||
storyId: string,
|
||||
storyStore: StoryStore
|
||||
): [Args, (args: Args) => void, (argNames?: string[]) => void] => {
|
||||
const story = storyStore.fromId(storyId);
|
||||
if (!story) {
|
||||
throw new Error(`Unknown story: ${storyId}`);
|
||||
}
|
||||
|
||||
const { args: initialArgs } = story;
|
||||
const [args, setArgs] = useState(initialArgs);
|
||||
useEffect(() => {
|
||||
const cb = (changed: { storyId: string; args: Args }) => {
|
||||
if (changed.storyId === storyId) {
|
||||
setArgs(changed.args);
|
||||
}
|
||||
};
|
||||
storyStore._channel.on(Events.STORY_ARGS_UPDATED, cb);
|
||||
return () => storyStore._channel.off(Events.STORY_ARGS_UPDATED, cb);
|
||||
}, [storyId]);
|
||||
const updateArgs = useCallback((newArgs) => storyStore.updateStoryArgs(storyId, newArgs), [
|
||||
storyId,
|
||||
]);
|
||||
const resetArgs = useCallback(
|
||||
(argNames?: string[]) => storyStore.resetStoryArgs(storyId, argNames),
|
||||
[storyId]
|
||||
);
|
||||
return [args, updateArgs, resetArgs];
|
||||
};
|
||||
|
||||
const matches = (name: string, descriptor: PropDescriptor) =>
|
||||
Array.isArray(descriptor) ? descriptor.includes(name) : name.match(descriptor);
|
||||
|
||||
const filterArgTypes = (argTypes: ArgTypes, include?: PropDescriptor, exclude?: PropDescriptor) => {
|
||||
if (!include && !exclude) {
|
||||
return argTypes;
|
||||
}
|
||||
return (
|
||||
argTypes &&
|
||||
pickBy(argTypes, (argType, key) => {
|
||||
const name = argType.name || key;
|
||||
return (!include || matches(name, include)) && (!exclude || !matches(name, exclude));
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const extractComponentArgTypes = (
|
||||
component: Component,
|
||||
{ parameters }: DocsContextProps,
|
||||
include?: PropDescriptor,
|
||||
exclude?: PropDescriptor
|
||||
): ArgTypes => {
|
||||
const params = parameters || {};
|
||||
const { extractArgTypes }: { extractArgTypes: ArgTypesExtractor } = params.docs || {};
|
||||
if (!extractArgTypes) {
|
||||
throw new Error(ArgsTableError.ARGS_UNSUPPORTED);
|
||||
}
|
||||
let argTypes = extractArgTypes(component);
|
||||
argTypes = filterArgTypes(argTypes, include, exclude);
|
||||
|
||||
return argTypes;
|
||||
};
|
||||
|
||||
const isShortcut = (value?: string) => {
|
||||
return value && [CURRENT_SELECTION, PRIMARY_STORY].includes(value);
|
||||
};
|
||||
|
||||
export const getComponent = (props: ArgsTableProps = {}, context: DocsContextProps): Component => {
|
||||
const { of } = props as OfProps;
|
||||
const { story } = props as StoryProps;
|
||||
const { parameters = {} } = context;
|
||||
const { component } = parameters;
|
||||
if (isShortcut(of) || isShortcut(story)) {
|
||||
return component || null;
|
||||
}
|
||||
if (!of) {
|
||||
throw new Error(ArgsTableError.NO_COMPONENT);
|
||||
}
|
||||
return of;
|
||||
};
|
||||
|
||||
const addComponentTabs = (
|
||||
tabs: Record<string, PureArgsTableProps>,
|
||||
components: Record<string, Component>,
|
||||
context: DocsContextProps,
|
||||
include?: PropDescriptor,
|
||||
exclude?: PropDescriptor
|
||||
) => ({
|
||||
...tabs,
|
||||
...mapValues(components, (comp) => ({
|
||||
rows: extractComponentArgTypes(comp, context, include, exclude),
|
||||
})),
|
||||
});
|
||||
|
||||
export const StoryTable: FC<
|
||||
StoryProps & { component: Component; subcomponents: Record<string, Component> }
|
||||
> = (props) => {
|
||||
const context = useContext(DocsContext);
|
||||
const {
|
||||
id: currentId,
|
||||
parameters: { argTypes },
|
||||
storyStore,
|
||||
} = context;
|
||||
const { story, component, subcomponents, showComponent, include, exclude } = props;
|
||||
let storyArgTypes;
|
||||
try {
|
||||
let storyId;
|
||||
switch (story) {
|
||||
case CURRENT_SELECTION: {
|
||||
storyId = currentId;
|
||||
storyArgTypes = argTypes;
|
||||
break;
|
||||
}
|
||||
case PRIMARY_STORY: {
|
||||
const primaryStory = getDocsStories(context)[0];
|
||||
storyId = primaryStory.id;
|
||||
storyArgTypes = primaryStory.parameters.argTypes;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
storyId = lookupStoryId(story, context);
|
||||
const data = storyStore.fromId(storyId);
|
||||
storyArgTypes = data.parameters.argTypes;
|
||||
}
|
||||
}
|
||||
storyArgTypes = filterArgTypes(storyArgTypes, include, exclude);
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [args, updateArgs, resetArgs] = useArgs(storyId, storyStore);
|
||||
let tabs = { Story: { rows: storyArgTypes, args, updateArgs, resetArgs } } as Record<
|
||||
string,
|
||||
PureArgsTableProps
|
||||
>;
|
||||
|
||||
// Use the dynamically generated component tabs if there are no controls
|
||||
const storyHasArgsWithControls =
|
||||
storyArgTypes && Object.values(storyArgTypes).find((v) => !!v?.control);
|
||||
|
||||
if (!storyHasArgsWithControls) {
|
||||
updateArgs = null;
|
||||
resetArgs = null;
|
||||
tabs = {};
|
||||
}
|
||||
|
||||
if (component && (!storyHasArgsWithControls || showComponent)) {
|
||||
const mainLabel = getComponentName(component);
|
||||
tabs = addComponentTabs(tabs, { [mainLabel]: component }, context, include, exclude);
|
||||
}
|
||||
|
||||
if (subcomponents) {
|
||||
tabs = addComponentTabs(tabs, subcomponents, context, include, exclude);
|
||||
}
|
||||
return <TabbedArgsTable tabs={tabs} />;
|
||||
} catch (err) {
|
||||
return <PureArgsTable error={err.message} />;
|
||||
}
|
||||
};
|
||||
|
||||
export const ComponentsTable: FC<ComponentsProps> = (props) => {
|
||||
const context = useContext(DocsContext);
|
||||
const { components, include, exclude } = props;
|
||||
|
||||
const tabs = addComponentTabs({}, components, context, include, exclude);
|
||||
return <TabbedArgsTable tabs={tabs} />;
|
||||
};
|
||||
|
||||
export const ArgsTable: FC<ArgsTableProps> = (props) => {
|
||||
const context = useContext(DocsContext);
|
||||
const {
|
||||
parameters: { subcomponents },
|
||||
} = context;
|
||||
|
||||
const { include, exclude, components } = props as ComponentsProps;
|
||||
const { story } = props as StoryProps;
|
||||
|
||||
const main = getComponent(props, context);
|
||||
if (story) {
|
||||
return <StoryTable {...(props as StoryProps)} component={main} subcomponents={subcomponents} />;
|
||||
}
|
||||
|
||||
if (!components && !subcomponents) {
|
||||
let mainProps;
|
||||
try {
|
||||
mainProps = { rows: extractComponentArgTypes(main, context, include, exclude) };
|
||||
} catch (err) {
|
||||
mainProps = { error: err.message };
|
||||
}
|
||||
return <PureArgsTable {...mainProps} />;
|
||||
}
|
||||
|
||||
if (components) {
|
||||
return <ComponentsTable {...(props as ComponentsProps)} components={components} />;
|
||||
}
|
||||
|
||||
const mainLabel = getComponentName(main);
|
||||
return (
|
||||
<ComponentsTable
|
||||
{...(props as ComponentsProps)}
|
||||
components={{ [mainLabel]: main, ...subcomponents }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ArgsTable.defaultProps = {
|
||||
story: PRIMARY_STORY,
|
||||
};
|
71
addons/docs/src/blocks/Canvas.tsx
Normal file
71
addons/docs/src/blocks/Canvas.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import React, { FC, ReactElement, ReactNode, ReactNodeArray, useContext } from 'react';
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { toId, storyNameFromExport } from '@storybook/csf';
|
||||
import { resetComponents } from '@storybook/components/html';
|
||||
import { Preview as PurePreview, PreviewProps as PurePreviewProps } from '@storybook/components';
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { SourceContext, SourceContextProps } from './SourceContainer';
|
||||
import { getSourceProps } from './Source';
|
||||
|
||||
export enum SourceState {
|
||||
OPEN = 'open',
|
||||
CLOSED = 'closed',
|
||||
NONE = 'none',
|
||||
}
|
||||
|
||||
type CanvasProps = PurePreviewProps & {
|
||||
withSource?: SourceState;
|
||||
mdxSource?: string;
|
||||
};
|
||||
|
||||
const getPreviewProps = (
|
||||
{
|
||||
withSource = SourceState.CLOSED,
|
||||
mdxSource,
|
||||
children,
|
||||
...props
|
||||
}: CanvasProps & { children?: ReactNode },
|
||||
docsContext: DocsContextProps,
|
||||
sourceContext: SourceContextProps
|
||||
): PurePreviewProps => {
|
||||
if (withSource === SourceState.NONE) {
|
||||
return props;
|
||||
}
|
||||
if (mdxSource) {
|
||||
return {
|
||||
...props,
|
||||
withSource: getSourceProps({ code: decodeURI(mdxSource) }, docsContext, sourceContext),
|
||||
};
|
||||
}
|
||||
const childArray: ReactNodeArray = Array.isArray(children) ? children : [children];
|
||||
const stories = childArray.filter(
|
||||
(c: ReactElement) => c.props && (c.props.id || c.props.name)
|
||||
) as ReactElement[];
|
||||
const { mdxComponentMeta, mdxStoryNameToKey } = docsContext;
|
||||
const targetIds = stories.map(
|
||||
(s) =>
|
||||
s.props.id ||
|
||||
toId(
|
||||
mdxComponentMeta.id || mdxComponentMeta.title,
|
||||
storyNameFromExport(mdxStoryNameToKey[s.props.name])
|
||||
)
|
||||
);
|
||||
const sourceProps = getSourceProps({ ids: targetIds }, docsContext, sourceContext);
|
||||
return {
|
||||
...props, // pass through columns etc.
|
||||
withSource: sourceProps,
|
||||
isExpanded: withSource === SourceState.OPEN,
|
||||
};
|
||||
};
|
||||
|
||||
export const Canvas: FC<CanvasProps> = (props) => {
|
||||
const docsContext = useContext(DocsContext);
|
||||
const sourceContext = useContext(SourceContext);
|
||||
const previewProps = getPreviewProps(props, docsContext, sourceContext);
|
||||
const { children } = props;
|
||||
return (
|
||||
<MDXProvider components={resetComponents}>
|
||||
<PurePreview {...previewProps}>{children}</PurePreview>
|
||||
</MDXProvider>
|
||||
);
|
||||
};
|
@ -3,9 +3,8 @@ import { Title } from './Title';
|
||||
import { Subtitle } from './Subtitle';
|
||||
import { Description } from './Description';
|
||||
import { Primary } from './Primary';
|
||||
import { Props } from './Props';
|
||||
import { ArgsTable } from './ArgsTable';
|
||||
import { Stories } from './Stories';
|
||||
import { PRIMARY_STORY } from './types';
|
||||
|
||||
export const DocsPage: FC = () => (
|
||||
<>
|
||||
@ -13,7 +12,7 @@ export const DocsPage: FC = () => (
|
||||
<Subtitle />
|
||||
<Description />
|
||||
<Primary />
|
||||
<Props story={PRIMARY_STORY} />
|
||||
<ArgsTable />
|
||||
<Stories />
|
||||
</>
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import { DocsStoryProps } from './types';
|
||||
import { Anchor } from './Anchor';
|
||||
import { Description } from './Description';
|
||||
import { Story } from './Story';
|
||||
import { Preview } from './Preview';
|
||||
import { Canvas } from './Canvas';
|
||||
|
||||
export const DocsStory: FunctionComponent<DocsStoryProps> = ({
|
||||
id,
|
||||
@ -18,8 +18,8 @@ export const DocsStory: FunctionComponent<DocsStoryProps> = ({
|
||||
{expanded && parameters && parameters.docs && parameters.docs.storyDescription && (
|
||||
<Description markdown={parameters.docs.storyDescription} />
|
||||
)}
|
||||
<Preview withToolbar={withToolbar}>
|
||||
<Canvas withToolbar={withToolbar}>
|
||||
<Story id={id} />
|
||||
</Preview>
|
||||
</Canvas>
|
||||
</Anchor>
|
||||
);
|
||||
|
@ -1,71 +1,13 @@
|
||||
import React, { FC, ReactElement, ReactNode, ReactNodeArray, useContext } from 'react';
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { toId, storyNameFromExport } from '@storybook/csf';
|
||||
import { resetComponents } from '@storybook/components/html';
|
||||
import { Preview as PurePreview, PreviewProps as PurePreviewProps } from '@storybook/components';
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { SourceContext, SourceContextProps } from './SourceContainer';
|
||||
import { getSourceProps } from './Source';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import deprecate from 'util-deprecate';
|
||||
import dedent from 'ts-dedent';
|
||||
import { Canvas } from './Canvas';
|
||||
|
||||
export enum SourceState {
|
||||
OPEN = 'open',
|
||||
CLOSED = 'closed',
|
||||
NONE = 'none',
|
||||
}
|
||||
export const Preview = deprecate(
|
||||
(props: ComponentProps<typeof Canvas>) => <Canvas {...props} />,
|
||||
dedent`
|
||||
Preview doc block has been renamed to Canvas.
|
||||
|
||||
type PreviewProps = PurePreviewProps & {
|
||||
withSource?: SourceState;
|
||||
mdxSource?: string;
|
||||
};
|
||||
|
||||
const getPreviewProps = (
|
||||
{
|
||||
withSource = SourceState.CLOSED,
|
||||
mdxSource,
|
||||
children,
|
||||
...props
|
||||
}: PreviewProps & { children?: ReactNode },
|
||||
docsContext: DocsContextProps,
|
||||
sourceContext: SourceContextProps
|
||||
): PurePreviewProps => {
|
||||
if (withSource === SourceState.NONE) {
|
||||
return props;
|
||||
}
|
||||
if (mdxSource) {
|
||||
return {
|
||||
...props,
|
||||
withSource: getSourceProps({ code: decodeURI(mdxSource) }, docsContext, sourceContext),
|
||||
};
|
||||
}
|
||||
const childArray: ReactNodeArray = Array.isArray(children) ? children : [children];
|
||||
const stories = childArray.filter(
|
||||
(c: ReactElement) => c.props && (c.props.id || c.props.name)
|
||||
) as ReactElement[];
|
||||
const { mdxComponentMeta, mdxStoryNameToKey } = docsContext;
|
||||
const targetIds = stories.map(
|
||||
(s) =>
|
||||
s.props.id ||
|
||||
toId(
|
||||
mdxComponentMeta.id || mdxComponentMeta.title,
|
||||
storyNameFromExport(mdxStoryNameToKey[s.props.name])
|
||||
)
|
||||
);
|
||||
const sourceProps = getSourceProps({ ids: targetIds }, docsContext, sourceContext);
|
||||
return {
|
||||
...props, // pass through columns etc.
|
||||
withSource: sourceProps,
|
||||
isExpanded: withSource === SourceState.OPEN,
|
||||
};
|
||||
};
|
||||
|
||||
export const Preview: FC<PreviewProps> = (props) => {
|
||||
const docsContext = useContext(DocsContext);
|
||||
const sourceContext = useContext(SourceContext);
|
||||
const previewProps = getPreviewProps(props, docsContext, sourceContext);
|
||||
const { children } = props;
|
||||
return (
|
||||
<MDXProvider components={resetComponents}>
|
||||
<PurePreview {...previewProps}>{children}</PurePreview>
|
||||
</MDXProvider>
|
||||
);
|
||||
};
|
||||
https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#previewprops-renamed
|
||||
`
|
||||
);
|
||||
|
@ -1,248 +1,19 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import React, { FC, useContext, useEffect, useState, useCallback } from 'react';
|
||||
import mapValues from 'lodash/mapValues';
|
||||
import pickBy from 'lodash/pickBy';
|
||||
import {
|
||||
ArgsTable,
|
||||
ArgsTableProps,
|
||||
ArgsTableError,
|
||||
ArgTypes,
|
||||
TabbedArgsTable,
|
||||
} from '@storybook/components';
|
||||
import { Args } from '@storybook/addons';
|
||||
import { StoryStore } from '@storybook/client-api';
|
||||
import Events from '@storybook/core-events';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import deprecate from 'util-deprecate';
|
||||
import dedent from 'ts-dedent';
|
||||
import { ArgsTable } from './ArgsTable';
|
||||
import { CURRENT_SELECTION } from './types';
|
||||
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { Component, CURRENT_SELECTION, PRIMARY_STORY } from './types';
|
||||
import { getComponentName, getDocsStories } from './utils';
|
||||
import { ArgTypesExtractor } from '../lib/docgen/types';
|
||||
import { lookupStoryId } from './Story';
|
||||
export const Props = deprecate(
|
||||
(props: ComponentProps<typeof ArgsTable>) => <ArgsTable {...props} />,
|
||||
dedent`
|
||||
Props doc block has been renamed to ArgsTable.
|
||||
|
||||
type PropDescriptor = string[] | RegExp;
|
||||
|
||||
interface BaseProps {
|
||||
include?: PropDescriptor;
|
||||
exclude?: PropDescriptor;
|
||||
}
|
||||
|
||||
type OfProps = BaseProps & {
|
||||
of: '.' | Component;
|
||||
};
|
||||
|
||||
type ComponentsProps = BaseProps & {
|
||||
components: {
|
||||
[label: string]: Component;
|
||||
};
|
||||
};
|
||||
|
||||
type StoryProps = BaseProps & {
|
||||
story: '.' | string;
|
||||
showComponent?: boolean;
|
||||
};
|
||||
|
||||
type PropsProps = BaseProps | OfProps | ComponentsProps | StoryProps;
|
||||
|
||||
const useArgs = (
|
||||
storyId: string,
|
||||
storyStore: StoryStore
|
||||
): [Args, (args: Args) => void, (argNames?: string[]) => void] => {
|
||||
const story = storyStore.fromId(storyId);
|
||||
if (!story) {
|
||||
throw new Error(`Unknown story: ${storyId}`);
|
||||
}
|
||||
|
||||
const { args: initialArgs } = story;
|
||||
const [args, setArgs] = useState(initialArgs);
|
||||
useEffect(() => {
|
||||
const cb = (changed: { storyId: string; args: Args }) => {
|
||||
if (changed.storyId === storyId) {
|
||||
setArgs(changed.args);
|
||||
}
|
||||
};
|
||||
storyStore._channel.on(Events.STORY_ARGS_UPDATED, cb);
|
||||
return () => storyStore._channel.off(Events.STORY_ARGS_UPDATED, cb);
|
||||
}, [storyId]);
|
||||
const updateArgs = useCallback((newArgs) => storyStore.updateStoryArgs(storyId, newArgs), [
|
||||
storyId,
|
||||
]);
|
||||
const resetArgs = useCallback(
|
||||
(argNames?: string[]) => storyStore.resetStoryArgs(storyId, argNames),
|
||||
[storyId]
|
||||
);
|
||||
return [args, updateArgs, resetArgs];
|
||||
};
|
||||
|
||||
const matches = (name: string, descriptor: PropDescriptor) =>
|
||||
Array.isArray(descriptor) ? descriptor.includes(name) : name.match(descriptor);
|
||||
|
||||
const filterArgTypes = (argTypes: ArgTypes, include?: PropDescriptor, exclude?: PropDescriptor) => {
|
||||
if (!include && !exclude) {
|
||||
return argTypes;
|
||||
}
|
||||
return (
|
||||
argTypes &&
|
||||
pickBy(argTypes, (argType, key) => {
|
||||
const name = argType.name || key;
|
||||
return (!include || matches(name, include)) && (!exclude || !matches(name, exclude));
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
export const extractComponentArgTypes = (
|
||||
component: Component,
|
||||
{ parameters }: DocsContextProps,
|
||||
include?: PropDescriptor,
|
||||
exclude?: PropDescriptor
|
||||
): ArgTypes => {
|
||||
const params = parameters || {};
|
||||
const { extractArgTypes }: { extractArgTypes: ArgTypesExtractor } = params.docs || {};
|
||||
if (!extractArgTypes) {
|
||||
throw new Error(ArgsTableError.ARGS_UNSUPPORTED);
|
||||
}
|
||||
let argTypes = extractArgTypes(component);
|
||||
argTypes = filterArgTypes(argTypes, include, exclude);
|
||||
|
||||
return argTypes;
|
||||
};
|
||||
|
||||
export const getComponent = (props: PropsProps = {}, context: DocsContextProps): Component => {
|
||||
const { of } = props as OfProps;
|
||||
const { parameters = {} } = context;
|
||||
const { component } = parameters;
|
||||
|
||||
const target = of === CURRENT_SELECTION ? component : of;
|
||||
if (!target) {
|
||||
if (of === CURRENT_SELECTION) {
|
||||
return null;
|
||||
}
|
||||
throw new Error(ArgsTableError.NO_COMPONENT);
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
const addComponentTabs = (
|
||||
tabs: Record<string, ArgsTableProps>,
|
||||
components: Record<string, Component>,
|
||||
context: DocsContextProps,
|
||||
include?: PropDescriptor,
|
||||
exclude?: PropDescriptor
|
||||
) => ({
|
||||
...tabs,
|
||||
...mapValues(components, (comp) => ({
|
||||
rows: extractComponentArgTypes(comp, context, include, exclude),
|
||||
})),
|
||||
});
|
||||
|
||||
export const StoryTable: FC<
|
||||
StoryProps & { component: Component; subcomponents: Record<string, Component> }
|
||||
> = (props) => {
|
||||
const context = useContext(DocsContext);
|
||||
const {
|
||||
id: currentId,
|
||||
parameters: { argTypes },
|
||||
storyStore,
|
||||
} = context;
|
||||
const { story, component, subcomponents, showComponent, include, exclude } = props;
|
||||
let storyArgTypes;
|
||||
try {
|
||||
let storyId;
|
||||
switch (story) {
|
||||
case CURRENT_SELECTION: {
|
||||
storyId = currentId;
|
||||
storyArgTypes = argTypes;
|
||||
break;
|
||||
}
|
||||
case PRIMARY_STORY: {
|
||||
const primaryStory = getDocsStories(context)[0];
|
||||
storyId = primaryStory.id;
|
||||
storyArgTypes = primaryStory.parameters.argTypes;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
storyId = lookupStoryId(story, context);
|
||||
const data = storyStore.fromId(storyId);
|
||||
storyArgTypes = data.parameters.argTypes;
|
||||
}
|
||||
}
|
||||
storyArgTypes = filterArgTypes(storyArgTypes, include, exclude);
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [args, updateArgs, resetArgs] = useArgs(storyId, storyStore);
|
||||
let tabs = { Story: { rows: storyArgTypes, args, updateArgs, resetArgs } } as Record<
|
||||
string,
|
||||
ArgsTableProps
|
||||
>;
|
||||
|
||||
// Use the dynamically generated component tabs if there are no controls
|
||||
const storyHasArgsWithControls =
|
||||
storyArgTypes && Object.values(storyArgTypes).find((v) => !!v?.control);
|
||||
|
||||
if (!storyHasArgsWithControls) {
|
||||
updateArgs = null;
|
||||
resetArgs = null;
|
||||
tabs = {};
|
||||
}
|
||||
|
||||
if (component && (!storyHasArgsWithControls || showComponent)) {
|
||||
const mainLabel = getComponentName(component);
|
||||
tabs = addComponentTabs(tabs, { [mainLabel]: component }, context, include, exclude);
|
||||
}
|
||||
|
||||
if (subcomponents) {
|
||||
tabs = addComponentTabs(tabs, subcomponents, context, include, exclude);
|
||||
}
|
||||
return <TabbedArgsTable tabs={tabs} />;
|
||||
} catch (err) {
|
||||
return <ArgsTable error={err.message} />;
|
||||
}
|
||||
};
|
||||
|
||||
export const ComponentsTable: FC<ComponentsProps> = (props) => {
|
||||
const context = useContext(DocsContext);
|
||||
const { components, include, exclude } = props;
|
||||
|
||||
const tabs = addComponentTabs({}, components, context, include, exclude);
|
||||
return <TabbedArgsTable tabs={tabs} />;
|
||||
};
|
||||
|
||||
export const Props: FC<PropsProps> = (props) => {
|
||||
const context = useContext(DocsContext);
|
||||
const {
|
||||
parameters: { subcomponents },
|
||||
} = context;
|
||||
|
||||
const { include, exclude, components } = props as ComponentsProps;
|
||||
const { story } = props as StoryProps;
|
||||
|
||||
const main = getComponent(props, context);
|
||||
if (story) {
|
||||
return <StoryTable {...(props as StoryProps)} component={main} subcomponents={subcomponents} />;
|
||||
}
|
||||
|
||||
if (!components && !subcomponents) {
|
||||
let mainProps;
|
||||
try {
|
||||
mainProps = { rows: extractComponentArgTypes(main, context, include, exclude) };
|
||||
} catch (err) {
|
||||
mainProps = { error: err.message };
|
||||
}
|
||||
return <ArgsTable {...mainProps} />;
|
||||
}
|
||||
|
||||
if (components) {
|
||||
return <ComponentsTable {...(props as ComponentsProps)} components={components} />;
|
||||
}
|
||||
|
||||
const mainLabel = getComponentName(main);
|
||||
return (
|
||||
<ComponentsTable
|
||||
{...(props as ComponentsProps)}
|
||||
components={{ [mainLabel]: main, ...subcomponents }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#previewprops-renamed
|
||||
`
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
Props.defaultProps = {
|
||||
of: CURRENT_SELECTION,
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
export { ColorPalette, ColorItem, IconGallery, IconItem, Typeset } from '@storybook/components';
|
||||
|
||||
export * from './Anchor';
|
||||
export * from './ArgsTable';
|
||||
export * from './Canvas';
|
||||
export * from './Description';
|
||||
export * from './DocsContext';
|
||||
export * from './DocsPage';
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Preview, Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { Canvas, Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Button" component={Button} parameters={{ notes: 'component notes' }} />
|
||||
|
||||
# Preview
|
||||
# Canvas
|
||||
|
||||
Previews can contain normal components, stories, and story references
|
||||
Canvases can contain normal components, stories, and story references
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Button>Just a button</Button>
|
||||
<Story name="hello button">
|
||||
<Button>Hello button</Button>
|
||||
@ -16,11 +16,10 @@ Previews can contain normal components, stories, and story references
|
||||
<Button>Two</Button>
|
||||
</Story>
|
||||
<Story id="welcome--welcome" />
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
Canvas wthout a story
|
||||
|
||||
Preview wthout a story
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Button>Just a button</Button>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
@ -5,7 +5,7 @@ exports[`docs-mdx-compiler-plugin previews.mdx 1`] = `
|
||||
import { assertIsFn, AddContext } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Preview, Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { Canvas, Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = (name) =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
@ -30,9 +30,9 @@ function MDXContent({ components, ...props }) {
|
||||
}}
|
||||
mdxType=\\"Meta\\"
|
||||
/>
|
||||
<h1>{\`Preview\`}</h1>
|
||||
<p>{\`Previews can contain normal components, stories, and story references\`}</p>
|
||||
<Preview mdxType=\\"Preview\\">
|
||||
<h1>{\`Canvas\`}</h1>
|
||||
<p>{\`Canvases can contain normal components, stories, and story references\`}</p>
|
||||
<Canvas mdxType=\\"Canvas\\">
|
||||
<Button mdxType=\\"Button\\">Just a button</Button>
|
||||
<Story name=\\"hello button\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">Hello button</Button>
|
||||
@ -41,11 +41,11 @@ function MDXContent({ components, ...props }) {
|
||||
<Button mdxType=\\"Button\\">Two</Button>
|
||||
</Story>
|
||||
<Story id=\\"welcome--welcome\\" mdxType=\\"Story\\" />
|
||||
</Preview>
|
||||
<p>{\`Preview wthout a story\`}</p>
|
||||
<Preview mdxSource=\\"%0A%3CButton%3EJust%20a%20button%3C/Button%3E%0A\\" mdxType=\\"Preview\\">
|
||||
</Canvas>
|
||||
<p>{\`Canvas wthout a story\`}</p>
|
||||
<Canvas mdxSource=\\"%0A%3CButton%3EJust%20a%20button%3C/Button%3E%0A\\" mdxType=\\"Canvas\\">
|
||||
<Button mdxType=\\"Button\\">Just a button</Button>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ const jsStringEscape = require('js-string-escape');
|
||||
// story in the contents
|
||||
|
||||
const STORY_REGEX = /^<Story[\s>]/;
|
||||
const PREVIEW_REGEX = /^<Preview[\s>]/;
|
||||
const CANVAS_REGEX = /^<(Preview|Canvas)[\s>]/;
|
||||
const META_REGEX = /^<Meta[\s>]/;
|
||||
const RESERVED = /^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|await|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$/;
|
||||
|
||||
@ -143,22 +143,20 @@ function genStoryExport(ast, context) {
|
||||
};
|
||||
}
|
||||
|
||||
function genPreviewExports(ast, context) {
|
||||
// console.log('genPreviewExports', JSON.stringify(ast, null, 2));
|
||||
|
||||
const previewExports = {};
|
||||
function genCanvasExports(ast, context) {
|
||||
const canvasExports = {};
|
||||
for (let i = 0; i < ast.children.length; i += 1) {
|
||||
const child = ast.children[i];
|
||||
if (child.type === 'JSXElement' && child.openingElement.name.name === 'Story') {
|
||||
const storyExport = genStoryExport(child, context);
|
||||
if (storyExport) {
|
||||
Object.assign(previewExports, storyExport);
|
||||
Object.assign(canvasExports, storyExport);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
context.counter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return previewExports;
|
||||
return canvasExports;
|
||||
}
|
||||
|
||||
function genMeta(ast, options) {
|
||||
@ -210,13 +208,12 @@ function getExports(node, counter, options) {
|
||||
const storyExport = genStoryExport(ast, counter);
|
||||
return storyExport && { stories: storyExport };
|
||||
}
|
||||
if (PREVIEW_REGEX.exec(value)) {
|
||||
// Preview, possibly containing multiple stories
|
||||
if (CANVAS_REGEX.exec(value)) {
|
||||
// Canvas/Preview, possibly containing multiple stories
|
||||
const ast = parser.parseExpression(value, { plugins: ['jsx'] });
|
||||
return { stories: genPreviewExports(ast, counter) };
|
||||
return { stories: genCanvasExports(ast, counter) };
|
||||
}
|
||||
if (META_REGEX.exec(value)) {
|
||||
// Preview, possibly containing multiple stories
|
||||
const ast = parser.parseExpression(value, { plugins: ['jsx'] });
|
||||
return { meta: genMeta(ast, options) };
|
||||
}
|
||||
@ -266,11 +263,11 @@ function extractExports(node, options) {
|
||||
if (
|
||||
ast.openingElement &&
|
||||
ast.openingElement.type === 'JSXOpeningElement' &&
|
||||
ast.openingElement.name.name === 'Preview' &&
|
||||
['Preview', 'Canvas'].includes(ast.openingElement.name.name) &&
|
||||
!hasStoryChild(ast)
|
||||
) {
|
||||
const previewAst = ast.openingElement;
|
||||
previewAst.attributes.push({
|
||||
const canvasAst = ast.openingElement;
|
||||
canvasAst.attributes.push({
|
||||
type: 'JSXAttribute',
|
||||
name: {
|
||||
type: 'JSXIdentifier',
|
||||
|
@ -110,7 +110,7 @@ module.exports = {
|
||||
Finally, you can create MDX files like this:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { InfoButton } from './InfoButton.vue';
|
||||
|
||||
<Meta title='InfoButton' component={InfoButton} />
|
||||
@ -124,9 +124,9 @@ Some **markdown** description, or whatever you want.
|
||||
template: '<info-button label="I\'m a button!"/>',
|
||||
}}</Story>
|
||||
|
||||
## Props
|
||||
## ArgsTable
|
||||
|
||||
<Props of={InfoButton} />
|
||||
<ArgsTable of={InfoButton} />
|
||||
```
|
||||
|
||||
Yes, it's redundant to declare `component` twice. [Coming soon](https://github.com/storybookjs/storybook/issues/8685).
|
||||
|
@ -19,7 +19,7 @@ title: 'MDX Syntax'
|
||||
Let's get started with an example that combines markdown with a single story:
|
||||
|
||||
```md
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
||||
import { Checkbox } from './Checkbox';
|
||||
|
||||
<Meta title="MDX/Checkbox" component={Checkbox} />
|
||||
@ -29,7 +29,7 @@ import { Checkbox } from './Checkbox';
|
||||
With `MDX` we can define a story for `Checkbox` right in the middle of our
|
||||
markdown documentation.
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="all checkboxes">
|
||||
<form>
|
||||
<Checkbox id="Unchecked" label="Unchecked" />
|
||||
@ -37,7 +37,7 @@ markdown documentation.
|
||||
<Checkbox appearance="secondary" id="second" label="Secondary" checked />
|
||||
</form>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
```
|
||||
|
||||
And here's how that's rendered in Storybook:
|
||||
@ -93,19 +93,19 @@ Let's define a story for our `Badge` component:
|
||||
<Badge status="positive">Positive</Badge>
|
||||
</Story>
|
||||
|
||||
We can drop it in a `Preview` to get a code snippet:
|
||||
We can drop it in a `Canvas` to get a code snippet:
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="negative">
|
||||
<Badge status="negative">Negative</Badge>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
We can even preview multiple stories in a block. This
|
||||
gets rendered as a group, but defines individual stories
|
||||
with unique URLs and isolated snapshot tests.
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="warning">
|
||||
<Badge status="warning">Warning</Badge>
|
||||
</Story>
|
||||
@ -121,7 +121,7 @@ with unique URLs and isolated snapshot tests.
|
||||
with icon
|
||||
</Badge>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
```
|
||||
|
||||
And here's how that gets rendered in Storybook:
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { moduleMetadata } from '@storybook/angular';
|
||||
import { Story, Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Story, Meta, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { Welcome, Button } from '@storybook/angular/demo';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
import { text, withKnobs } from '@storybook/addon-knobs';
|
||||
@ -79,7 +79,7 @@ Let's add another one. The UI updates automatically as you'd expect.
|
||||
|
||||
We can automatically generate props tables from Angular components:
|
||||
|
||||
<Props of={ButtonComponent} />
|
||||
<ArgsTable of={ButtonComponent} />
|
||||
|
||||
## More info
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
||||
import { CoolButton } from '../cool-button/cool-button';
|
||||
import { addComponents } from '@storybook/aurelia';
|
||||
import { text, withKnobs } from '@storybook/addon-knobs';
|
||||
@ -8,9 +8,9 @@ import Button from './button';
|
||||
|
||||
# Welcome
|
||||
|
||||
This is a test document written in MDX that defines a `CoolButton` story wrapped in a `Preview` doc block:
|
||||
This is a test document written in MDX that defines a `CoolButton` story wrapped in a `Canvas` doc block:
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="to Storybook">
|
||||
{{
|
||||
template: `<cool-button text.bind="testText"></cool-button>`,
|
||||
@ -19,4 +19,4 @@ This is a test document written in MDX that defines a `CoolButton` story wrapped
|
||||
},
|
||||
}}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, Canvas, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { Button } from './Button';
|
||||
|
||||
<Meta title="Test" />
|
||||
|
||||
Here's some _markdown_!
|
||||
|
||||
# Preview
|
||||
# Canvas
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="button">
|
||||
<Button>hello</Button>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
# Props
|
||||
# ArgsTable
|
||||
|
||||
<Props of={Button} />
|
||||
<ArgsTable of={Button} />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Props, Description } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, ArgsTable, Description } from '@storybook/addon-docs/blocks';
|
||||
import * as DocgenJS from './DocgenJS';
|
||||
import * as DocgenTS from './DocgenTS';
|
||||
|
||||
@ -8,7 +8,7 @@ export const DescriptionProps = ({ of }) => (
|
||||
<>
|
||||
<h2>{of.displayName}</h2>
|
||||
<Description of={of} />
|
||||
<Props of={of} />
|
||||
<ArgsTable of={of} />
|
||||
</>
|
||||
);
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { ButtonTooManyProps } from './jsdoc-perfo';
|
||||
|
||||
<Meta title="Docgen/jsdoc-perfo" />
|
||||
|
||||
## Render 150 props with JSDoc tags
|
||||
|
||||
<Props of={ButtonTooManyProps} />
|
||||
<Props of={ButtonTooManyProps} />
|
||||
<Props of={ButtonTooManyProps} />
|
||||
<ArgsTable of={ButtonTooManyProps} />
|
||||
<ArgsTable of={ButtonTooManyProps} />
|
||||
<ArgsTable of={ButtonTooManyProps} />
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { JsDocProps, FailingJsDocProps } from './jsdoc';
|
||||
import { TypeScriptProps } from './jsdoc-ts';
|
||||
|
||||
<Meta title="Docgen/jsdoc" />
|
||||
|
||||
<Props of={JsDocProps} />
|
||||
<Props of={TypeScriptProps} />
|
||||
<Props of={FailingJsDocProps} />
|
||||
<ArgsTable of={JsDocProps} />
|
||||
<ArgsTable of={TypeScriptProps} />
|
||||
<ArgsTable of={FailingJsDocProps} />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { PropTypesProps } from './prop-types';
|
||||
import { TypeScriptProps, TypeScriptHtmlComponent } from './ts-types';
|
||||
|
||||
@ -6,10 +6,10 @@ import { TypeScriptProps, TypeScriptHtmlComponent } from './ts-types';
|
||||
|
||||
## Prop Types
|
||||
|
||||
<Props of={PropTypesProps} />
|
||||
<ArgsTable of={PropTypesProps} />
|
||||
|
||||
## TypeScript
|
||||
|
||||
<Props of={TypeScriptProps} />
|
||||
<ArgsTable of={TypeScriptProps} />
|
||||
|
||||
<Props of={TypeScriptHtmlComponent} />
|
||||
<ArgsTable of={TypeScriptHtmlComponent} />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { PropsSort } from "./PropsSort";
|
||||
import { Props, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { PropsSort } from './PropsSort';
|
||||
import { ArgsTable, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="PropsSort" />
|
||||
|
||||
<Props of={PropsSort} />
|
||||
<Props of={PropsSort} exclude={["foo"]} />
|
||||
<ArgsTable of={PropsSort} />
|
||||
<ArgsTable of={PropsSort} exclude={['foo']} />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Story, Preview, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { Story, Canvas, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
# Storybook Docs for HTML
|
||||
@ -27,15 +27,15 @@ How you like them apples?!
|
||||
|
||||
## Custom source
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="custom source" height="100px" parameters={{ docs: { source: { code: 'hello' } } }}>
|
||||
{'<h1>Custom source</h1>'}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Transformed source
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story
|
||||
name="transformed source"
|
||||
height="100px"
|
||||
@ -43,7 +43,7 @@ How you like them apples?!
|
||||
>
|
||||
{'<h1>Some source</h1>'}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Story reference
|
||||
|
||||
|
@ -4,7 +4,7 @@ import {
|
||||
Subtitle,
|
||||
Description,
|
||||
Primary,
|
||||
Props,
|
||||
ArgsTable,
|
||||
Stories,
|
||||
} from '@storybook/addon-docs/blocks';
|
||||
import { DocgenButton } from '../../components/DocgenButton';
|
||||
@ -22,7 +22,7 @@ export default {
|
||||
<Subtitle />
|
||||
<Description />
|
||||
<Primary />
|
||||
<Props />
|
||||
<ArgsTable />
|
||||
<Stories />
|
||||
</>
|
||||
),
|
||||
@ -61,7 +61,7 @@ checkBoxProps.parameters = {
|
||||
<input type="checkbox" checked={showProps} onChange={() => setShowProps(!showProps)} />
|
||||
<span>display props</span>
|
||||
</label>
|
||||
{showProps && <Props />}
|
||||
{showProps && <ArgsTable />}
|
||||
</>
|
||||
);
|
||||
},
|
||||
@ -78,7 +78,7 @@ customLabels.parameters = {
|
||||
<Subtitle>Custom sub title</Subtitle>
|
||||
<Description>Custom description</Description>
|
||||
<Primary />
|
||||
<Props />
|
||||
<ArgsTable />
|
||||
<Stories title="Custom stories title" />
|
||||
</>
|
||||
),
|
||||
@ -117,7 +117,7 @@ multipleComponents.parameters = {
|
||||
<Subtitle />
|
||||
<Description />
|
||||
<Primary name="Many Components" />
|
||||
<Props />
|
||||
<ArgsTable />
|
||||
</>
|
||||
),
|
||||
},
|
||||
@ -138,7 +138,7 @@ componentsProps.parameters = {
|
||||
<Description>
|
||||
Here's what happens when your component has some related components
|
||||
</Description>
|
||||
<Props
|
||||
<ArgsTable
|
||||
components={{
|
||||
'ButtonGroup Custom': ButtonGroup,
|
||||
'Docgen Button': DocgenButton,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {
|
||||
Story,
|
||||
Preview,
|
||||
Props,
|
||||
Canvas,
|
||||
ArgsTable,
|
||||
Source,
|
||||
Description,
|
||||
ColorPalette,
|
||||
@ -33,11 +33,11 @@ import MdxNotes from '../notes/notes.mdx';
|
||||
|
||||
<Source id="." />
|
||||
|
||||
<Props of="." />
|
||||
<ArgsTable of="." />
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story id="nonexistent-story" />
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Transclusion
|
||||
|
||||
@ -79,7 +79,7 @@ export const nonStory1 = 'foo'; // a non-story export
|
||||
|
||||
export const nonStory2 = () => <Button>Not a story</Button>; // another one
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="hello story">
|
||||
<Button onClick={action('clicked')}>{text('caption', 'hello world')}</Button>
|
||||
</Story>
|
||||
@ -93,7 +93,7 @@ export const nonStory2 = () => <Button>Not a story</Button>; // another one
|
||||
<Button onClick={action('clicked')}>goodbye world</Button>
|
||||
</Story>
|
||||
<Story name="plaintext">Plain text</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Story name="solo story">
|
||||
<Button onClick={action('clicked')}>solo</Button>
|
||||
@ -122,15 +122,15 @@ export const nonStory2 = () => <Button>Not a story</Button>; // another one
|
||||
|
||||
<Source name="hello story" />
|
||||
|
||||
<Preview>
|
||||
<Button onClick={action('clicked')}>view source in preview</Button>
|
||||
</Preview>
|
||||
<Canvas>
|
||||
<Button onClick={action('clicked')}>view source in Canvas</Button>
|
||||
</Canvas>
|
||||
|
||||
## Configurable height
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story id="basics-button--all-buttons" height="400px" />
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Description
|
||||
|
||||
@ -138,29 +138,29 @@ export const nonStory2 = () => <Button>Not a story</Button>; // another one
|
||||
|
||||
<Description of={DocgenButton} />
|
||||
|
||||
## Props
|
||||
## ArgsTable
|
||||
|
||||
### Docgen
|
||||
|
||||
<Props of={DocgenButton} />
|
||||
<ArgsTable of={DocgenButton} />
|
||||
|
||||
### Flow
|
||||
|
||||
Flow types are not officially supported
|
||||
|
||||
<Props of={FlowTypeButton} />
|
||||
<ArgsTable of={FlowTypeButton} />
|
||||
|
||||
### withSource="none"
|
||||
|
||||
<Preview withSource="none">
|
||||
<Canvas withSource="none">
|
||||
<h1>no source</h1>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Preview withSource="none">
|
||||
<Story name="no source preview">
|
||||
<Canvas withSource="none">
|
||||
<Story name="no source Canvas">
|
||||
<Button onClick={action('clicked')}>solo</Button>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Docs Disable
|
||||
|
||||
@ -170,9 +170,9 @@ Flow types are not officially supported
|
||||
|
||||
## Story with multiple children
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="story multiple children">
|
||||
<p>Hello Child #1</p>
|
||||
<p>Hello Child #2</p>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Addons/Docs/docs-only" parameters={{ previewTabs: { canvas: { hidden: true } } }} />
|
||||
|
||||
@ -8,9 +8,9 @@ This file is a documentation-only MDX file, i.e. it doesn't contain any `<Story>
|
||||
|
||||
Therefore, it shows up in the navigation UI as a document icon.
|
||||
|
||||
It can, however, still contain a `<Preview>` definition:
|
||||
It can, however, still contain a `<Canvas>` definition:
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<div>
|
||||
<h3>This is a preview block within a documentation-only MDX file</h3>
|
||||
<p>
|
||||
@ -18,7 +18,7 @@ It can, however, still contain a `<Preview>` definition:
|
||||
cases such as documenting a design system.
|
||||
</p>
|
||||
</div>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Props, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { ArgsTable, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { DocgenButton } from '../../components/DocgenButton';
|
||||
|
||||
<Meta title="Addons/Docs/IncludeExclude" />
|
||||
@ -7,18 +7,18 @@ import { DocgenButton } from '../../components/DocgenButton';
|
||||
|
||||
### Array
|
||||
|
||||
<Props of={DocgenButton} include={['disabled', 'label']} />
|
||||
<ArgsTable of={DocgenButton} include={['disabled', 'label']} />
|
||||
|
||||
### Regex
|
||||
|
||||
<Props of={DocgenButton} include={/^o.*/} />
|
||||
<ArgsTable of={DocgenButton} include={/^o.*/} />
|
||||
|
||||
## Exclude
|
||||
|
||||
### Regex
|
||||
|
||||
<Props of={DocgenButton} exclude={/^o.*|^...$/} />
|
||||
<ArgsTable of={DocgenButton} exclude={/^o.*|^...$/} />
|
||||
|
||||
## Mixed
|
||||
|
||||
<Props of={DocgenButton} include={/^o.*/} exclude={['one', 'obj']} />
|
||||
<ArgsTable of={DocgenButton} include={/^o.*/} exclude={['one', 'obj']} />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Preview, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Canvas, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import range from 'lodash/range';
|
||||
import { DocgenButton } from '../../components/DocgenButton';
|
||||
import { ButtonGroup, SubGroup } from '../../components/ButtonGroup';
|
||||
@ -28,7 +28,7 @@ export const Template = (args = {}) => (
|
||||
|
||||
## ArgTypes
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story
|
||||
name="ArgTypes"
|
||||
args={{
|
||||
@ -79,17 +79,17 @@ export const Template = (args = {}) => (
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Props story="ArgTypes" />
|
||||
<ArgsTable story="ArgTypes" />
|
||||
|
||||
## ArgTypes w/ Component
|
||||
|
||||
<Props story="ArgTypes" showComponent />
|
||||
<ArgsTable story="ArgTypes" showComponent />
|
||||
|
||||
## Args
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Args"
|
||||
args={{
|
||||
@ -99,13 +99,13 @@ export const Template = (args = {}) => (
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Props story="Args" />
|
||||
<ArgsTable story="Args" />
|
||||
|
||||
## Component Story
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Component"
|
||||
argTypes={{
|
||||
@ -118,13 +118,13 @@ export const Template = (args = {}) => (
|
||||
return <ButtonGroup background={background}>{contents}</ButtonGroup>;
|
||||
}}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Props story="Component" />
|
||||
<ArgsTable story="Component" />
|
||||
|
||||
## Controls Story
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Controls"
|
||||
args={{
|
||||
@ -150,18 +150,18 @@ export const Template = (args = {}) => (
|
||||
);
|
||||
}}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Props story="Controls" />
|
||||
<ArgsTable story="Controls" />
|
||||
|
||||
## Components
|
||||
|
||||
<Props components={{ ButtonGroup, SubGroup }} />
|
||||
<ArgsTable components={{ ButtonGroup, SubGroup }} />
|
||||
|
||||
## Component
|
||||
|
||||
<Props of={DocgenButton} />
|
||||
<ArgsTable of={DocgenButton} />
|
||||
|
||||
## OptionalButton
|
||||
|
||||
<Props of={OptionalButton} />
|
||||
<ArgsTable of={OptionalButton} />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Preview, Story } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Canvas, Story } from '@storybook/addon-docs/blocks';
|
||||
import { Button } from '@storybook/react/demo';
|
||||
|
||||
<Meta
|
||||
@ -10,36 +10,36 @@ import { Button } from '@storybook/react/demo';
|
||||
|
||||
# Layout parameter
|
||||
|
||||
This tests Storybook's built-in `layout` parameter, both as its applied in the canvas, and also how it's handled by the `Preview` block in `addon-docs`.
|
||||
This tests Storybook's built-in `layout` parameter, both as its applied in the canvas, and also how it's handled by the `Canvas` block in `addon-docs`.
|
||||
|
||||
## Default
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="defaultValue">
|
||||
<Button>Hello world</Button>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Padded
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="padded" parameters={{ layout: 'padded' }}>
|
||||
<Button>Hello world</Button>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Fullscreen
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="fullscreen" parameters={{ layout: 'fullscreen' }}>
|
||||
<Button>Hello world</Button>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Centered
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="centered" parameters={{ layout: 'centered' }}>
|
||||
<Button>Hello world</Button>
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { useState } from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, Canvas, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Other/Demo/ButtonMdx" component={Button} />
|
||||
|
||||
# Simple Button
|
||||
|
||||
<Props of={Button} />
|
||||
<ArgsTable of={Button} />
|
||||
|
||||
## Hello
|
||||
|
||||
@ -27,7 +27,7 @@ import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
|
||||
## Counter w/ Code
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story name="with counter">
|
||||
{() => {
|
||||
const [counter, setCounter] = useState(0);
|
||||
@ -35,4 +35,4 @@ import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
return <Button onClick={() => setCounter(counter + 1)}>{label}</Button>;
|
||||
}}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Props, Story } from '@storybook/addon-docs/blocks';
|
||||
import { ArgsTable, Story } from '@storybook/addon-docs/blocks';
|
||||
import { Button } from '@storybook/react/demo';
|
||||
|
||||
# Welcome!
|
||||
@ -7,6 +7,6 @@ Let's write markdown without stories
|
||||
|
||||
But we can still use doc blocks in our stories
|
||||
|
||||
<Props of={Button} />
|
||||
<ArgsTable of={Button} />
|
||||
|
||||
<Story id="basics-button--all-buttons" height="400px" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Preview, Story, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Canvas, Story, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import MyButton from './Button.vue';
|
||||
import InfoButton from './components/InfoButton.vue';
|
||||
|
||||
@ -22,7 +22,7 @@ Controls can also be defined and used in MDX stories.
|
||||
|
||||
## Rounded
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Rounded"
|
||||
args={{
|
||||
@ -33,13 +33,13 @@ Controls can also be defined and used in MDX stories.
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Props story="Rounded" />
|
||||
<ArgsTable story="Rounded" />
|
||||
|
||||
## Square
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Square"
|
||||
args={{
|
||||
@ -50,10 +50,10 @@ Controls can also be defined and used in MDX stories.
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Props story="Square" />
|
||||
<ArgsTable story="Square" />
|
||||
|
||||
## Multiple components
|
||||
|
||||
<Props components={{ MyButton, InfoButton }} />
|
||||
<ArgsTable components={{ MyButton, InfoButton }} />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Story, Preview, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { Story, Canvas, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { stripIndents } from 'common-tags';
|
||||
import MyButton from './Button.vue';
|
||||
|
||||
@ -68,13 +68,13 @@ The default configuration for `addon-docs/vue` implements the `prepareForInline`
|
||||
|
||||
To provide a tangible example of the inline/iframe rendering contexts, here's the same story rendered both ways.
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story id="app--app" inline={true} />
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Preview>
|
||||
<Canvas>
|
||||
<Story id="app--app" height="200px" />
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
The biggest win here is that we don't have to worry about setting the height anymore. The story can calculate its height like any other inline element. As you can see, several of the stories on this page are quite small, but take up `500px`, because that's the default story height, and we didn't tweak the story to be an explicit height. Another huge gain here is in terms of performance. Using an iframe to render a single element is definitely unnecessary in most cases and, as you may have noticed while reading this page, can _really_ cause page performance to suffer.
|
||||
|
||||
@ -88,7 +88,7 @@ Just like in React, we can easily reference other stories in our docs:
|
||||
|
||||
## More info
|
||||
|
||||
For more info, check out the [Storybook Docs Technical Preview](https://docs.google.com/document/d/1un6YX7xDKEKl5-MVb-egnOYN8dynb5Hf7mq0hipk8JE/edit?usp=sharing).
|
||||
For more info, check out the [Storybook Docs Technical Canvas](https://docs.google.com/document/d/1un6YX7xDKEKl5-MVb-egnOYN8dynb5Hf7mq0hipk8JE/edit?usp=sharing).
|
||||
|
||||
We want your feedback to help make this more useful.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Story, Preview, Meta, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Story, Canvas, Meta, ArgsTable } from '@storybook/addon-docs/blocks';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { html } from 'lit-html';
|
||||
import '../demo-wc-card.js';
|
||||
@ -12,16 +12,14 @@ import '../demo-wc-card.js';
|
||||
A story can be a simple return of `html`
|
||||
|
||||
<Story name="simple" height="220px">
|
||||
{html`
|
||||
<demo-wc-card>Hello World</demo-wc-card>
|
||||
`}
|
||||
{html` <demo-wc-card>Hello World</demo-wc-card> `}
|
||||
</Story>
|
||||
|
||||
## API
|
||||
|
||||
You can show the api table of a web component at any point in your documentation.
|
||||
|
||||
<Props of="demo-wc-card" />
|
||||
<ArgsTable of="demo-wc-card" />
|
||||
|
||||
## Function stories
|
||||
|
||||
@ -29,7 +27,10 @@ Or a function
|
||||
|
||||
<Story name="function" height="220px">
|
||||
{() => {
|
||||
const rows = [{ header: 'health', value: '200' }, { header: 'mana', value: '100' }];
|
||||
const rows = [
|
||||
{ header: 'health', value: '200' },
|
||||
{ header: 'mana', value: '100' },
|
||||
];
|
||||
return html`
|
||||
<demo-wc-card back-side .rows=${rows}>
|
||||
A card with data on the back
|
||||
@ -42,21 +43,19 @@ Or a function
|
||||
|
||||
You can also wrap your live demos in a nice little wrapper.
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="wrapper" height="220px">
|
||||
{html`
|
||||
<demo-wc-card>Hello World</demo-wc-card>
|
||||
`}
|
||||
{html` <demo-wc-card>Hello World</demo-wc-card> `}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Story reference
|
||||
|
||||
You can also reference an existing story from within your MDX file.
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story id="welcome--welcome" height="500px" inline={false} />
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
## Stories not inline
|
||||
|
||||
@ -80,7 +79,7 @@ or add it to individual stories.
|
||||
<Story inline={false} />
|
||||
```
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="notInline" height="220px">
|
||||
{html`
|
||||
<style>
|
||||
@ -89,4 +88,4 @@ or add it to individual stories.
|
||||
<p>Makes all p tags red... so best to not render inline</pd>
|
||||
`}
|
||||
</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
||||
|
||||
# HTML MDX Demo
|
||||
|
||||
@ -6,16 +6,16 @@ Here's a few sample HTML stories in MDX. Enjoy!
|
||||
|
||||
<Meta title="Demo" />
|
||||
|
||||
<Preview withToolbar>
|
||||
<Canvas withToolbar>
|
||||
<Story name="heading">{() => '<h1>Hello World</h1>'}</Story>
|
||||
</Preview>
|
||||
</Canvas>
|
||||
|
||||
<Story name="button">
|
||||
{() => {
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.innerText = 'Hello Button';
|
||||
btn.addEventListener('click', e => console.log(e));
|
||||
btn.addEventListener('click', (e) => console.log(e));
|
||||
return btn;
|
||||
}}
|
||||
</Story>
|
||||
|
Loading…
x
Reference in New Issue
Block a user