Skip to content

Actions: Warn instead of throw for implicit actions in docs renders#34505

Open
EricMChavez wants to merge 2 commits intostorybookjs:nextfrom
EricMChavez:fix/33758-docs-implicit-actions
Open

Actions: Warn instead of throw for implicit actions in docs renders#34505
EricMChavez wants to merge 2 commits intostorybookjs:nextfrom
EricMChavez:fix/33758-docs-implicit-actions

Conversation

@EricMChavez
Copy link
Copy Markdown

@EricMChavez EricMChavez commented Apr 9, 2026

Closes #33758

What I did

When a story is embedded in a docs page (viewMode: 'docs') and an arg matched by actions.argTypesRegex (e.g. ^on.*) fires during render — for example a Vue 3 component emitting an event from onMounted — the implicit action handler currently throws ImplicitActionsDuringRendering, which crashes the entire docs page.

The throw exists to protect play functions from accidentally relying on implicit actions, but docs renders have no play-function semantics. This PR downgrades the throw to a console.warn when the active StoryRender has viewMode === 'docs'. Story view (viewMode === 'story') is unchanged, so play-function safety is preserved.

The discriminator is reliable: docs-embedded stories are mounted via Preview.renderStoryToElement, which hard-codes 'docs' as the StoryRender view mode, and ViewMode is exhaustively 'story' | 'docs'.

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

New unit tests in code/core/src/actions/runtime/action.test.ts:

  • viewMode: 'story' + phase: 'rendering' → throws (preserves play-function safety)
  • viewMode: 'docs' + phase: 'rendering' → warns, no throw
  • no active render → no-op

Manual testing

  1. Use the reporter's repro: https://repro-storybook-implicit-action.vercel.app/
  2. Reproduce locally with a Vue 3 sandbox:
    • yarn task sandbox --template vue3-vite/default-ts --start-from auto
    • Add a component that emits an event from onMounted and a story with an onBlabla argType (no matching args entry).
    • Open the story's docs page; before this fix it crashes with ImplicitActionsDuringRendering, after this fix the docs page renders and the warning shows in the console.

Documentation

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

This is a behavior fix, not a deprecation — no migration entry added. Happy to add a note if reviewers prefer.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Added tests covering implicit action behavior across story, docs, and no-render scenarios to ensure correct warn/throw behavior and global-state isolation.
  • Bug Fixes

    • Implicit actions during docs rendering now emit warnings instead of throwing errors; implicit actions during story rendering still throw, and actions with no active render remain allowed.

Stories embedded in a docs page render with viewMode === 'docs' and have
no play function semantics, so an implicit action firing during a
lifecycle hook (e.g. Vue 3 onMounted emitting an event) should warn
rather than crash the entire docs page.

Fixes storybookjs#33758

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 85d67c35-4002-4fdf-ab71-6d1ebbc2c9d6

📥 Commits

Reviewing files that changed from the base of the PR and between 61c4c0a and 3de4a90.

📒 Files selected for processing (2)
  • code/core/src/actions/runtime/action.test.ts
  • code/core/src/actions/runtime/action.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • code/core/src/actions/runtime/action.ts
  • code/core/src/actions/runtime/action.test.ts

📝 Walkthrough

Walkthrough

Modify implicit-action handling so that when a story renderer exists with viewMode: 'docs', implicit actions are treated as deprecated (emit warnings) regardless of globalThis.FEATURES.disallowImplicitActionsInRenderV8. Add tests covering docs, story, and no-render scenarios.

Changes

Cohort / File(s) Summary
Implicit Action Tests
code/core/src/actions/runtime/action.test.ts
Add Vitest suite that mocks Storybook preview API and global state; asserts implicit-action behavior for: active story render (throws), active docs render (warns), and no active render (no throw). Preserves and restores globals and mocks.
Implicit Action Runtime Logic
code/core/src/actions/runtime/action.ts
Adjust implicit-action deprecation check: when storyRenderer.viewMode === 'docs', treat as deprecated regardless of globalThis.FEATURES.disallowImplicitActionsInRenderV8. Replace console.warn calls with logger.warn.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes


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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
code/core/src/actions/runtime/action.ts (1)

67-80: ⚠️ Potential issue | 🟠 Major

Use Storybook client logger instead of console.warn in runtime code.

Line 79 uses raw console.warn in a client-side runtime code path. Replace it with storybook/internal/client-logger for consistency with the repository's logging standards.

Proposed fix
 import { ImplicitActionsDuringRendering } from 'storybook/internal/preview-errors';
+import { logger } from 'storybook/internal/client-logger';
 import type { Renderer } from 'storybook/internal/types';
@@
         if (deprecated) {
-          console.warn(error);
+          logger.warn(error);
         } else {
           throw error;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/core/src/actions/runtime/action.ts` around lines 67 - 80, Replace the
raw console.warn call with Storybook's client logger: import the logger from
'storybook/internal/client-logger' and call its warn method with the
ImplicitActionsDuringRendering error instead of console.warn; update the block
where inDocs/deprecated and error (created from ImplicitActionsDuringRendering
using storyRenderer.phase and name) are defined to use clientLogger.warn(error)
so runtime logging follows the repo standard.
🧹 Nitpick comments (1)
code/core/src/actions/runtime/action.test.ts (1)

12-13: Restore global keys by original presence, not only original value.

Lines 20-21 always reassign properties, which can leave keys present with undefined even if they were absent originally. That can affect later tests that use 'key' in global checks.

Proposed fix
 describe('action handler — implicit actions', () => {
+  const hadPreview = '__STORYBOOK_PREVIEW__' in (global as any);
+  const hadFeatures = 'FEATURES' in (globalThis as any);
   const originalPreview = (global as any).__STORYBOOK_PREVIEW__;
   const originalFeatures = (globalThis as any).FEATURES;
@@
   afterEach(() => {
-    (global as any).__STORYBOOK_PREVIEW__ = originalPreview;
-    (globalThis as any).FEATURES = originalFeatures;
+    if (hadPreview) {
+      (global as any).__STORYBOOK_PREVIEW__ = originalPreview;
+    } else {
+      delete (global as any).__STORYBOOK_PREVIEW__;
+    }
+    if (hadFeatures) {
+      (globalThis as any).FEATURES = originalFeatures;
+    } else {
+      delete (globalThis as any).FEATURES;
+    }
     vi.restoreAllMocks();
   });

Also applies to: 19-22

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/core/src/actions/runtime/action.test.ts` around lines 12 - 13, The test
saves originalPreview and originalFeatures but restores them unconditionally,
which can leave properties set to undefined when they were originally absent;
update the teardown to record presence (e.g., hadPreview/hadFeatures) when
capturing (global as any).__STORYBOOK_PREVIEW__ and (globalThis as any).FEATURES
and then on restore set the property back only if it was originally present
(assign originalPreview/originalFeatures) otherwise delete the property (use
delete (global as any).__STORYBOOK_PREVIEW__ and delete (globalThis as
any).FEATURES) so key presence matches original state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@code/core/src/actions/runtime/action.test.ts`:
- Line 5: Change the relative import in action.test.ts to include the explicit
.ts extension: locate the import statement "import { action } from './action';"
and update it to import from './action.ts' so it follows the repository's import
rule; ensure any other imports in this test file follow the same explicit .ts
extension convention.
- Around line 7-9: The test uses vi.mock('storybook/preview-api') without spy:
true and has an inline vi.spyOn(...) inside a test; update the module mock to
vi.mock('storybook/preview-api', { spy: true }, ...) and move any inline
vi.spyOn(...) mockImplementation calls out of the test into the test suite's
beforeEach so all mock behaviors for the file (action.test.ts) are declared in
beforeEach; ensure the spy created via vi.mock supports spyOn and the prior
inline mockImplementation is replicated in that beforeEach setup.

---

Outside diff comments:
In `@code/core/src/actions/runtime/action.ts`:
- Around line 67-80: Replace the raw console.warn call with Storybook's client
logger: import the logger from 'storybook/internal/client-logger' and call its
warn method with the ImplicitActionsDuringRendering error instead of
console.warn; update the block where inDocs/deprecated and error (created from
ImplicitActionsDuringRendering using storyRenderer.phase and name) are defined
to use clientLogger.warn(error) so runtime logging follows the repo standard.

---

Nitpick comments:
In `@code/core/src/actions/runtime/action.test.ts`:
- Around line 12-13: The test saves originalPreview and originalFeatures but
restores them unconditionally, which can leave properties set to undefined when
they were originally absent; update the teardown to record presence (e.g.,
hadPreview/hadFeatures) when capturing (global as any).__STORYBOOK_PREVIEW__ and
(globalThis as any).FEATURES and then on restore set the property back only if
it was originally present (assign originalPreview/originalFeatures) otherwise
delete the property (use delete (global as any).__STORYBOOK_PREVIEW__ and delete
(globalThis as any).FEATURES) so key presence matches original state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9c3dc644-3264-4743-9082-a60e99d976e9

📥 Commits

Reviewing files that changed from the base of the PR and between 7022915 and 61c4c0a.

📒 Files selected for processing (2)
  • code/core/src/actions/runtime/action.test.ts
  • code/core/src/actions/runtime/action.ts

Comment thread code/core/src/actions/runtime/action.test.ts Outdated
Comment thread code/core/src/actions/runtime/action.test.ts
- Use storybook client logger instead of raw console.warn
- Add explicit .ts extension to relative import
- Move vi.spyOn to beforeEach for consistent mock setup
- Restore globals by original presence in test teardown

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@valentinpalkovic
Copy link
Copy Markdown
Contributor

Hi @EricMChavez,

Due to a recent high volume of unreviewed AI-generated PRs, we are requesting verification and proof that the implemented fix actually works. Please provide a simple GIF/Video or image of how the fix works, optimally with before-and-after comparisons.

Thank you for your understanding!

@EricMChavez
Copy link
Copy Markdown
Author

Screenshot Before: implicit actions block render in docs

Screenshot Before

After: implicit actions throw warning, does not block render in docs

Screenshot After

Note: Story view still throws error for implicit actions
Screenshot Story

@valentinpalkovic valentinpalkovic moved this from Human verification to Empathy Queue (prioritized) in Core Team Projects Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Empathy Queue (prioritized)

Development

Successfully merging this pull request may close these issues.

[Bug]: "Implicit actions can not be used" error when defining argTypes with on without handler in doc file

2 participants