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

Blocks: Add of prop to Subtitle #22552

Merged
merged 18 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<h1>Migration</h1>

- [From version 8.0 to 8.1.0](#from-version-80-to-810)
- [Subtitle block and `parameters.componentSubtitle`](#subtitle-block-and-parameterscomponentsubtitle)
- [From version 7.x to 8.0.0](#from-version-7x-to-800)
- [Portable stories](#portable-stories)
- [Project annotations are now merged instead of overwritten in composeStory](#project-annotations-are-now-merged-instead-of-overwritten-in-composestory)
Expand Down Expand Up @@ -90,17 +92,17 @@
- [Tab addons cannot manually route, Tool addons can filter their visibility via tabId](#tab-addons-cannot-manually-route-tool-addons-can-filter-their-visibility-via-tabid)
- [Removed `config` preset](#removed-config-preset-1)
- [From version 7.5.0 to 7.6.0](#from-version-750-to-760)
- [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated)
- [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated)
- [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated)
- [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop)
- [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react)
- [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated)
- [Using implicit actions during rendering is deprecated](#using-implicit-actions-during-rendering-is-deprecated)
- [typescript.skipBabel deprecated](#typescriptskipbabel-deprecated)
- [Primary doc block accepts of prop](#primary-doc-block-accepts-of-prop)
- [Addons no longer need a peer dependency on React](#addons-no-longer-need-a-peer-dependency-on-react)
- [From version 7.4.0 to 7.5.0](#from-version-740-to-750)
- [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated)
- [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers)
- [`storyStoreV6` and `storiesOf` is deprecated](#storystorev6-and-storiesof-is-deprecated)
- [`storyIndexers` is replaced with `experimental_indexers`](#storyindexers-is-replaced-with-experimental_indexers)
- [From version 7.0.0 to 7.2.0](#from-version-700-to-720)
- [Addon API is more type-strict](#addon-api-is-more-type-strict)
- [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated)
- [Addon API is more type-strict](#addon-api-is-more-type-strict)
- [Addon-controls hideNoControlsWarning parameter is deprecated](#addon-controls-hidenocontrolswarning-parameter-is-deprecated)
- [From version 6.5.x to 7.0.0](#from-version-65x-to-700)
- [7.0 breaking changes](#70-breaking-changes)
- [Dropped support for Node 15 and below](#dropped-support-for-node-15-and-below)
Expand All @@ -126,7 +128,7 @@
- [Deploying build artifacts](#deploying-build-artifacts)
- [Dropped support for file URLs](#dropped-support-for-file-urls)
- [Serving with nginx](#serving-with-nginx)
- [Ignore story files from node_modules](#ignore-story-files-from-node_modules)
- [Ignore story files from node\_modules](#ignore-story-files-from-node_modules)
- [7.0 Core changes](#70-core-changes)
- [7.0 feature flags removed](#70-feature-flags-removed)
- [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates)
Expand All @@ -140,7 +142,7 @@
- [Addon-interactions: Interactions debugger is now default](#addon-interactions-interactions-debugger-is-now-default)
- [7.0 Vite changes](#70-vite-changes)
- [Vite builder uses Vite config automatically](#vite-builder-uses-vite-config-automatically)
- [Vite cache moved to node_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook)
- [Vite cache moved to node\_modules/.cache/.vite-storybook](#vite-cache-moved-to-node_modulescachevite-storybook)
- [7.0 Webpack changes](#70-webpack-changes)
- [Webpack4 support discontinued](#webpack4-support-discontinued)
- [Babel mode v7 exclusively](#babel-mode-v7-exclusively)
Expand Down Expand Up @@ -190,7 +192,7 @@
- [Dropped addon-docs manual babel configuration](#dropped-addon-docs-manual-babel-configuration)
- [Dropped addon-docs manual configuration](#dropped-addon-docs-manual-configuration)
- [Autoplay in docs](#autoplay-in-docs)
- [Removed STORYBOOK_REACT_CLASSES global](#removed-storybook_react_classes-global)
- [Removed STORYBOOK\_REACT\_CLASSES global](#removed-storybook_react_classes-global)
- [7.0 Deprecations and default changes](#70-deprecations-and-default-changes)
- [storyStoreV7 enabled by default](#storystorev7-enabled-by-default)
- [`Story` type deprecated](#story-type-deprecated)
Expand Down Expand Up @@ -403,6 +405,14 @@
- [Packages renaming](#packages-renaming)
- [Deprecated embedded addons](#deprecated-embedded-addons)

## From version 8.0 to 8.1.0

### 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`.

## From version 7.x to 8.0.0

### Portable stories
Expand Down
104 changes: 104 additions & 0 deletions code/ui/blocks/src/blocks/Subtitle.stories.tsx
Original file line number Diff line number Diff line change
@@ -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 ButtonStoriesWithMetaSubtitleAsBoth from '../examples/ButtonWithMetaSubtitleAsBoth.stories';
import * as ButtonStoriesWithMetaSubtitleAsComponentSubtitle from '../examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories';
import * as ButtonStoriesWithMetaSubtitleAsDocsSubtitle from '../examples/ButtonWithMetaSubtitleAsDocsSubtitle.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 OfCSFFileAsBoth: Story = {
args: {
of: ButtonStoriesWithMetaSubtitleAsBoth,
},
parameters: {
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleAsBoth.stories'],
},
};
export const OfCSFFileAsComponentSubtitle: Story = {
name: 'Of CSF File As parameters.componentSubtitle',
args: {
of: ButtonStoriesWithMetaSubtitleAsComponentSubtitle,
},
parameters: {
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories'],
},
};
export const OfCSFFileAsDocsSubtitle: Story = {
name: 'Of CSF File As parameters.docs.subtitle',
args: {
of: ButtonStoriesWithMetaSubtitleAsDocsSubtitle,
},
parameters: {
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleAsDocsSubtitle.stories'],
},
};
export const OfMetaAsBoth: Story = {
args: {
of: ButtonStoriesWithMetaSubtitleAsBoth.default,
},
parameters: {
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleAsBoth.stories'],
},
};
export const OfMetaAsComponentSubtitle: Story = {
name: 'Of Meta As parameters.componentSubtitle',
args: {
of: ButtonStoriesWithMetaSubtitleAsComponentSubtitle.default,
},
parameters: {
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleAsComponentSubtitle.stories'],
},
};
export const OfMetaAsDocsSubtitle: Story = {
name: 'Of Meta As parameters.docs.subtitle',
args: {
of: ButtonStoriesWithMetaSubtitleAsDocsSubtitle.default,
},
parameters: {
relativeCsfPaths: ['../examples/ButtonWithMetaSubtitleAsDocsSubtitle.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 a string passed as a children</Subtitle>,
};
35 changes: 30 additions & 5 deletions code/ui/blocks/src/blocks/Subtitle.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
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 content = children || docsContext.storyById().parameters?.componentSubtitle;
const DEPRECATION_MIGRATION_LINK =
'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#subtitle-block-and-parameterscomponentsubtitle';

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 { componentSubtitle, docs } = preparedMeta.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>
Expand Down
3 changes: 3 additions & 0 deletions code/ui/blocks/src/examples/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,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>;

Expand Down
Original file line number Diff line number Diff line change
@@ -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 WithMetaSubtitleAsBoth: Story = {
args: {
primary: true,
label: 'Button',
},
};
Original file line number Diff line number Diff line change
@@ -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',
},
};
Original file line number Diff line number Diff line change
@@ -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',
},
};
2 changes: 1 addition & 1 deletion code/ui/blocks/src/examples/EmptyExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';

export const EmptyExample = ({}) => (
<div>
This component is not intended to render anything, it simply serves a something to hang
This component is not intended to render anything, it simply serves as something to hang
parameters off
</div>
);
8 changes: 7 additions & 1 deletion docs/api/doc-block-subtitle.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ import { Subtitle } from '@storybook/blocks';

Type: `JSX.Element | string`

Default: `parameters.componentSubtitle`
Default: `parameters.docs.subtitle`

Provides the content.

### `of`

Type: CSF file exports

Specifies which meta's subtitle is displayed.