diff --git a/MIGRATION.md b/MIGRATION.md
index 2e2e735fb21f..07aecbbe3973 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -1,5 +1,7 @@
Migration
+- [From version 8.4.x to 8.5.x](#from-version-84x-to-85x)
+ - [Added source code pnael to docs](#added-source-code-pnael-to-docs)
- [From version 8.2.x to 8.3.x](#from-version-82x-to-83x)
- [Removed `experimental_SIDEBAR_BOTTOM` and deprecated `experimental_SIDEBAR_TOP` addon types](#removed-experimental_sidebar_bottom-and-deprecated-experimental_sidebar_top-addon-types)
- [New parameters format for addon backgrounds](#new-parameters-format-for-addon-backgrounds)
@@ -167,7 +169,7 @@
- [Angular: Drop support for calling Storybook directly](#angular-drop-support-for-calling-storybook-directly)
- [Angular: Application providers and ModuleWithProviders](#angular-application-providers-and-modulewithproviders)
- [Angular: Removed legacy renderer](#angular-removed-legacy-renderer)
- - [Angular: initializer functions](#angular-initializer-functions)
+ - [Angular: Initializer functions](#angular-initializer-functions)
- [Next.js: use the `@storybook/nextjs` framework](#nextjs-use-the-storybooknextjs-framework)
- [SvelteKit: needs the `@storybook/sveltekit` framework](#sveltekit-needs-the-storybooksveltekit-framework)
- [Vue3: replaced app export with setup](#vue3-replaced-app-export-with-setup)
@@ -419,6 +421,22 @@
- [Packages renaming](#packages-renaming)
- [Deprecated embedded addons](#deprecated-embedded-addons)
+## From version 8.4.x to 8.5.x
+
+### Added source code pnael to docs
+
+Starting in 8.5, Storybook Docs (`@storybook/addon-docs`) automatically adds a new addon panel to stories that displays a source snippet beneath each story. This works similarly to the existing [source snippet doc block](https://storybook.js.org/docs/writing-docs/doc-blocks#source), but in the story view. It is intended to replace the [Storysource addon](https://storybook.js.org/addons/@storybook/addon-storysource).
+
+If you wish to disable this panel globally, add the following line to your `.storybook/preview.js` project configuration. You can also selectively disable/enable at the story level.
+
+```js
+export default {
+ parameters: {
+ docsSourcePanel: { disable: true },
+ },
+};
+```
+
## From version 8.2.x to 8.3.x
### Removed `experimental_SIDEBAR_BOTTOM` and deprecated `experimental_SIDEBAR_TOP` addon types
diff --git a/code/addons/docs/src/manager.tsx b/code/addons/docs/src/manager.tsx
index 09c371be238b..fdbe0375d369 100644
--- a/code/addons/docs/src/manager.tsx
+++ b/code/addons/docs/src/manager.tsx
@@ -1,31 +1,17 @@
import React from 'react';
import { AddonPanel, type SyntaxHighlighterFormatTypes } from 'storybook/internal/components';
-import { FORCE_RE_RENDER, PRELOAD_ENTRIES } from 'storybook/internal/core-events';
-import { ADDON_ID, PANEL_ID, PARAM_KEY, SNIPPET_RENDERED } from 'storybook/internal/docs-tools';
+import { ADDON_ID, PANEL_ID, SNIPPET_RENDERED } from 'storybook/internal/docs-tools';
import { addons, types, useAddonState, useChannel } from 'storybook/internal/manager-api';
import { Source } from '@storybook/blocks';
-addons.register(ADDON_ID, async (api) => {
- // at this point, the parameters are not yet defined so we can not check whether the addon panel should
- // be added or not. The "PRELOAD_ENTRIES" event seems to be the earliest point in time where the parameters
- // are available
- const isDisabled = await new Promise((resolve) => {
- api.once(PRELOAD_ENTRIES, () => {
- const parameter = api.getCurrentParameter(PARAM_KEY);
- resolve(shouldDisableAddonPanel(parameter));
- });
- });
-
- if (isDisabled) {
- return;
- }
-
+addons.register(ADDON_ID, (api) => {
addons.add(PANEL_ID, {
title: 'Code',
type: types.PANEL,
- paramKey: PARAM_KEY,
+ // disable this with `docsSourcePanel: { disable: true }`
+ paramKey: 'docsSourcePanel',
match: ({ viewMode }) => viewMode === 'story',
render: ({ active }) => {
const [codeSnippet, setSourceCode] = useAddonState<{
@@ -49,24 +35,4 @@ addons.register(ADDON_ID, async (api) => {
);
},
});
-
- api.emit(FORCE_RE_RENDER);
});
-
-const isObject = (value: unknown): value is object => {
- return value != null && typeof value === 'object';
-};
-
-/**
- * Checks whether the addon panel should be disabled by checking the parameter.source.addonPanel
- * property.
- */
-const shouldDisableAddonPanel = (parameter: unknown) => {
- return (
- isObject(parameter) &&
- 'source' in parameter &&
- isObject(parameter.source) &&
- 'addonPanel' in parameter.source &&
- parameter.source.addonPanel === false
- );
-};
diff --git a/code/addons/docs/template/stories/sourcePanel/index.stories.tsx b/code/addons/docs/template/stories/sourcePanel/index.stories.tsx
new file mode 100644
index 000000000000..dd4d2208fe6e
--- /dev/null
+++ b/code/addons/docs/template/stories/sourcePanel/index.stories.tsx
@@ -0,0 +1,15 @@
+export default {
+ component: globalThis.Components.Button,
+ tags: ['autodocs'],
+ parameters: {
+ chromatic: { disable: true },
+ docsSourcePanel: { disable: true },
+ },
+};
+
+export const One = { args: { label: 'One' } };
+export const Two = { args: { label: 'Two' } };
+export const WithSource = {
+ args: { label: 'Three' },
+ parameters: { docsSourcePanel: { disable: false } },
+};