feat(storybook): add @fluentui/react-storybook-addon-playground with in-browser TSX playground - #36728
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Same-origin execution of URL-supplied code is unsafe, and shared Storybook targets can omit the required playground assets.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds a private Storybook addon providing an in-browser Monaco-based TSX playground for Fluent UI v9 stories.
Changes:
- Implements editing, compilation, formatting, IntelliSense, preview, themes, and shareable links.
- Adds the Docs-mode launcher and Storybook static-asset integration.
- Wires the addon into the public docsite and updates sandbox-addon interoperability.
Merge confidence: 40/100. URL-supplied code currently executes unsandboxed on the Storybook origin, and clean Storybook builds do not consistently build the playground assets.
File summaries
| File | Description |
|---|---|
yarn.lock |
Registers the workspace package and dependencies. |
tsconfig.base.json |
Adds the package path alias. |
tsconfig.base.all.json |
Adds the complete-workspace alias. |
webpack.playground.config.js |
Bundles the standalone playground. |
tsconfig.spec.json |
Configures test type-checking. |
tsconfig.playground.json |
Configures playground sources. |
tsconfig.lib.json |
Configures addon library output. |
tsconfig.json |
Defines TypeScript project references. |
tools/typings-loader.js |
Emits collected typings as JSON. |
tools/playground-typings.json |
Provides the loader stub asset. |
tools/collect-typings.spec.js |
Tests declaration collection. |
tools/collect-typings.js |
Collects transitive declarations. |
src/url.ts |
Implements shareable code hashes. |
src/url.spec.ts |
Tests URL helpers. |
src/types.ts |
Extends Storybook context types. |
src/styles.css |
Styles the Docs launcher button. |
src/public-types.ts |
Defines addon parameters. |
src/preset/preview.ts |
Registers the decorator. |
src/playground/useSplitPane.ts |
Implements pane resizing. |
src/playground/useSplitPane.spec.ts |
Tests keyboard resizing. |
src/playground/useMediaQuery.ts |
Tracks responsive queries. |
src/playground/typings.ts |
Registers Monaco declaration files. |
src/playground/themes.ts |
Defines selectable Fluent themes. |
src/playground/shortcuts.ts |
Produces platform shortcut labels. |
src/playground/shortcuts.spec.ts |
Tests shortcut labels. |
src/playground/runner.ts |
Evaluates compiled playground code. |
src/playground/runner.spec.ts |
Tests evaluation and allowlisting. |
src/playground/Preview.tsx |
Renders the component preview. |
src/playground/Preview.styles.ts |
Styles the preview surface. |
src/playground/Playground.tsx |
Implements the application shell. |
src/playground/Playground.styles.ts |
Defines shell and responsive styles. |
src/playground/playground.html |
Provides the application document. |
src/playground/playground-typings.d.ts |
Types the generated typings asset. |
src/playground/monaco.ts |
Configures Monaco and workers. |
src/playground/modules.ts |
Defines runtime module loaders. |
src/playground/main.tsx |
Bootstraps the React application. |
src/playground/formatter.ts |
Integrates Prettier with Monaco. |
src/playground/formatter.spec.ts |
Tests TSX formatting. |
src/playground/ErrorBoundary.tsx |
Handles preview render failures. |
src/playground/editorTheme.ts |
Defines Monaco themes. |
src/playground/Editor.tsx |
Manages the Monaco editor. |
src/playground/Editor.styles.ts |
Sizes the editor container. |
src/playground/defaultCode.ts |
Supplies the initial example. |
src/playground/compiler.ts |
Compiles TSX in Monaco’s worker. |
src/index.ts |
Exports the addon API. |
src/decorators/withOpenInPlaygroundButton.ts |
Injects the Docs launcher. |
src/decorators/withOpenInPlaygroundButton.spec.ts |
Tests launcher behavior. |
README.md |
Documents usage and development. |
project.json |
Adds build targets. |
preset.js |
Registers annotations and static assets. |
package.json |
Defines the private package. |
LICENSE |
Adds package licensing. |
jest.config.js |
Configures Jest. |
etc/react-storybook-addon-playground.api.md |
Records the public API. |
eslint.config.js |
Configures package linting. |
config/tests.js |
Adds Jest setup. |
config/api-extractor.json |
Configures API Extractor. |
.swcrc |
Configures SWC compilation. |
.babelrc.json |
Adds Babel annotations. |
sandbox-utils.ts |
Excludes the playground button. |
change/...json |
Adds the sandbox-addon patch entry. |
apps/public-docsite-v9/project.json |
Builds the playground dependency. |
apps/public-docsite-v9/package.json |
Adds the workspace dependency. |
apps/public-docsite-v9/.storybook/main.js |
Excludes addon sources from stories. |
.storybook/preview.js |
Loads launcher styles. |
.storybook/main.js |
Registers the addon globally. |
.github/CODEOWNERS |
Assigns package ownership. |
Review details
- Files reviewed: 65/67 changed files
- Comments generated: 6
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ## Installation | ||
|
|
||
| ```sh | ||
| yarn add @fluentui/react-storybook-addon-playground | ||
| ``` |
|
Pull request demo site: URL |
Martin Hochel (Hotell)
left a comment
There was a problem hiding this comment.
posting initial comments
Co-authored-by: Atishay Jain <atisjai@microsoft.com>
|
Dmytro Kirpa (@dmytrokirpa) wanted to provide comprehensive "text" but I rather decided to prototype, here is the suggestion to make this more secure and configurable. the complexity is higher ofc but we can improve it.
thoughts ? |
Using configuration instead of hardcoded parameters makes perfect sense. I had planned to follow up on that, but we can do it in the intial PR. Replacing the |
…lySchemaAdapterUT and isSafeUrl function (microsoft#36737)
discussed offline.
Dmytro Kirpa (@dmytrokirpa) we should ideally merge package scaffold with some noop and release as 0.0.1, then move to experimental. otherwise the |
…caffold Ship 0.0.1 on latest first so later experimental playground releases do not take the latest npm tag. Co-authored-by: Cursor <cursoragent@cursor.com>
Implements the configurable Monaco playground with a sandboxed preview, Docs launcher, and Storybook wiring on top of the published package scaffold. Co-authored-by: Cursor <cursoragent@cursor.com>
ab45332 to
6b95616
Compare
|
Split per #36728 (comment):
Suggested merge order:
Until step 2, GitHub will also show the scaffold commit (and any |
Previous Behavior
Storybook Docs pages only offer "Show code" and the export-to-sandbox buttons (StackBlitz / CodeSandbox). There is no way to edit and run a story's TSX directly in the browser against Fluent UI React v9.
New Behavior
New workspace package
@fluentui/react-storybook-addon-playground(packages/react-components/react-storybook-addon-playground):preset.js)previewAnnotations: registers thewithOpenInPlaygroundButtondecorator, which adds an Open in Playground button next to "Show code" in Docs mode. It takes the story source fromparameters.fullSource(injected by@fluentui/babel-preset-storybook-full-sourcevia the export-to-sandbox addon) and opens./playground.html#code=<lz-string>in a new tab.staticDirs: serves the pre-built playground app (dist/playground) from the Storybook root, soplayground.htmlis part of the Storybook static output (works in bothstorybook devandstorybook build).src/playground, separate webpack bundle built by thebuild-playgroundnx target, whichbuilddepends on)PresetConfig/definePlaygroundSetup.sandbox="allow-scripts"iframe with a postMessage protocol.Repo wiring:
public-docsite-v9-headlessload the addon vialoadWorkspaceAddon.react-storybook-addon-export-to-sandbox: the "Show code" lookup now also ignores.with-open-in-playground-button.Related Issue(s)
0.0.1onlatest)