Skip to content

Commit

Permalink
Merge pull request #19806 from storybookjs/jeppe/sb-898-blocks-descri…
Browse files Browse the repository at this point in the history
…ption

Blocks: Description stories
  • Loading branch information
JReinhold authored Nov 27, 2022
2 parents 47b9d25 + 5f44ba7 commit 11fcfbe
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 20 deletions.
2 changes: 1 addition & 1 deletion code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"storybook:blocks:chromatic": "STORYBOOK_BLOCKS_ONLY=true yarn storybook:ui:chromatic --project-token=${CHROMATIC_TOKEN_STORYBOOK_BLOCKS:-MISSING_PROJECT_TOKEN}",
"storybook:ui": "NODE_OPTIONS=\"--preserve-symlinks --preserve-symlinks-main\" ./lib/cli/bin/index.js dev --port 6006 --config-dir ./ui/.storybook --no-manager-cache",
"storybook:ui:build": "NODE_OPTIONS=\"--preserve-symlinks --preserve-symlinks-main\" ./lib/cli/bin/index.js build --config-dir ./ui/.storybook",
"storybook:ui:chromatic": "yarn chromatic --build-script-name storybook:ui:build --storybook-config-dir ./ui/.storybook --storybook-base-dir ./code/ui --project-token=${CHROMATIC_TOKEN_STORYBOOK_UI:-MISSING_PROJECT_TOKEN} --only-changed --exit-zero-on-changes --exit-once-uploaded",
"storybook:ui:chromatic": "yarn chromatic --build-script-name storybook:ui:build --storybook-config-dir ./ui/.storybook --storybook-base-dir ./code --project-token=${CHROMATIC_TOKEN_STORYBOOK_UI:-MISSING_PROJECT_TOKEN} --only-changed --exit-zero-on-changes --exit-once-uploaded",
"task": "cd .. && yarn task",
"test": "NODE_OPTIONS=--max_old_space_size=4096 jest --config ./jest.config.js",
"test:cli": "npm --prefix lib/cli run test"
Expand Down
23 changes: 23 additions & 0 deletions code/ui/blocks/src/blocks/Description.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Description } from './Description';
import { BooleanControl } from '../controls/Boolean';

const meta: Meta<typeof Description> = {
component: Description,
parameters: {
relativeCsfPaths: ['../controls/Boolean.stories'],
controls: {
include: [],
hideNoControlsWarning: true,
},
},
};
export default meta;

type Story = StoryObj<typeof meta>;

export const BooleanControlJSDoc: Story = {
args: {
of: BooleanControl,
},
};
52 changes: 34 additions & 18 deletions code/ui/blocks/src/blocks/Description.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { FC } from 'react';
import React, { useContext } from 'react';
import { str } from '@storybook/docs-tools';
import { deprecate } from '@storybook/client-logger';
import type { DescriptionProps as PureDescriptionProps } from '../components';
import { Description } from '../components';

Expand All @@ -13,7 +14,6 @@ export enum DescriptionType {
INFO = 'info',
NOTES = 'notes',
DOCGEN = 'docgen',
LEGACY_5_2 = 'legacy-5.2',
AUTO = 'auto',
}

Expand All @@ -22,8 +22,17 @@ type Info = string | any;

interface DescriptionProps {
of?: '.' | Component;
/**
* @deprecated Manually specifying description type is deprecated. In the future all descriptions will be extracted from JSDocs on the meta, story or component.
*/
type?: DescriptionType;
/**
* @deprecated The 'markdown' prop on the Description block is deprecated. Write the markdown directly in the .mdx file instead
*/
markdown?: string;
/**
* @deprecated The 'children' prop on the Description block is deprecated. Write the markdown directly in the .mdx file instead
*/
children?: string;
}

Expand All @@ -34,7 +43,7 @@ const getInfo = (info?: Info) => info && (typeof info === 'string' ? info : str(

const noDescription = (component?: Component): string | null => null;

export const getDescriptionProps = (
export const useDescriptionProps = (
{ of, type, markdown, children }: DescriptionProps,
{ storyById }: DocsContextProps<any>
): PureDescriptionProps => {
Expand All @@ -43,6 +52,12 @@ export const getDescriptionProps = (
return { markdown: children || markdown };
}
const { notes, info, docs } = parameters;
if (Boolean(notes) || Boolean(info)) {
deprecate(
"Using 'parameters.notes' or 'parameters.info' properties to describe stories is deprecated. Write JSDocs directly at the meta, story or component instead."
);
}

const { extractComponentDescription = noDescription, description } = docs || {};
const target = [PRIMARY_STORY].includes(of) ? component : of;

Expand All @@ -57,31 +72,32 @@ export const getDescriptionProps = (
return { markdown: getInfo(info) };
case DescriptionType.NOTES:
return { markdown: getNotes(notes) };
// FIXME: remove in 6.0
case DescriptionType.LEGACY_5_2:
return {
markdown: `
${getNotes(notes) || getInfo(info) || ''}

${extractComponentDescription(target) || ''}
`.trim(),
};
case DescriptionType.DOCGEN:
case DescriptionType.AUTO:
default:
return { markdown: extractComponentDescription(target, { component, ...parameters }) };
}
};

const DescriptionContainer: FC<DescriptionProps> = (props) => {
const DescriptionContainer: FC<DescriptionProps> = (props = { of: PRIMARY_STORY }) => {
const context = useContext(DocsContext);
const { markdown } = getDescriptionProps(props, context);
const { markdown } = useDescriptionProps(props, context);
if (props.type) {
deprecate(
'Manually specifying description type is deprecated. In the future all descriptions will be extracted from JSDocs on the meta, story or component.'
);
}
if (props.markdown) {
deprecate(
"The 'markdown' prop on the Description block is deprecated. Write the markdown directly in the .mdx file instead"
);
}
if (props.children) {
deprecate(
"The 'children' prop on the Description block is deprecated. Write the markdown directly in the .mdx file instead."
);
}
return markdown ? <Description markdown={markdown} /> : null;
};

// since we are in the docs blocks, assume default description if for primary component story
DescriptionContainer.defaultProps = {
of: PRIMARY_STORY,
};

export { DescriptionContainer as Description };
85 changes: 85 additions & 0 deletions code/ui/blocks/src/blocks/internal/InternalDescription.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Description, DescriptionType } from '../Description';
import { BooleanControl } from '../../controls/Boolean';

const meta: Meta<typeof Description> = {
title: 'Blocks/Internal/Description',
component: Description,
parameters: {
relativeCsfPaths: ['../controls/Boolean.stories'],
},
args: {
of: BooleanControl,
},
};
export default meta;

type Story = StoryObj<typeof meta>;

export const InfoType: Story = {
args: {
type: DescriptionType.INFO,
},
};
export const NotesType: Story = {
args: {
type: DescriptionType.NOTES,
},
};
export const DocgenType: Story = {
args: {
type: DescriptionType.DOCGEN,
},
};
export const AutoType: Story = {
args: {
type: DescriptionType.AUTO,
},
};
export const Markdown: Story = {
args: {
markdown: `# My Example Markdown

An \`inline\` codeblock

\`\`\`tsx
// TypeScript React code block
export const MyStory = () => {
return <Button>Click me</Button>;
};
\`\`\`

\`\`\`
code block with with no language
const a = fn({
b: 2,
});
\`\`\`
`,
},
};
export const Children: Story = {
render: (args) => (
<Description {...args}>
{`# My Example Markdown

An \`inline\` codeblock

\`\`\`tsx
// TypeScript React code block
export const MyStory = () => {
return <Button>Click me</Button>;
};
\`\`\`

\`\`\`
code block with with no language
const a = fn({
b: 2,
});
\`\`\`
`}
</Description>
),
};
9 changes: 8 additions & 1 deletion code/ui/blocks/src/controls/Boolean.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,16 @@ const parse = (value: string | null): boolean => value === 'true';

export type BooleanProps = ControlProps<BooleanValue> & BooleanConfig;
/**
* # Boolean control
* # Boolean Control
* Renders a switch toggle with "True" or "False".
* or if the value is `undefined`, renders a button to set the boolean.
*
* ## Example usage
*
* ```
*
* <BooleanControl name="isTrue" value={value} onChange={handleValueChange}/>
* ```
*/
export const BooleanControl: FC<BooleanProps> = ({ name, value, onChange, onBlur, onFocus }) => {
const onSetFalse = useCallback(() => onChange(false), [onChange]);
Expand Down

0 comments on commit 11fcfbe

Please sign in to comment.