mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-09 00:19:13 +08:00
Add of prop and deprecate componentSubtitle
This commit is contained in:
parent
84b1609cdd
commit
764c819a38
@ -71,6 +71,7 @@
|
||||
- [Source block](#source-block)
|
||||
- [Canvas block](#canvas-block)
|
||||
- [ArgsTable block](#argstable-block)
|
||||
- [Subtitle block and `parameters.componentSubtitle`](#subtitle-block-and-parameterscomponentsubtitle)
|
||||
- [Configuring Autodocs](#configuring-autodocs)
|
||||
- [MDX2 upgrade](#mdx2-upgrade)
|
||||
- [Legacy MDX1 support](#legacy-mdx1-support)
|
||||
@ -1333,7 +1334,7 @@ Additionally to changing the docs information architecture, we've updated the AP
|
||||
|
||||
- When you've attached to a CSF file (with the `Meta` block, or in Autodocs), you can drop the `of` and the block will reference the first story or the CSF file as a whole.
|
||||
|
||||
- Most other props controlling rendering of blocks now correspond precisely to the parameters for that block [defined for autodocs above](#autodocs-changes).
|
||||
- Most other props controlling rendering of blocks now correspond precisely to the parameters for that block [defined for autodocs above](#autodocsautodocs-changes).
|
||||
|
||||
##### Meta block
|
||||
|
||||
@ -1449,6 +1450,12 @@ The following props are not supported in the new blocks:
|
||||
- `story="^"` to reference the primary story (just omit `of` in that case, for `Controls`).
|
||||
- `story="."` to reference the current story (this no longer makes sense in Docs 2).
|
||||
- `story="name"` to reference a story (use `of={}`).
|
||||
-
|
||||
##### Subtitle block and `parameters.componentSubtitle`
|
||||
|
||||
The `Subtitle` block now accepts an `of` prop, which can be a reference to a CSF file or a default export (meta).
|
||||
|
||||
`parameters.componentSubtitle` has been deprecated to be consistent with other parameters related to autodocs, instead use `parameters.docs.subtitle`.
|
||||
|
||||
#### Configuring Autodocs
|
||||
|
||||
|
104
code/ui/blocks/src/blocks/Subtitle.stories.tsx
Normal file
104
code/ui/blocks/src/blocks/Subtitle.stories.tsx
Normal file
@ -0,0 +1,104 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { Subtitle } from './Subtitle';
|
||||
import * as DefaultButtonStories from '../examples/Button.stories';
|
||||
import * as ButtonStoriesWithMetaSubtitleInBoth from '../examples/ButtonWithMetaSubtitleInBoth.stories';
|
||||
import * as ButtonStoriesWithMetaSubtitleInComponentSubtitle from '../examples/ButtonWithMetaSubtitleInComponentSubtitle.stories';
|
||||
import * as ButtonStoriesWithMetaSubtitleInDocsSubtitle from '../examples/ButtonWithMetaSubtitleInDocsSubtitle.stories';
|
||||
|
||||
const meta: Meta<typeof Subtitle> = {
|
||||
component: Subtitle,
|
||||
parameters: {
|
||||
controls: {
|
||||
include: [],
|
||||
hideNoControlsWarning: true,
|
||||
},
|
||||
// workaround for https://github.com/storybookjs/storybook/issues/20505
|
||||
docs: { source: { type: 'code' } },
|
||||
attached: false,
|
||||
docsStyles: true,
|
||||
},
|
||||
};
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const OfCSFFileInBoth: Story = {
|
||||
args: {
|
||||
of: ButtonStoriesWithMetaSubtitleInBoth,
|
||||
},
|
||||
parameters: {
|
||||
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleInBoth.stories'],
|
||||
},
|
||||
};
|
||||
export const OfCSFFileInComponentSubtitle: Story = {
|
||||
name: 'Of CSF File In parameters.componentSubtitle',
|
||||
args: {
|
||||
of: ButtonStoriesWithMetaSubtitleInComponentSubtitle,
|
||||
},
|
||||
parameters: {
|
||||
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleInComponentSubtitle.stories'],
|
||||
},
|
||||
};
|
||||
export const OfCSFFileInDocsSubtitle: Story = {
|
||||
name: 'Of CSF File In parameters.docs.subtitle',
|
||||
args: {
|
||||
of: ButtonStoriesWithMetaSubtitleInDocsSubtitle,
|
||||
},
|
||||
parameters: {
|
||||
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleInDocsSubtitle.stories'],
|
||||
},
|
||||
};
|
||||
export const OfMetaInBoth: Story = {
|
||||
args: {
|
||||
of: ButtonStoriesWithMetaSubtitleInBoth.default,
|
||||
},
|
||||
parameters: {
|
||||
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleInBoth.stories'],
|
||||
},
|
||||
};
|
||||
export const OfMetaInComponentSubtitle: Story = {
|
||||
name: 'Of Meta In parameters.componentSubtitle',
|
||||
args: {
|
||||
of: ButtonStoriesWithMetaSubtitleInComponentSubtitle.default,
|
||||
},
|
||||
parameters: {
|
||||
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleInComponentSubtitle.stories'],
|
||||
},
|
||||
};
|
||||
export const OfMetaInDocsSubtitle: Story = {
|
||||
name: 'Of Meta In parameters.docs.subtitle',
|
||||
args: {
|
||||
of: ButtonStoriesWithMetaSubtitleInDocsSubtitle.default,
|
||||
},
|
||||
parameters: {
|
||||
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleInDocsSubtitle.stories'],
|
||||
},
|
||||
};
|
||||
export const DefaultAttached: Story = {
|
||||
parameters: { relativeCsfPaths: ['../examples/Button.stories'], attached: true },
|
||||
};
|
||||
export const OfUndefinedAttached: Story = {
|
||||
args: {
|
||||
// @ts-expect-error this is supposed to be undefined
|
||||
// eslint-disable-next-line import/namespace
|
||||
of: DefaultButtonStories.NotDefined,
|
||||
},
|
||||
parameters: {
|
||||
chromatic: { disableSnapshot: true },
|
||||
relativeCsfPaths: ['../examples/Button.stories'],
|
||||
attached: true,
|
||||
},
|
||||
decorators: [(s) => (window?.navigator.userAgent.match(/StorybookTestRunner/) ? <div /> : s())],
|
||||
};
|
||||
export const OfStringMetaAttached: Story = {
|
||||
name: 'Of "meta" Attached',
|
||||
args: {
|
||||
of: 'meta',
|
||||
},
|
||||
parameters: { relativeCsfPaths: ['../examples/Button.stories'], attached: true },
|
||||
};
|
||||
export const Children: Story = {
|
||||
parameters: { relativeCsfPaths: ['../examples/Button.stories'], attached: true },
|
||||
render: () => <Subtitle>This subtitle is set inside the Subtitle element.</Subtitle>,
|
||||
};
|
@ -1,16 +1,41 @@
|
||||
import type { FunctionComponent, ReactNode } from 'react';
|
||||
import React, { useContext } from 'react';
|
||||
import React from 'react';
|
||||
import { deprecate } from '@storybook/client-logger';
|
||||
|
||||
import { Subtitle as PureSubtitle } from '../components';
|
||||
import { DocsContext } from './DocsContext';
|
||||
import type { Of } from './useOf';
|
||||
import { useOf } from './useOf';
|
||||
|
||||
interface SubtitleProps {
|
||||
children?: ReactNode;
|
||||
/**
|
||||
* Specify where to get the subtitle from.
|
||||
* If not specified, the subtitle will be extracted from the meta of the attached CSF file.
|
||||
*/
|
||||
of?: Of;
|
||||
}
|
||||
|
||||
export const Subtitle: FunctionComponent<SubtitleProps> = ({ children }) => {
|
||||
const docsContext = useContext(DocsContext);
|
||||
const { parameters } = docsContext.storyById();
|
||||
const content = children || parameters?.componentSubtitle;
|
||||
const DEPRECATION_MIGRATION_LINK =
|
||||
'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#description-block-parameters';
|
||||
|
||||
export const Subtitle: FunctionComponent<SubtitleProps> = (props) => {
|
||||
const { of, children } = props;
|
||||
|
||||
if ('of' in props && of === undefined) {
|
||||
throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?');
|
||||
}
|
||||
|
||||
const { preparedMeta } = useOf(of || 'meta', ['meta']);
|
||||
const { parameters } = preparedMeta;
|
||||
const { componentSubtitle, docs } = parameters || {};
|
||||
|
||||
if (componentSubtitle) {
|
||||
deprecate(
|
||||
`Using 'parameters.componentSubtitle' property to subtitle stories is deprecated. See ${DEPRECATION_MIGRATION_LINK}`
|
||||
);
|
||||
}
|
||||
|
||||
const content = children || docs?.subtitle || componentSubtitle;
|
||||
|
||||
return content ? (
|
||||
<PureSubtitle className="sbdocs-subtitle sb-unstyled">{content}</PureSubtitle>
|
||||
|
@ -20,6 +20,9 @@ const meta = {
|
||||
notes: 'These are notes for the Button stories',
|
||||
info: 'This is info for the Button stories',
|
||||
jsx: { useBooleanShorthandSyntax: false },
|
||||
docs: {
|
||||
subtitle: 'This is the subtitle for the Button stories',
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof Button>;
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Button } from './Button';
|
||||
|
||||
const meta = {
|
||||
title: 'examples/Button with Meta Subtitle in Both',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
parameters: {
|
||||
// Stop *this* story from being stacked in Chromatic
|
||||
theme: 'default',
|
||||
// this is to test the deprecated features of the Subtitle block
|
||||
componentSubtitle: 'This subtitle is set in parameters.componentSubtitle',
|
||||
docs: {
|
||||
subtitle: 'This subtitle is set in parameters.docs.subtitle',
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof Button>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const WithMetaSubtitleInBoth: Story = {
|
||||
args: {
|
||||
primary: true,
|
||||
label: 'Button',
|
||||
},
|
||||
};
|
@ -0,0 +1,26 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Button } from './Button';
|
||||
|
||||
const meta = {
|
||||
title: 'examples/Button with Meta Subtitle in componentSubtitle',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
parameters: {
|
||||
// Stop *this* story from being stacked in Chromatic
|
||||
theme: 'default',
|
||||
// this is to test the deprecated features of the Subtitle block
|
||||
componentSubtitle: 'This subtitle is set in parameters.componentSubtitle',
|
||||
},
|
||||
} satisfies Meta<typeof Button>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const WithMetaSubtitleInComponentSubtitle: Story = {
|
||||
args: {
|
||||
primary: true,
|
||||
label: 'Button',
|
||||
},
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Button } from './Button';
|
||||
|
||||
const meta = {
|
||||
title: 'examples/Button with Meta Subtitle in docs.subtitle',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
backgroundColor: { control: 'color' },
|
||||
},
|
||||
parameters: {
|
||||
// Stop *this* story from being stacked in Chromatic
|
||||
theme: 'default',
|
||||
docs: {
|
||||
subtitle: 'This subtitle is set in parameters.docs.subtitle',
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof Button>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const WithMetaSubtitleInDocsSubtitle: Story = {
|
||||
args: {
|
||||
primary: true,
|
||||
label: 'Button',
|
||||
},
|
||||
};
|
@ -24,10 +24,16 @@ import { Subtitle } from '@storybook/blocks';
|
||||
|
||||
`Subtitle` is configured with the following props:
|
||||
|
||||
### `of`
|
||||
|
||||
Type: CSF file exports
|
||||
|
||||
Specifies which meta's subtitle is displayed.
|
||||
|
||||
### `children`
|
||||
|
||||
Type: `JSX.Element | string`
|
||||
|
||||
Default: `parameters.componentSubtitle`
|
||||
Default: `parameters.docs.subtitle`
|
||||
|
||||
Provides the content.
|
||||
|
Loading…
x
Reference in New Issue
Block a user