Skip to content

feat(storybook): add @fluentui/react-storybook-addon-playground with in-browser TSX playground (#36728) - #36744

Draft
Dmytro Kirpa (dmytrokirpa) wants to merge 23 commits into
masterfrom
experimental/storybook-playground
Draft

Dmytro Kirpa (dmytrokirpa) wants to merge 23 commits into
masterfrom
experimental/storybook-playground

Conversation

@dmytrokirpa

Copy link
Copy Markdown
Contributor

Previous Behavior

New Behavior

Related Issue(s)

  • Fixes #

…in-browser TSX playground (#36728)

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown

📊 Bundle size report

✅ No changes found

Copilot AI 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.

🟡 Changes recommended

Runtime correctness, accessibility, peer-version, CSS transformation, and release metadata issues remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds a configurable Storybook addon providing an in-browser Monaco TSX playground, sandboxed preview, typings, formatting, and shareable state.

Changes:

  • Implements the playground shell, runtime, compiler, and Storybook integration.
  • Adds tests, public APIs, documentation, and build configuration.
  • Enables the addon for headless-component Storybook and docsite builds.
File summaries
File Description
.github/CODEOWNERS Assigns addon ownership.
apps/public-docsite-v9-headless/package.json Adds the addon dependency.
apps/public-docsite-v9-headless/project.json Adds build dependencies.
change/@fluentui-react-storybook-addon-export-to-sandbox-bfb6dbfb-a9e5-47e0-b04d-be8d1f1d4399.json Records sandbox-addon fix.
change/@fluentui-react-storybook-addon-playground-99650265-91f2-458b-bfdb-cf5dda68c498.json Records playground package change.
packages/react-components/react-headless-components-preview/stories/.storybook/css.d.ts Declares CSS imports.
packages/react-components/react-headless-components-preview/stories/.storybook/main.js Configures playground modules and setup.
packages/react-components/react-headless-components-preview/stories/.storybook/playground.setup.tsx Defines headless playground presentation.
packages/react-components/react-headless-components-preview/stories/.storybook/preview.js Loads addon styling.
packages/react-components/react-headless-components-preview/stories/.storybook/tsconfig.json Includes setup sources.
packages/react-components/react-headless-components-preview/stories/project.json Adds Storybook build prerequisites.
packages/react-components/react-storybook-addon-export-to-sandbox/src/sandbox-utils.ts Excludes playground buttons from lookup.
packages/react-components/react-storybook-addon-playground/.babelrc.json Configures Babel transforms.
packages/react-components/react-storybook-addon-playground/.swcrc Excludes separately bundled sources.
packages/react-components/react-storybook-addon-playground/LICENSE Adds package license.
packages/react-components/react-storybook-addon-playground/README.md Documents installation and usage.
packages/react-components/react-storybook-addon-playground/config/api-extractor.json Configures API extraction.
packages/react-components/react-storybook-addon-playground/config/tests.js Adds Jest setup.
packages/react-components/react-storybook-addon-playground/eslint.config.js Configures React and DOM linting.
packages/react-components/react-storybook-addon-playground/etc/react-storybook-addon-playground.api.md Records public API surface.
packages/react-components/react-storybook-addon-playground/jest.config.js Configures unit tests.
packages/react-components/react-storybook-addon-playground/package.json Adds dependencies and exports.
packages/react-components/react-storybook-addon-playground/preset.js Serves playground assets.
packages/react-components/react-storybook-addon-playground/project.json Adds playground build target.
packages/react-components/react-storybook-addon-playground/src/decorators/withOpenInPlaygroundButton.spec.ts Tests Docs button integration.
packages/react-components/react-storybook-addon-playground/src/decorators/withOpenInPlaygroundButton.ts Adds the Docs launcher button.
packages/react-components/react-storybook-addon-playground/src/defaultSetup.tsx Defines default Fluent setup.
packages/react-components/react-storybook-addon-playground/src/index.ts Exports public APIs.
packages/react-components/react-storybook-addon-playground/src/playground/Editor.styles.ts Styles the editor container.
packages/react-components/react-storybook-addon-playground/src/playground/Editor.tsx Integrates Monaco models and actions.
packages/react-components/react-storybook-addon-playground/src/playground/Playground.styles.ts Styles the playground shell.
packages/react-components/react-storybook-addon-playground/src/playground/Playground.tsx Implements the main playground UI.
packages/react-components/react-storybook-addon-playground/src/playground/Preview.styles.ts Styles the preview frame.
packages/react-components/react-storybook-addon-playground/src/playground/Preview.tsx Coordinates the sandboxed preview.
packages/react-components/react-storybook-addon-playground/src/playground/compiler.ts Compiles TSX through Monaco.
packages/react-components/react-storybook-addon-playground/src/playground/cssModules.spec.ts Tests CSS-module processing.
packages/react-components/react-storybook-addon-playground/src/playground/cssModules.ts Transforms CSS-module sources.
packages/react-components/react-storybook-addon-playground/src/playground/editorTheme.ts Defines Monaco themes.
packages/react-components/react-storybook-addon-playground/src/playground/formatter.spec.ts Tests Prettier integration.
packages/react-components/react-storybook-addon-playground/src/playground/formatter.ts Registers document formatters.
packages/react-components/react-storybook-addon-playground/src/playground/main.tsx Bootstraps the standalone app.
packages/react-components/react-storybook-addon-playground/src/playground/monaco.ts Configures Monaco and workers.
packages/react-components/react-storybook-addon-playground/src/playground/playground.html Provides the shell document.
packages/react-components/react-storybook-addon-playground/src/playground/runner.spec.ts Tests module validation.
packages/react-components/react-storybook-addon-playground/src/playground/runner.ts Validates compiled imports.
packages/react-components/react-storybook-addon-playground/src/playground/runtime.ts Loads and resolves runtime manifests.
packages/react-components/react-storybook-addon-playground/src/playground/sandbox.ts Builds the isolated execution document.
packages/react-components/react-storybook-addon-playground/src/playground/shortcuts.spec.ts Tests shortcut labels.
packages/react-components/react-storybook-addon-playground/src/playground/shortcuts.ts Provides platform shortcuts.
packages/react-components/react-storybook-addon-playground/src/playground/themes.ts Defines shell themes.
packages/react-components/react-storybook-addon-playground/src/playground/typings.ts Registers Monaco declarations.
packages/react-components/react-storybook-addon-playground/src/playground/useMediaQuery.ts Tracks responsive queries.
packages/react-components/react-storybook-addon-playground/src/playground/useSplitPane.spec.ts Tests split-pane behavior.
packages/react-components/react-storybook-addon-playground/src/playground/useSplitPane.ts Implements pane resizing.
packages/react-components/react-storybook-addon-playground/src/preset/preset.ts Exposes the Webpack hook.
packages/react-components/react-storybook-addon-playground/src/preset/preview.ts Registers the decorator.
packages/react-components/react-storybook-addon-playground/src/public-types.ts Defines addon configuration types.
packages/react-components/react-storybook-addon-playground/src/setup.ts Defines setup and manifest APIs.
packages/react-components/react-storybook-addon-playground/src/styles.css Styles the Docs launcher.
packages/react-components/react-storybook-addon-playground/src/types.ts Extends Storybook context types.
packages/react-components/react-storybook-addon-playground/src/url.spec.ts Tests URL-state handling.
packages/react-components/react-storybook-addon-playground/src/url.ts Encodes shareable playground state.
packages/react-components/react-storybook-addon-playground/src/webpack.spec.ts Tests runtime-entry generation.
packages/react-components/react-storybook-addon-playground/src/webpack.ts Emits runtime assets and typings.
packages/react-components/react-storybook-addon-playground/tools/collect-typings.js Collects transitive declarations.
packages/react-components/react-storybook-addon-playground/tools/collect-typings.spec.js Tests declaration collection.
packages/react-components/react-storybook-addon-playground/tsconfig.json References playground compilation.
packages/react-components/react-storybook-addon-playground/tsconfig.lib.json Excludes bundled playground files.
packages/react-components/react-storybook-addon-playground/tsconfig.playground.json Configures shell type checking.
packages/react-components/react-storybook-addon-playground/tsconfig.spec.json Configures test type checking.
packages/react-components/react-storybook-addon-playground/webpack.playground.config.js Bundles the standalone shell.
syncpack.config.js Preserves Monaco version policy.
tsconfig.base.all.json Adds the workspace package alias.
tsconfig.base.json Adds the package path mapping.
yarn.lock Records workspace dependencies.
Review details
  • Files reviewed: 63/65 changed files
  • Comments generated: 11
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

Copy link
Copy Markdown

Pull request demo site: URL

Comment thread apps/public-docsite-v9-headless/package.json

Copilot AI 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.

🟡 Changes recommended

Cross-platform option discovery, CSS error handling, subpath typings, token usage, and forced-colors focus visibility remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

packages/react-components/react-storybook-addon-playground/package.json:52

  • The ./setup subpath resolves types from the root declaration barrel but runtime values from lib/setup.js. This makes root-only values such as createPlaygroundUrl appear importable from @fluentui/react-storybook-addon-playground/setup, although that runtime module does not export them. Point the types condition at the declaration generated from setup.ts.
    packages/react-components/react-storybook-addon-playground/src/styles.css:27
  • Removing the outline leaves this box shadow as the only keyboard-focus indicator. Box shadows are suppressed in Windows forced-colors mode, so the new button can have no visible focus state there; retain a solid outline (or add an explicit forced-colors rule) instead.
    packages/react-components/react-storybook-addon-playground/src/playground/Playground.styles.ts:40
  • The new shell stylesheet hardcodes spacing and typography values throughout (for example 16px here) even though it is rendered under FluentProvider. docs/architecture/design-tokens.md:3-19 requires tokens for spacing, fonts, radii, strokes, and durations so these values remain theme-consistent. Replace the themeable literals across this stylesheet with the corresponding Fluent tokens.
  • Files reviewed: 72/74 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread packages/react-components/react-storybook-addon-playground/src/webpack.ts Outdated
Compile initial CSS through the guarded debounced run path so malformed shared playground CSS reports an error instead of throwing during React render.

Copilot AI 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.

🟡 Changes recommended

URL-state loss, declaration-resolution failures, an inconsistent subpath API, and accessibility issues remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (6)

Previously missed (6) — in code that hasn't changed since the last review.

packages/react-components/react-storybook-addon-playground/src/playground/Playground.tsx:676

  • This hint is false after a component render error. The sandbox replaces the previous tree with a new keyed error boundary, whose error state renders null, so a previously successful preview becomes blank while this message says it is still shown. Either preserve the prior element on sandbox render failures or track whether each error occurred before root.render and only show this hint when the old preview was retained.
    packages/react-components/react-storybook-addon-playground/src/styles.css:29
  • Removing the native outline leaves this button with only a box-shadow focus indicator. Forced-colors mode suppresses box shadows, so keyboard focus becomes invisible. Keep an outline (it can be transparent normally and use Highlight in forced colors) in addition to the visual inset treatment.
    packages/react-components/react-storybook-addon-playground/src/url.ts:35
  • decodeCode is not the inverse of encodeCode for a valid empty source: decoding encodeCode('') yields '', which this line turns into null. decodePlaygroundStateFromHash then rejects it and Playground also skips hash synchronization for empty code, so clearing the editor and refreshing/share-linking restores the default or previous source instead of the current empty program. Preserve empty strings and update the downstream truthiness checks to distinguish only null.
    packages/react-components/react-storybook-addon-playground/tools/collect-typings.js:16
  • This regex also recognizes import-like text inside comments and string literals. A declaration JSDoc example such as // import { Example } from 'optional-package' is treated as a real bare dependency; unlike unresolved relative false positives, it is added to missing and fails the Storybook build. Extract specifiers from parsed syntax or lexically skip comments and quoted text before matching.
    packages/react-components/react-storybook-addon-playground/tools/collect-typings.js:260
  • Packages that publish declarations only through package.json#exports are rejected here because own-type detection checks only top-level types/typings and index.d.ts. Although resolveEntryFile supports exports maps, it is never reached for such a package, so a configured modern package is reported as missing and the Storybook build fails. Include resolvable export type targets in this detection while retaining the @types/* fallback.
    packages/react-components/react-storybook-addon-playground/src/playground/Playground.styles.ts:40
  • These new shell styles hardcode spacing and stroke values even though docs/architecture/design-tokens.md:5-19 requires Fluent tokens for spacing, borders, typography, radii, and durations. Replace values such as the 16px gap/padding and 1px stroke with tokens.spacingHorizontalM and tokens.strokeWidthThin, and apply the same tokenization to the other semantic values in this stylesheet so theme/high-contrast behavior remains consistent.
  • Files reviewed: 72/74 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread packages/react-components/react-storybook-addon-playground/package.json Outdated
Generate isolated declarations for the setup subpath and add component-level coverage for successful, failed, and stale playground compile transactions.
@dmytrokirpa

Copy link
Copy Markdown
Contributor Author

Copilot Fix the code for all comments in this review thread.

When a review comment includes a suggested change, apply the suggestion exactly.

Do not make changes beyond what is described in the linked review thread.

Copilot AI and others added 2 commits September 16, 2026 15:18
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>

Copilot AI commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Copilot Fix the code for all comments in this review thread.

When a review comment includes a suggested change, apply...

Fixed the linked review finding in 1dbe2599: exports-only packages with a resolvable root declaration export are now recognized before falling back to @types. Added regression coverage; final review found no issues.

Copilot AI 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.

🟡 Changes recommended

Several headless stories currently open broken playgrounds due to unsupported imports, with additional URL-state and runtime edge cases unresolved.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 75/77 changed files
  • Comments generated: 6
  • Review effort level: Balanced

Comment on lines +74 to +80
loadWorkspaceAddon('@fluentui/react-storybook-addon-playground', {
tsConfigPath,
/** @type {import('../../../react-storybook-addon-playground/src/index').PresetConfig} */
options: {
modules: getHeadlessPlaygroundModules(),
setup: path.resolve(__dirname, './playground.setup.tsx'),
},
Comment on lines +33 to +35
const decoded = decompressFromEncodedURIComponent(encoded);

return typeof decoded === 'string' && decoded.length > 0 ? decoded : null;
Copilot AI and others added 9 commits September 17, 2026 06:12
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>

Copilot AI 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.

🟡 Changes recommended

Reset behavior, stale asynchronous error attribution, alias typings, focus visibility, and release metadata need correction.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (4)

Previously missed (4) — in code that hasn't changed since the last review.

packages/react-components/react-storybook-addon-playground/src/playground/Playground.tsx:408

  • Reset prefers the setup's generic defaultCode over the source that opened this playground. Because the built-in setup always provides defaultCode, clicking “Reset” on any Docs story replaces that story with the generic demo instead of restoring its initial source. Match the initialization precedence by using initialCode first.
    packages/react-components/react-storybook-addon-playground/src/styles.css:29
  • Removing the outline and relying only on a colored inset shadow makes keyboard focus disappear in forced-colors/high-contrast modes, where author shadows can be suppressed. Preserve a native focus-visible outline for this button.
    packages/react-components/react-storybook-addon-playground/src/webpack.ts:216
  • The generated alias declaration only forwards named exports; TypeScript's export * never forwards a default export. A configured mapping such as { alias: 'default-exporting-package' } therefore works in the runtime loader but Monaco incorrectly reports that alias has no default export. Generate alias typings that preserve the target module's complete export shape.
    change/@fluentui-react-storybook-addon-playground-751293a3-5a89-42e3-8d5d-f2e4b6b20f94.json:2
  • This change entry describes a feature but classifies it as patch. Repository release guidance requires minor for features (docs/workflows/contributing.md:30-36), so this entry should use the feature release type as the other playground entry does.
  • Files reviewed: 78/80 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment on lines +365 to +370
if (runtimeError.runId === currentRunId) {
setError({
title: runtimeErrorTitle(runtimeError.kind),
message: runtimeError.message,
previewRetained: false,
});
Comment on lines +41 to +42
const error = 'reason' in event ? event.reason : event.error || event.message;
sendError(error, activeRunId);
Copilot AI and others added 2 commits September 17, 2026 12:51
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Co-authored-by: dmytrokirpa <1492102+dmytrokirpa@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants