diff --git a/code/addons/docs/src/DocsRenderer.tsx b/code/addons/docs/src/DocsRenderer.tsx index b8dc9bd6b780..40c78d803c64 100644 --- a/code/addons/docs/src/DocsRenderer.tsx +++ b/code/addons/docs/src/DocsRenderer.tsx @@ -51,8 +51,9 @@ export class DocsRenderer { return new Promise((resolve, reject) => { import('@mdx-js/react') .then(({ MDXProvider }) => + // We use a `key={}` here to reset the `hasError` state each time we render ErrorBoundary renderElement( - + diff --git a/code/lib/cli/src/automigrate/fixes/add-react.ts b/code/lib/cli/src/automigrate/fixes/add-react.ts index df3fe6f51c3a..420be48912f1 100644 --- a/code/lib/cli/src/automigrate/fixes/add-react.ts +++ b/code/lib/cli/src/automigrate/fixes/add-react.ts @@ -49,11 +49,11 @@ export const addReact: Fix = { return dedent` We've detected that you're using ${dependentsFormatted}. - Starting in Storybook 7 we now require the following peer dependencies: + Starting in Storybook 7, we now require these peer dependencies to render docs: ${additionalDependenciesFormatted} - We can add these for you automatically. + We can add these for you automatically as dev dependencies. More info: ${chalk.yellow( 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#react-peer-dependencies-required' diff --git a/code/lib/cli/src/automigrate/fixes/autodocs-true.ts b/code/lib/cli/src/automigrate/fixes/autodocs-true.ts index 88849eeab315..238c44ebec61 100644 --- a/code/lib/cli/src/automigrate/fixes/autodocs-true.ts +++ b/code/lib/cli/src/automigrate/fixes/autodocs-true.ts @@ -64,7 +64,7 @@ export const autodocsTrue: Fix = { ${autodocsFormatted} ${value === 'tag' ? tagWarning : ''} More info: ${chalk.yellow( - 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#autodocs' + 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#autodocs-changes' )} `; } @@ -77,7 +77,7 @@ export const autodocsTrue: Fix = { ${autodocsFormatted} More info: ${chalk.yellow( - 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#autodocs' + 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#autodocs-changes' )} `; }, diff --git a/code/lib/codemod/src/transforms/__tests__/mdx-to-csf.test.ts b/code/lib/codemod/src/transforms/__tests__/mdx-to-csf.test.ts index 23cd271013b9..10a39af030c8 100644 --- a/code/lib/codemod/src/transforms/__tests__/mdx-to-csf.test.ts +++ b/code/lib/codemod/src/transforms/__tests__/mdx-to-csf.test.ts @@ -138,6 +138,30 @@ test('convert correct story nodes', () => { `); }); +test('convert addon-docs imports', () => { + const input = dedent` + import { Meta } from '@storybook/addon-docs'; + import { Story } from '@storybook/addon-docs/blocks'; + + + + Story + `; + + const mdx = jscodeshift({ source: input, path: 'Foobar.stories.mdx' }); + + expect(mdx).toMatchInlineSnapshot(` + import { Meta } from '@storybook/blocks'; + import { Story } from '@storybook/blocks'; + import * as FoobarStories from './Foobar.stories'; + + + + + + `); +}); + test('convert story nodes with spaces', () => { const input = dedent` import { Meta, Story } from '@storybook/addon-docs'; diff --git a/code/lib/codemod/src/transforms/mdx-to-csf.ts b/code/lib/codemod/src/transforms/mdx-to-csf.ts index ce9dcbddd7f8..18092ab9f986 100644 --- a/code/lib/codemod/src/transforms/mdx-to-csf.ts +++ b/code/lib/codemod/src/transforms/mdx-to-csf.ts @@ -75,8 +75,8 @@ export function transform(source: string, baseName: string): [mdx: string, csf: // rewrite addon docs import visit(root, ['mdxjsEsm'], (node: MdxjsEsm) => { node.value = node.value - .replaceAll('@storybook/addon-docs', '@storybook/blocks') - .replaceAll('@storybook/addon-docs/blocks', '@storybook/blocks'); + .replaceAll('@storybook/addon-docs/blocks', '@storybook/blocks') + .replaceAll('@storybook/addon-docs', '@storybook/blocks'); }); const file = getEsmAst(root); diff --git a/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts b/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts index b7e4e70f6063..d59dca691d14 100644 --- a/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts +++ b/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts @@ -11,7 +11,7 @@ import { normalizeStoriesEntry } from '@storybook/core-common'; import type { NormalizedStoriesSpecifier, StoryIndexer, StoryIndexEntry } from '@storybook/types'; import { loadCsf, getStorySortParameter } from '@storybook/csf-tools'; import { toId } from '@storybook/csf'; -import { logger } from '@storybook/node-logger'; +import { logger, once } from '@storybook/node-logger'; import { StoryIndexGenerator } from './StoryIndexGenerator'; @@ -61,6 +61,7 @@ describe('StoryIndexGenerator', () => { const actual = jest.requireActual('@storybook/csf-tools'); loadCsfMock.mockImplementation(actual.loadCsf); jest.mocked(logger.warn).mockClear(); + jest.mocked(once.warn).mockClear(); }); describe('extraction', () => { const storiesSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry( @@ -925,6 +926,21 @@ describe('StoryIndexGenerator', () => { }); }); + describe('warnings', () => { + it('when entries do not match any files', async () => { + const generator = new StoryIndexGenerator( + [normalizeStoriesEntry('./src/docs2/wrong.js', options)], + options + ); + await generator.initialize(); + await generator.getIndex(); + + expect(once.warn).toHaveBeenCalledTimes(1); + const logMessage = jest.mocked(once.warn).mock.calls[0][0]; + expect(logMessage).toContain(`No story files found for the specified pattern`); + }); + }); + describe('duplicates', () => { it('warns when two MDX entries reference the same CSF file without a name', async () => { const docsErrorSpecifier: NormalizedStoriesSpecifier = normalizeStoriesEntry( diff --git a/code/lib/core-server/src/utils/StoryIndexGenerator.ts b/code/lib/core-server/src/utils/StoryIndexGenerator.ts index 50094e723f1e..5fc8746dd958 100644 --- a/code/lib/core-server/src/utils/StoryIndexGenerator.ts +++ b/code/lib/core-server/src/utils/StoryIndexGenerator.ts @@ -21,7 +21,7 @@ import type { } from '@storybook/types'; import { userOrAutoTitleFromSpecifier, sortStoriesV7 } from '@storybook/preview-api'; import { normalizeStoryPath } from '@storybook/core-common'; -import { logger } from '@storybook/node-logger'; +import { logger, once } from '@storybook/node-logger'; import { getStorySortParameter } from '@storybook/csf-tools'; import { toId } from '@storybook/csf'; import { analyze } from '@storybook/docs-mdx'; @@ -122,6 +122,15 @@ export class StoryIndexGenerator { path.join(this.options.workingDir, specifier.directory, specifier.files) ); const files = await glob(fullGlob); + + if (files.length === 0) { + once.warn( + `No story files found for the specified pattern: ${chalk.blue( + path.join(specifier.directory, specifier.files) + )}` + ); + } + files.sort().forEach((absolutePath: Path) => { const ext = path.extname(absolutePath); if (ext === '.storyshot') { diff --git a/code/lib/csf-tools/package.json b/code/lib/csf-tools/package.json index fcb406dda107..911c3955b5ea 100644 --- a/code/lib/csf-tools/package.json +++ b/code/lib/csf-tools/package.json @@ -1,7 +1,7 @@ { "name": "@storybook/csf-tools", "version": "7.0.0-beta.62", - "description": "", + "description": "Parse and manipulate CSF and Storybook config files", "keywords": [ "storybook" ], diff --git a/code/lib/csf-tools/src/CsfFile.test.ts b/code/lib/csf-tools/src/CsfFile.test.ts index bc6b319ebcc8..2784c6f19f38 100644 --- a/code/lib/csf-tools/src/CsfFile.test.ts +++ b/code/lib/csf-tools/src/CsfFile.test.ts @@ -556,7 +556,7 @@ describe('CsfFile', () => { `, true ) - ).toThrow('CSF: unexpected storiesOf call'); + ).toThrow('Unexpected `storiesOf` usage:'); }); it('function exports', () => { diff --git a/code/lib/csf-tools/src/CsfFile.ts b/code/lib/csf-tools/src/CsfFile.ts index 266dd66027d4..bc0d6400827e 100644 --- a/code/lib/csf-tools/src/CsfFile.ts +++ b/code/lib/csf-tools/src/CsfFile.ts @@ -414,9 +414,10 @@ export class CsfFile { const { callee } = node; if (t.isIdentifier(callee) && callee.name === 'storiesOf') { throw new Error(dedent` - CSF: unexpected storiesOf call ${formatLocation(node, self._fileName)} + Unexpected \`storiesOf\` usage: ${formatLocation(node, self._fileName)}. - More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#story-store-v7 + In SB7, we use the next-generation \`storyStoreV7\` by default, which does not support \`storiesOf\`. + More info, with details about how to opt-out here: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#storystorev7-enabled-by-default `); } }, diff --git a/code/lib/manager-api/package.json b/code/lib/manager-api/package.json index 8d8401d802be..f15c6b106340 100644 --- a/code/lib/manager-api/package.json +++ b/code/lib/manager-api/package.json @@ -1,7 +1,7 @@ { "name": "@storybook/manager-api", "version": "7.0.0-beta.62", - "description": "Core Storybook API & Context", + "description": "Core Storybook Manager API & Context", "keywords": [ "storybook" ], diff --git a/code/lib/telemetry/src/telemetry.ts b/code/lib/telemetry/src/telemetry.ts index a2cbe0e43917..4ae1364a5836 100644 --- a/code/lib/telemetry/src/telemetry.ts +++ b/code/lib/telemetry/src/telemetry.ts @@ -31,6 +31,7 @@ export async function sendTelemetry( : { anonymousId: getAnonymousProjectId(), inCI: Boolean(process.env.CI), + isTTY: process.stdout.isTTY, }; const eventId = nanoid(); const body = { ...rest, eventType, eventId, sessionId, metadata, payload, context }; diff --git a/code/lib/types/package.json b/code/lib/types/package.json index 51b729072084..b7476686de7c 100644 --- a/code/lib/types/package.json +++ b/code/lib/types/package.json @@ -1,7 +1,7 @@ { "name": "@storybook/types", "version": "7.0.0-beta.62", - "description": "Core Storybook Types", + "description": "Core Storybook TS Types", "keywords": [ "storybook" ], diff --git a/code/ui/blocks/src/blocks/useOf.ts b/code/ui/blocks/src/blocks/useOf.ts index 8e5d9d5f7a4f..8c2c55310029 100644 --- a/code/ui/blocks/src/blocks/useOf.ts +++ b/code/ui/blocks/src/blocks/useOf.ts @@ -1,6 +1,5 @@ import type { DocsContextProps, - ModuleExport, ResolvedModuleExportType, ResolvedModuleExportFromType, } from '@storybook/types'; @@ -16,7 +15,7 @@ export type Of = Parameters[0]; * if the resolved module is a component it will include the project annotations */ export const useOf = ( - moduleExportOrType: ModuleExport | TType, + moduleExportOrType: Of, validTypes?: TType[] ): ResolvedModuleExportFromType => { const context = useContext(DocsContext); diff --git a/docs/get-started/introduction.md b/docs/get-started/introduction.md deleted file mode 100644 index df7d0b2e5f28..000000000000 --- a/docs/get-started/introduction.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: 'Introduction to Storybook' ---- - -Storybook is a tool for UI development. It makes development faster and easier by isolating components. This allows you to work on one component at a time. You can develop entire UIs without needing to start up a complex dev stack, force certain data into your database, or navigate around your application. - - - -Use Storybook to build small atomic components and complex pages in your web application. If it's a UI, you can build it with Storybook. - -![Storybook relationship](./storybook-relationship.png) - -Storybook helps you **document** components for reuse and automatically **visually test** your components to prevent bugs. Extend Storybook with an ecosystem of **addons** that help you do things like fine-tune responsive layouts or verify accessibility. - -Storybook integrates with most popular JavaScript UI frameworks and (experimentally) supports server-rendered component frameworks such as [Ruby on Rails](https://rubyonrails.org/). - -## Learning resources - -If you want to learn more about the component-driven approach that Storybook enables, this [site](http://componentdriven.org) is a good place to start. - -If you want a guided tutorial through building a simple application with Storybook in your framework and language, our [tutorials](https://storybook.js.org/tutorials/) have your back. - -Read on to learn Storybook basics and API! diff --git a/docs/get-started/storybook-hero-video-optimized-lg.mp4 b/docs/get-started/storybook-hero-video-optimized-lg.mp4 deleted file mode 100644 index 06dd11ce7742..000000000000 Binary files a/docs/get-started/storybook-hero-video-optimized-lg.mp4 and /dev/null differ diff --git a/docs/get-started/storybook-relationship.png b/docs/get-started/storybook-relationship.png deleted file mode 100644 index 17c31cf9b50f..000000000000 Binary files a/docs/get-started/storybook-relationship.png and /dev/null differ diff --git a/docs/toc.js b/docs/toc.js index 5ed31627fba0..f2f7c8e9072e 100644 --- a/docs/toc.js +++ b/docs/toc.js @@ -1,19 +1,16 @@ module.exports = { toc: [ - { - title: '📕 Why Storybook?', - pathSegment: 'why-storybook', - type: 'link', - }, + { title: '🚀 Get started', pathSegment: 'get-started', type: 'menu', children: [ { - pathSegment: 'introduction', - title: 'Introduction', + pathSegment: 'why-storybook', + title: 'Why Storybook?', type: 'bullet-link', + description: 'Learn why Storybook can help you build better UIs', }, { pathSegment: 'install',