Skip to content

Angular: Honor stylePreprocessorOptions.includePaths in angular-vite - #35483

Merged
valentinpalkovic merged 1 commit into
storybookjs:nextfrom
brandonroberts:angular-vite/include-paths-alias
Jul 14, 2026
Merged

valentinpalkovic merged 1 commit into
storybookjs:nextfrom
brandonroberts:angular-vite/include-paths-alias

Conversation

@brandonroberts

@brandonroberts brandonroberts commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

The builder schema exposes SCSS search paths as includePaths (matching angular.json), but the framework preset read loadPaths, so the value was silently dropped end-to-end. Read includePaths (with loadPaths accepted as a dart-sass/Vite-spelling alias) and allow both spellings in the builder schemas.

Also fix the docs: the "TypeScript paths" section claimed aliases work out of the box, but nothing maps tsconfig paths into Vite's resolver. Document the vite-tsconfig-paths workaround and how to configure SCSS include paths.

Closes #

What I did

  • Fix: @storybook/angular-vite's preset read stylePreprocessorOptions.loadPaths, but the builder schema (and angular.json) expose the field as includePaths, so user-configured SCSS include paths were silently dropped. The preset now reads includePaths, keeping loadPaths as a dart-sass/Vite-spelling alias, and both spellings are allowed in the start-storybook/build-storybook schemas.
  • Test: Added unit coverage for the exported angularOptionsPlugin (resolution, alias, precedence, sass passthrough, empty config).
  • Docs: Corrected the "TypeScript paths" section — nothing maps tsconfig paths into Vite's resolver, so documented the vite-tsconfig-paths / resolve.alias workaround — and added a "SCSS include paths" section covering includePaths/loadPaths on the builder target and the CLI-only viteFinal path.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

Caution

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Using the angular-vite sandbox (yarn task --task sandbox --start-from auto --template angular-vite/default-ts):

  1. Add an SCSS partial the stories can reference, e.g. src/styles/_theme.scss containing $primary: hotpink;.
  2. Configure the Storybook builder target in angular.json to include that folder, using the Angular spelling:
    "storybook": {
      "builder": "@storybook/angular-vite:start-storybook",
      "options": {
        "stylePreprocessorOptions": { "includePaths": ["src/styles"] }
      }
    }
  3. In a component's SCSS, import the partial by its bare name: @use 'theme'; (relying on the include path, not a relative path).
  4. Run Storybook via ng run <project>:storybook and confirm the story renders with the styles applied — before this fix the build fails to resolve theme because includePaths was ignored.
  5. Repeat with "loadPaths" instead of "includePaths" and confirm it behaves identically (alias).

Docs-only changes (TypeScript paths / SCSS include paths sections of docs/get-started/frameworks/angular-vite.mdx) require no runtime testing — review the rendered MDX for accuracy.

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Declare whether manual QA will be needed for this PR during the next release, through qa:needed or qa:skip

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • New Features

    • Added support for configuring SCSS search paths using either includePaths or loadPaths.
    • SCSS paths are resolved relative to the workspace and passed through with Sass options.
  • Documentation

    • Clarified TypeScript path-alias configuration for Angular Vite projects.
    • Added guidance for configuring SCSS include paths in Storybook.

The builder schema exposes SCSS search paths as `includePaths` (matching
angular.json), but the framework preset read `loadPaths`, so the value was
silently dropped end-to-end. Read `includePaths` (with `loadPaths` accepted
as a dart-sass/Vite-spelling alias) and allow both spellings in the builder
schemas.

Also fix the docs: the "TypeScript paths" section claimed aliases work out of
the box, but nothing maps tsconfig `paths` into Vite's resolver. Document the
`vite-tsconfig-paths` workaround and how to configure SCSS include paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoVAvMxLe3UVXfyh24btWK
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Angular Vite adds loadPaths support alongside includePaths for SCSS preprocessing, resolves configured paths from the workspace root, tests precedence and Sass option forwarding, and updates documentation for TypeScript aliases and SCSS configuration.

Changes

Angular Vite style path configuration

Layer / File(s) Summary
SCSS path alias support
code/frameworks/angular-vite/build-schema.json, code/frameworks/angular-vite/start-schema.json, code/frameworks/angular-vite/src/preset.ts, code/frameworks/angular-vite/src/preset.test.ts
Schemas accept loadPaths; the plugin prefers includePaths, resolves paths into SCSS loadPaths, forwards Sass options, and tests these behaviors.
Configuration documentation
docs/get-started/frameworks/angular-vite.mdx
Documents explicit Vite TypeScript alias configuration and SCSS path setup for Angular builder and Storybook CLI usage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
code/frameworks/angular-vite/build-schema.json (1)

90-109: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Add stylePreprocessorOptions.sass to both Angular builder schemas.

builders.json points at build-schema.json and start-schema.json, so these are the schemas Architect validates. Both still reject sass under stylePreprocessorOptions even though src/preset.ts forwards it into SCSS preprocessorOptions, which blocks valid Angular config like silenceDeprecations.

  • code/frameworks/angular-vite/build-schema.json#L90-L109
  • code/frameworks/angular-vite/start-schema.json#L103-L123
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/frameworks/angular-vite/build-schema.json` around lines 90 - 109, Add a
sass property to stylePreprocessorOptions in both
code/frameworks/angular-vite/build-schema.json lines 90-109 and
code/frameworks/angular-vite/start-schema.json lines 103-123, matching the
forwarded SCSS preprocessorOptions shape so settings such as silenceDeprecations
are accepted while preserving the existing schema validation.
🧹 Nitpick comments (2)
code/frameworks/angular-vite/src/preset.test.ts (1)

12-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mock doesn't follow the spy: true / beforeEach pattern required by guidelines.

This module mock overrides findConfigFile via a manual importOriginal factory instead of { spy: true }, and the override lives in the factory rather than a beforeEach. As per coding guidelines, "Use vi.mock() with the spy: true option for all package and file mocks" and "Implement mock behaviors in beforeEach blocks."

♻️ Suggested refactor to match the guideline pattern
-// The plugin's `config` hook looks up the preview file on disk before reading
-// style options; stub just that lookup so the test stays hermetic.
-vi.mock(import('storybook/internal/common'), async (importOriginal) => ({
-  ...(await importOriginal()),
-  findConfigFile: () => undefined,
-}));
+// The plugin's `config` hook looks up the preview file on disk before reading
+// style options; stub just that lookup so the test stays hermetic.
+vi.mock(import('storybook/internal/common'), { spy: true });
import { findConfigFile } from 'storybook/internal/common';

beforeEach(() => {
  vi.mocked(findConfigFile).mockReturnValue(undefined);
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/frameworks/angular-vite/src/preset.test.ts` around lines 12 - 15, Update
the mock for storybook/internal/common to use the guideline-compliant
spy-enabled vi.mock pattern, import findConfigFile, and move its undefined
return configuration into a beforeEach block using
vi.mocked(findConfigFile).mockReturnValue(undefined). Remove the manual
importOriginal factory override.

Source: Coding guidelines

docs/get-started/frameworks/angular-vite.mdx (1)

236-245: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Incomplete viteFinal snippet — inconsistent with other examples in this doc.

Every other viteFinal example in this file is wrapped in the full StorybookConfig object with export default config; this one is a bare method body, which isn't directly copy-pasteable.

📝 Suggested fix
 ```ts title=".storybook/main.ts"
-async viteFinal(config) {
-  const { mergeConfig } = await import('vite');
-  return mergeConfig(config, {
-    css: { preprocessorOptions: { scss: { loadPaths: ['src/styles'] } } },
-  });
-},
+import type { StorybookConfig } from '`@storybook/angular-vite`';
+
+const config: StorybookConfig = {
+  framework: '`@storybook/angular-vite`',
+  async viteFinal(config) {
+    const { mergeConfig } = await import('vite');
+    return mergeConfig(config, {
+      css: { preprocessorOptions: { scss: { loadPaths: ['src/styles'] } } },
+    });
+  },
+};
+
+export default config;
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/get-started/frameworks/angular-vite.mdx around lines 236 - 245, Expand
the viteFinal example into a complete .storybook/main.ts configuration:
import StorybookConfig, define a typed config object with the Angular Vite
framework and the existing viteFinal implementation, then export it as the
default. Preserve the current SCSS loadPaths behavior.


</details>

<!-- cr-comment:v1:fd9f3e8eb57aafae2b7b0d23 -->

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @code/frameworks/angular-vite/build-schema.json:

  • Around line 90-109: Add a sass property to stylePreprocessorOptions in both
    code/frameworks/angular-vite/build-schema.json lines 90-109 and
    code/frameworks/angular-vite/start-schema.json lines 103-123, matching the
    forwarded SCSS preprocessorOptions shape so settings such as silenceDeprecations
    are accepted while preserving the existing schema validation.

Nitpick comments:
In @code/frameworks/angular-vite/src/preset.test.ts:

  • Around line 12-15: Update the mock for storybook/internal/common to use the
    guideline-compliant spy-enabled vi.mock pattern, import findConfigFile, and move
    its undefined return configuration into a beforeEach block using
    vi.mocked(findConfigFile).mockReturnValue(undefined). Remove the manual
    importOriginal factory override.

In @docs/get-started/frameworks/angular-vite.mdx:

  • Around line 236-245: Expand the viteFinal example into a complete
    .storybook/main.ts configuration: import StorybookConfig, define a typed
    config object with the Angular Vite framework and the existing viteFinal
    implementation, then export it as the default. Preserve the current SCSS
    loadPaths behavior.

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: Organization UI

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `16a87c2c-8fb0-41d3-9241-e0fb2164ca8c`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 4fd2dcc69a132fe1de290b70ec1abfe9702212c9 and 0abc583bbfd9d076123fc0d447ee351a0973828f.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `code/frameworks/angular-vite/build-schema.json`
* `code/frameworks/angular-vite/src/preset.test.ts`
* `code/frameworks/angular-vite/src/preset.ts`
* `code/frameworks/angular-vite/start-schema.json`
* `docs/get-started/frameworks/angular-vite.mdx`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

@brandonroberts brandonroberts changed the title fix(angular-vite): honor stylePreprocessorOptions.includePaths Angular: Honor stylePreprocessorOptions.includePaths in angular-vite Jul 13, 2026
@brandonroberts brandonroberts added ci:docs Run the CI jobs for documentation checks only. documentation qa:skip Pull Requests that do not need any QA. (e.g. documentation) ci:normal Run our default set of CI jobs (choose this for most PRs). and removed ci:docs Run the CI jobs for documentation checks only. labels Jul 13, 2026
@valentinpalkovic
valentinpalkovic requested review from valentinpalkovic and removed request for jonniebigodes and kylegach July 14, 2026 09:50
@valentinpalkovic valentinpalkovic added the patch:yes Bugfix & documentation PR that need to be picked to main branch label Jul 14, 2026
@valentinpalkovic
valentinpalkovic merged commit 77b861c into storybookjs:next Jul 14, 2026
165 of 173 checks passed
@storybook-app-bot

storybook-app-bot Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Package Benchmarks

Commit: 0abc583, ran on 20 July 2026 at 10:49:19 UTC

The following packages have significant changes to their size or dependencies:

storybook

Before After Difference
Dependency count 73 73 0
Self size 21.32 MB 22.16 MB 🚨 +834 KB 🚨
Dependency size 36.44 MB 36.44 MB 0 B
Bundle Size Analyzer Link Link

@storybook/ember

Before After Difference
Dependency count 187 187 0
Self size 13 KB 15 KB 🚨 +2 KB 🚨
Dependency size 30.94 MB 30.94 MB 🚨 +657 B 🚨
Bundle Size Analyzer Link Link

@storybook/nextjs

Before After Difference
Dependency count 533 533 0
Self size 640 KB 663 KB 🚨 +23 KB 🚨
Dependency size 62.28 MB 62.31 MB 🚨 +35 KB 🚨
Bundle Size Analyzer Link Link

@storybook/nextjs-vite

Before After Difference
Dependency count 93 93 0
Self size 1.37 MB 1.39 MB 🚨 +22 KB 🚨
Dependency size 23.97 MB 24.01 MB 🚨 +38 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react-native-web-vite

Before After Difference
Dependency count 122 122 0
Self size 29 KB 30 KB 🚨 +970 B 🚨
Dependency size 25.04 MB 25.08 MB 🚨 +38 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react-vite

Before After Difference
Dependency count 83 83 0
Self size 32 KB 36 KB 🚨 +4 KB 🚨
Dependency size 21.75 MB 21.78 MB 🚨 +34 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react-webpack5

Before After Difference
Dependency count 274 274 0
Self size 23 KB 23 KB 🚨 +789 B 🚨
Dependency size 48.06 MB 48.09 MB 🚨 +35 KB 🚨
Bundle Size Analyzer Link Link

@storybook/tanstack-react

Before After Difference
Dependency count 84 84 0
Self size 112 KB 110 KB 🎉 -2 KB 🎉
Dependency size 21.78 MB 21.82 MB 🚨 +38 KB 🚨
Bundle Size Analyzer Link Link

@storybook/cli

Before After Difference
Dependency count 205 205 0
Self size 827 KB 827 KB 🎉 -168 B 🎉
Dependency size 91.32 MB 92.16 MB 🚨 +834 KB 🚨
Bundle Size Analyzer Link Link

@storybook/codemod

Before After Difference
Dependency count 198 198 0
Self size 32 KB 32 KB 🎉 -43 B 🎉
Dependency size 89.80 MB 90.63 MB 🚨 +834 KB 🚨
Bundle Size Analyzer Link Link

create-storybook

Before After Difference
Dependency count 74 74 0
Self size 1.09 MB 1.09 MB 🎉 -654 B 🎉
Dependency size 57.77 MB 58.60 MB 🚨 +834 KB 🚨
Bundle Size Analyzer node node

@storybook/react

Before After Difference
Dependency count 59 59 0
Self size 1.49 MB 1.52 MB 🚨 +35 KB 🚨
Dependency size 12.45 MB 12.45 MB 🎉 -97 B 🎉
Bundle Size Analyzer Link Link

filipw01 pushed a commit to filipw01/storybook that referenced this pull request Jul 18, 2026
…/include-paths-alias

Angular: Honor stylePreprocessorOptions.includePaths in angular-vite
(cherry picked from commit 77b861c)
@ndelangen ndelangen added patch:done Patch/release PRs already cherry-picked to main/release branch and removed patch:yes Bugfix & documentation PR that need to be picked to main branch labels Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-scan:human ci:normal Run our default set of CI jobs (choose this for most PRs). documentation patch:done Patch/release PRs already cherry-picked to main/release branch qa:skip Pull Requests that do not need any QA. (e.g. documentation)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants