Skip to content

Commit

Permalink
Merge branch 'next' into fix/hover-color-inconsistency
Browse files Browse the repository at this point in the history
  • Loading branch information
cdedreuille authored Sep 19, 2023
2 parents 7f98bff + 63f3384 commit b3983c3
Show file tree
Hide file tree
Showing 16 changed files with 147 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/generate-sandboxes-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
run: yarn wait-on http://localhost:6001
working-directory: ./code
- name: Generate
run: yarn generate-sandboxes --local-registry
run: yarn generate-sandboxes --local-registry --exclude=angular-cli/prerelease
working-directory: ./code
- name: Publish
run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/generate-sandboxes-next.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
run: yarn wait-on http://localhost:6001
working-directory: ./code
- name: Generate
run: yarn generate-sandboxes --local-registry
run: yarn generate-sandboxes --local-registry --exclude=angular-cli/prerelease
working-directory: ./code
- name: Publish
run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=next
Expand Down
46 changes: 46 additions & 0 deletions code/frameworks/nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [next/font/google](#nextfontgoogle)
- [next/font/local](#nextfontlocal)
- [Not supported features of next/font](#not-supported-features-of-nextfont)
- [Mocking fonts during testing](#mocking-fonts-during-testing)
- [Next.js Routing](#nextjs-routing)
- [Overriding defaults](#overriding-defaults)
- [Global Defaults](#global-defaults)
Expand Down Expand Up @@ -271,6 +272,51 @@ The following features are not supported (yet). Support for these features might
- [preload](https://nextjs.org/docs/api-reference/next/font#preload) option gets ignored. Storybook handles Font loading its own way.
- [display](https://nextjs.org/docs/api-reference/next/font#display) option gets ignored. All fonts are loaded with display set to "block" to make Storybook load the font properly.

#### Mocking fonts during testing

Occasionally fetching fonts from Google may fail as part of your Storybook build step. It is highly recommended to mock these requests, as those failures can cause your pipeline to fail as well. Next.js [supports mocking fonts](https://github.com/vercel/next.js/blob/725ddc7371f80cca273779d37f961c3e20356f95/packages/font/src/google/fetch-css-from-google-fonts.ts#L36) via a JavaScript module located where the env var `NEXT_FONT_GOOGLE_MOCKED_RESPONSES` references.

For example, using [GitHub Actions](https://www.chromatic.com/docs/github-actions):

```shell
- uses: chromaui/action@v1
env:
#👇 the location of mocked fonts to use
NEXT_FONT_GOOGLE_MOCKED_RESPONSES: ${{ github.workspace }}/mocked-google-fonts.js
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
```

Your mocked fonts will look something like this:

```js
// mocked-google-fonts.js
//👇 Mocked responses of google fonts with the URL as the key
module.exports = {
'https://fonts.googleapis.com/css?family=Inter:wght@400;500;600;800&display=block': `
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZJhiJ-Ek-_EeAmM.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* more font declarations go here */
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiJ-Ek-_EeA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}`,
};
```

### Next.js Routing

[Next.js's router](https://nextjs.org/docs/routing/introduction) is automatically stubbed for you so that when the router is interacted with, all of its interactions are automatically logged to the Actions ctions panel if you have the [Storybook actions addon](https://storybook.js.org/docs/react/essentials/actions).
Expand Down
1 change: 1 addition & 0 deletions code/frameworks/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"@storybook/addon-actions": "workspace:*",
"@storybook/builder-webpack5": "workspace:*",
"@storybook/core-common": "workspace:*",
"@storybook/core-events": "workspace:*",
"@storybook/node-logger": "workspace:*",
"@storybook/preset-react-webpack": "workspace:*",
"@storybook/preview-api": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
import loaderUtils from 'next/dist/compiled/loader-utils3';
import {
GoogleFontsDownloadError,
GoogleFontsLoadingError,
} from '@storybook/core-events/server-errors';
import type { LoaderOptions } from '../types';

const cssCache = new Map<string, Promise<string>>();
Expand Down Expand Up @@ -33,7 +37,10 @@ export async function getFontFaceDeclarations(options: LoaderOptions) {
cssCache.delete(url);
}
if (fontFaceCSS === null) {
throw Error(`Failed to fetch \`${fontFamily}\` from Google Fonts.`);
throw new GoogleFontsDownloadError({
fontFamily,
url,
});
}

return {
Expand All @@ -45,6 +52,6 @@ export async function getFontFaceDeclarations(options: LoaderOptions) {
variable,
};
} catch (error) {
throw new Error("Google Fonts couldn't be loaded.");
throw new GoogleFontsLoadingError({ error, url });
}
}
5 changes: 3 additions & 2 deletions code/lib/cli/src/sandbox-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ const baseTemplates = {
builder: '@storybook/builder-webpack5',
},
skipTasks: ['e2e-tests-dev', 'bench'],
// TODO: Can be enabled once we re-revert this PR: https://github.com/storybookjs/storybook/pull/24033
// TODO: Should be removed after we merge this PR: https://github.com/storybookjs/storybook/pull/24188
inDevelopment: true,
},
'angular-cli/default-ts': {
Expand Down Expand Up @@ -586,7 +586,8 @@ export const merged: TemplateKey[] = [
];
export const daily: TemplateKey[] = [
...merged,
'angular-cli/prerelease',
// TODO: Should be re-added after we merge this PR: https://github.com/storybookjs/storybook/pull/24188
// 'angular-cli/prerelease',
'cra/default-js',
'react-vite/default-js',
'vue3-vite/default-js',
Expand Down
40 changes: 40 additions & 0 deletions code/lib/core-events/src/errors/server-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,43 @@ export class MissingBuilderError extends StorybookError {
`;
}
}

export class GoogleFontsDownloadError extends StorybookError {
readonly category = Category.FRAMEWORK_NEXTJS;

readonly code = 1;

public readonly documentation =
'https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#nextjs-font-optimization';

constructor(public data: { fontFamily: string; url: string }) {
super();
}

template() {
return dedent`
Failed to fetch \`${this.data.fontFamily}\` from Google Fonts with URL: \`${this.data.url}\`
`;
}
}

export class GoogleFontsLoadingError extends StorybookError {
readonly category = Category.FRAMEWORK_NEXTJS;

readonly code = 2;

public readonly documentation =
'https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#nextjs-font-optimization';

constructor(public data: { error: unknown | Error; url: string }) {
super();
}

template() {
return dedent`
An error occurred when trying to load Google Fonts with URL \`${this.data.url}\`.
${this.data.error instanceof Error ? this.data.error.message : ''}
`;
}
}
2 changes: 1 addition & 1 deletion code/lib/types/src/modules/api-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export interface API_StatusObject {
}

export type API_StatusState = Record<StoryId, Record<string, API_StatusObject>>;
export type API_StatusUpdate = Record<StoryId, API_StatusObject>;
export type API_StatusUpdate = Record<StoryId, API_StatusObject | null>;

export type API_FilterFunction = (
item: API_PreparedIndexEntry & { status: Record<string, API_StatusObject | null> }
Expand Down
8 changes: 5 additions & 3 deletions code/ui/manager/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { renderStorybookUI } from './index';

import { values } from './globals/runtime';
import { Keys } from './globals/types';
import { prepareForTelemetry } from './utils/prepareForTelemetry';
import { prepareForTelemetry, shouldSkipError } from './utils/prepareForTelemetry';

const { FEATURES, CONFIG_TYPE } = global;

Expand Down Expand Up @@ -63,8 +63,10 @@ Object.keys(Keys).forEach((key: keyof typeof Keys) => {
});

global.sendTelemetryError = (error) => {
const channel = global.__STORYBOOK_ADDONS_CHANNEL__;
channel.emit(TELEMETRY_ERROR, prepareForTelemetry(error));
if (!shouldSkipError(error)) {
const channel = global.__STORYBOOK_ADDONS_CHANNEL__;
channel.emit(TELEMETRY_ERROR, prepareForTelemetry(error));
}
};

// handle all uncaught errors at the root of the application and log to telemetry
Expand Down
13 changes: 13 additions & 0 deletions code/ui/manager/src/utils/prepareForTelemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ function getBrowserInfo() {
return browserInfo;
}

// If you're adding errors to filter, please explain why they should be filtered.
const errorMessages = [
// It's a harmless issue with react-resize-detector that supposedly will be gone when we move to React 18.
// https://github.com/maslianok/react-resize-detector/issues/45#issuecomment-1500958024
'ResizeObserver loop completed with undelivered notifications.',
'ResizeObserver loop limit exceeded',
// Safari does not seem to provide any helpful info on window.onerror
// https://bugs.webkit.org/show_bug.cgi?id=132945
'Script error.',
];

export const shouldSkipError = (error: Error) => errorMessages.includes(error?.message);

export function prepareForTelemetry(
originalError: Error & {
fromStorybook?: boolean;
Expand Down
1 change: 1 addition & 0 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7347,6 +7347,7 @@ __metadata:
"@storybook/addon-actions": "workspace:*"
"@storybook/builder-webpack5": "workspace:*"
"@storybook/core-common": "workspace:*"
"@storybook/core-events": "workspace:*"
"@storybook/node-logger": "workspace:*"
"@storybook/preset-react-webpack": "workspace:*"
"@storybook/preview-api": "workspace:*"
Expand Down
1 change: 1 addition & 0 deletions docs/builders/builder-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ To opt into a builder, the user must add it as a dependency and then edit their
<CodeSnippets
paths={[
'common/storybook-vite-builder-install.yarn.js.mdx',
'common/storybook-vite-builder-install.pnpm.js.mdx',
'common/storybook-vite-builder-install.npm.js.mdx',
]}
/>
Expand Down
1 change: 1 addition & 0 deletions docs/builders/vite.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Run the following command to install the builder.
<CodeSnippets
paths={[
'common/storybook-vite-builder-install.yarn.js.mdx',
'common/storybook-vite-builder-install.pnpm.js.mdx',
'common/storybook-vite-builder-install.npm.js.mdx',
]}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```shell
pnpm add --save-dev @storybook/builder-vite
```
28 changes: 19 additions & 9 deletions scripts/sandbox/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,16 @@ const runGenerators = async (
};

export const options = createOptions({
template: {
type: 'string',
description: 'Which template would you like to create?',
templates: {
type: 'string[]',
description: 'Which templates would you like to create?',
values: Object.keys(sandboxTemplates),
},
exclude: {
type: 'string[]',
description: 'Space-delimited list of templates to exclude. Takes precedence over --templates',
promptType: false,
},
localRegistry: {
type: 'boolean',
description: 'Generate reproduction from local registry?',
Expand All @@ -220,7 +225,8 @@ export const options = createOptions({
});

export const generate = async ({
template,
templates,
exclude,
localRegistry,
debug,
}: OptionValues<typeof options>) => {
Expand All @@ -230,11 +236,11 @@ export const generate = async ({
...configuration,
}))
.filter(({ dirName }) => {
if (template) {
return dirName === template;
let include = Array.isArray(templates) ? templates.includes(dirName) : true;
if (Array.isArray(exclude) && include) {
include = !exclude.includes(dirName);
}

return true;
return include;
});

await runGenerators(generatorConfigs, localRegistry, debug);
Expand All @@ -243,7 +249,11 @@ export const generate = async ({
if (require.main === module) {
program
.description('Generate sandboxes from a set of possible templates')
.option('--template <template>', 'Create a single template')
.option('--templates [templates...]', 'Space-delimited list of templates to include')
.option(
'--exclude [templates...]',
'Space-delimited list of templates to exclude. Takes precedence over --templates'
)
.option('--debug', 'Print all the logs to the console')
.option('--local-registry', 'Use local registry', false)
.action((optionValues) => {
Expand Down
3 changes: 2 additions & 1 deletion scripts/tasks/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export const generate: Task = {
const { generate: generateRepro } = await import('../sandbox/generate');

await generateRepro({
template: details.key,
templates: [details.key],
exclude: [],
localRegistry: true,
debug: options.debug,
});
Expand Down

0 comments on commit b3983c3

Please sign in to comment.