diff --git a/docs/generated/api-storybook/executors/build.md b/docs/generated/api-storybook/executors/build.md index 138ffdcfe9900d..706a0bf6c4fb6f 100644 --- a/docs/generated/api-storybook/executors/build.md +++ b/docs/generated/api-storybook/executors/build.md @@ -46,3 +46,15 @@ Default: `true` Type: `boolean` Suppress verbose build output. + +### stylePreprocessorOptions.includePaths + +Type: `array` + +Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects. + +### styles + +Type: `array` + +Global styles to be included in the build. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects. diff --git a/docs/generated/api-storybook/executors/storybook.md b/docs/generated/api-storybook/executors/storybook.md index 3b42edcca32ee9..c5abbb60e056ab 100644 --- a/docs/generated/api-storybook/executors/storybook.md +++ b/docs/generated/api-storybook/executors/storybook.md @@ -85,6 +85,18 @@ Type: `array` Directory where to load static files from, array of strings +### stylePreprocessorOptions.includePaths + +Type: `array` + +Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects. + +### styles + +Type: `array` + +Global styles to be included in the build. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects. + ### watch Default: `true` diff --git a/docs/shared/guides/storybook/plugin-angular.md b/docs/shared/guides/storybook/plugin-angular.md index 792597b46b6287..ab12c6f3ab93ef 100644 --- a/docs/shared/guides/storybook/plugin-angular.md +++ b/docs/shared/guides/storybook/plugin-angular.md @@ -252,6 +252,36 @@ nx build-storybook my-project --projectBuildConfig=my-project:build-storybook > In a pure Angular/Storybook setup (**not** an Nx workspace), the Angular application/project would have an `angular.json` file. That file would have a property called `defaultProject`. In an Nx workspace the `defaultProject` property would be specified in the `nx.json` file. Previously, Nx would try to resolve the `defaultProject` of the workspace, and use the build configuration of that project. In most cases, the `defaultProject`'s build configuration would not work for some other project set up with Storybook, since there would most probably be mismatches in paths or other project-specific options. +### Configuring styles and preprocessor options + +The Angular builder supports including extra entry-point files for styles. Also, in case you use Sass, you can add extra base paths that will be checked for imports. Check out the [Angular Workspace Configuration](https://angular.io/guide/workspace-config#styles-and-scripts-configuration) documentation for more information. In your project's `project.json` file you can use the `styles` and `stylePreprocessorOptions` properties in your `storybook` and `build-storybook` target options, as you would in your Storybook or your Angular builder setup. These will be passed down to the [Storybook builder](https://github.com/storybookjs/storybook/pull/16675) and then to the Angular builder. + +```json + "storybook": { + "executor": "@nrwl/storybook:storybook", + "options": { + ... + "styles": ["some-styles.css"], + "stylePreprocessorOptions": { + "includePaths": ["some-style-paths"] + } + }, + ... + }, + "build-storybook": { + "executor": "@nrwl/storybook:build", + ... + "options": { + ... + "styles": ["some-styles.css"], + "stylePreprocessorOptions": { + "includePaths": ["some-style-paths"] + } + }, + ... + } +``` + ## More Documentation For more on using Storybook, see the [official Storybook documentation](https://storybook.js.org/docs/basics/introduction/). diff --git a/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts b/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts index 471f800bf9bf82..94e3f761a7ac3e 100644 --- a/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts +++ b/packages/storybook/src/executors/build-storybook/build-storybook.impl.spec.ts @@ -44,6 +44,10 @@ describe('Build storybook', () => { uiFramework, outputPath, projectBuildConfig: 'proj', + stylePreprocessorOptions: { + includePaths: ['my-path/my-style-options'], + }, + styles: ['my-other-path/my-other-styles.scss'], config, }; diff --git a/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts b/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts index cb7b8f55ace701..256224a5a629ca 100644 --- a/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts +++ b/packages/storybook/src/executors/build-storybook/build-storybook.impl.ts @@ -4,6 +4,7 @@ import 'dotenv/config'; import { CommonNxStorybookConfig } from '../models'; import { getStorybookFrameworkPath, + normalizeAngularBuilderStylesOptions, resolveCommonStorybookOptionMapper, runStorybookSetupCheck, } from '../utils'; @@ -21,8 +22,9 @@ export default async function buildStorybookExecutor( logger.info(`NX ui framework: ${options.uiFramework}`); const frameworkPath = getStorybookFrameworkPath(options.uiFramework); - const { default: frameworkOptions } = await import(frameworkPath); + + options = normalizeAngularBuilderStylesOptions(options, options.uiFramework); const option = storybookOptionMapper(options, frameworkOptions, context); // print warnings diff --git a/packages/storybook/src/executors/build-storybook/schema.json b/packages/storybook/src/executors/build-storybook/schema.json index 01909d742c9d58..1db8be711b631d 100644 --- a/packages/storybook/src/executors/build-storybook/schema.json +++ b/packages/storybook/src/executors/build-storybook/schema.json @@ -18,6 +18,20 @@ "type": "string", "description": "Workspace project where Storybook reads the Webpack config from" }, + "styles": { + "type": "array", + "description": "Global styles to be included in the build. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "items": { + "$ref": "#/definitions/extraEntryPoint" + } + }, + "stylePreprocessorOptions.includePaths": { + "description": "Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "type": "array", + "items": { + "type": "string" + } + }, "config": { "type": "object", "description": ".storybook configuration", @@ -51,5 +65,36 @@ "default": true } }, + "definitions": { + "extraEntryPoint": { + "oneOf": [ + { + "type": "object", + "properties": { + "input": { + "type": "string", + "description": "The file to include." + }, + "bundleName": { + "type": "string", + "pattern": "^[\\w\\-.]*$", + "description": "The bundle name for this extra entry point." + }, + "inject": { + "type": "boolean", + "description": "If the bundle will be referenced in the HTML file.", + "default": true + } + }, + "additionalProperties": false, + "required": ["input"] + }, + { + "type": "string", + "description": "The file to include." + } + ] + } + }, "required": ["uiFramework", "config"] } diff --git a/packages/storybook/src/executors/models.ts b/packages/storybook/src/executors/models.ts index b3b7c8de69d86a..b695d8a7594188 100644 --- a/packages/storybook/src/executors/models.ts +++ b/packages/storybook/src/executors/models.ts @@ -16,5 +16,9 @@ export interface CommonNxStorybookConfig { | '@storybook/svelte' | '@storybook/react-native'; projectBuildConfig?: string; + styles?: any[]; + stylePreprocessorOptions?: { + includePaths?: string[]; + }; config: StorybookConfig; } diff --git a/packages/storybook/src/executors/storybook/schema.json b/packages/storybook/src/executors/storybook/schema.json index 64f870affd199c..6289a9f90344fd 100644 --- a/packages/storybook/src/executors/storybook/schema.json +++ b/packages/storybook/src/executors/storybook/schema.json @@ -58,6 +58,20 @@ "type": "string", "description": "Workspace project where Storybook reads the Webpack config from" }, + "styles": { + "type": "array", + "description": "Global styles to be included in the build. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "items": { + "$ref": "#/definitions/extraEntryPoint" + } + }, + "stylePreprocessorOptions.includePaths": { + "description": "Options to pass to style preprocessors. The paths to include. Paths will be resolved to workspace root. This is for Angular projects only, as an option of the Storybook Angular builder. It will be ignored in non-Angular projects.", + "type": "array", + "items": { + "type": "string" + } + }, "config": { "type": "object", "description": ".storybook configuration", @@ -91,5 +105,36 @@ "default": true } }, + "definitions": { + "extraEntryPoint": { + "oneOf": [ + { + "type": "object", + "properties": { + "input": { + "type": "string", + "description": "The file to include." + }, + "bundleName": { + "type": "string", + "pattern": "^[\\w\\-.]*$", + "description": "The bundle name for this extra entry point." + }, + "inject": { + "type": "boolean", + "description": "If the bundle will be referenced in the HTML file.", + "default": true + } + }, + "additionalProperties": false, + "required": ["input"] + }, + { + "type": "string", + "description": "The file to include." + } + ] + } + }, "required": ["uiFramework", "config"] } diff --git a/packages/storybook/src/executors/storybook/storybook.impl.ts b/packages/storybook/src/executors/storybook/storybook.impl.ts index c9bed0f39e8f1f..2256087289ce52 100644 --- a/packages/storybook/src/executors/storybook/storybook.impl.ts +++ b/packages/storybook/src/executors/storybook/storybook.impl.ts @@ -4,6 +4,7 @@ import 'dotenv/config'; import { CommonNxStorybookConfig } from '../models'; import { getStorybookFrameworkPath, + normalizeAngularBuilderStylesOptions, resolveCommonStorybookOptionMapper, runStorybookSetupCheck, } from '../utils'; @@ -24,8 +25,9 @@ export default async function* storybookExecutor( context: ExecutorContext ): AsyncGenerator<{ success: boolean }> { let frameworkPath = getStorybookFrameworkPath(options.uiFramework); - const frameworkOptions = (await import(frameworkPath)).default; + + options = normalizeAngularBuilderStylesOptions(options, options.uiFramework); const option = storybookOptionMapper(options, frameworkOptions, context); // print warnings diff --git a/packages/storybook/src/executors/utils.ts b/packages/storybook/src/executors/utils.ts index a30c22a0d487a5..08b17b0f198f5d 100644 --- a/packages/storybook/src/executors/utils.ts +++ b/packages/storybook/src/executors/utils.ts @@ -18,7 +18,9 @@ import { findOrCreateConfig, readCurrentWorkspaceStorybookVersionFromExecutor, } from '../utils/utilities'; +import { StorybookBuilderOptions } from './build-storybook/build-storybook.impl'; import { CommonNxStorybookConfig } from './models'; +import { StorybookExecutorOptions } from './storybook/storybook.impl'; export interface NodePackage { name: string; @@ -322,3 +324,26 @@ export function findStorybookAndBuildTargets(targets: { }); return returnObject; } + +export function normalizeAngularBuilderStylesOptions( + builderOptions: StorybookBuilderOptions | StorybookExecutorOptions, + uiFramework: + | '@storybook/angular' + | '@storybook/react' + | '@storybook/html' + | '@storybook/web-components' + | '@storybook/vue' + | '@storybook/vue3' + | '@storybook/svelte' + | '@storybook/react-native' +): StorybookBuilderOptions | StorybookExecutorOptions { + if (uiFramework !== '@storybook/angular') { + if (builderOptions.styles) { + delete builderOptions.styles; + } + if (builderOptions.stylePreprocessorOptions) { + delete builderOptions.stylePreprocessorOptions; + } + } + return builderOptions; +}