ESM Support in Playroom
master.js, .mjs, or .cjs extension.repository·master·Indexed 26 days ago
https://github.com/seek-oss/playroomA zero-install, code-oriented design environment for developers to design across multiple themes and screen sizes simultaneously using their own JSX component libraries. Version 1.3.0 provides a CLI for starting development servers and building production assets, with configurable themes, viewports, code snippets, and custom frame components via a playroom.config.js file.
.js, .mjs, or .cjs extension.Define predefined snippets of JSX that users can quickly insert into the Playroom editor. Create a file (e.g., snippets.js) and export an array of objects.
Each object can contain:
group (optional): A string to group snippets in the UI.name (required): The name of the snippet.description (optional): A description to help differentiate snippets.code (required): The JSX code string.export default [
{
group: 'Components',
name: 'Button',
description: 'Strong weight',
code: `
<Button weight="strong">
Button
</Button>
`,
},
];storybook-addon-playroom package.Install Playroom as a development dependency and add the necessary scripts to your package.json to start the development server or build assets for production.
$ npm install --save-dev playroompackage.json:{
"scripts": {
"playroom:start": "playroom start",
"playroom:build": "playroom build"
}
}playroom.config.js file in your project root to configure your environment.Define boolean toggles that users can control for each frame independently (e.g., for testing RTL or touch targets). Configure these in playroom.config.js using the frameSettings array.
Each setting object requires:
id: A unique identifier.label: The display name in the UI.defaultValue: The initial boolean state.module.exports = {
// ...
frameSettings: [
{
id: 'rtl',
label: 'RTL Layout',
defaultValue: false,
},
{
id: 'showTouchTargets',
label: 'Show Touch Targets',
defaultValue: false,
},
],
};Playroom uses react-docgen-typescript to parse static prop types for better autocompletion in the editor. By default, it includes all .ts and .tsx files in the current working directory (excluding node_modules).
To customize which files are included, use the typeScriptFiles property in your playroom.config.js. This property accepts an array of tinyglobby-compatible globs.
module.exports = {
// ...
typeScriptFiles: ['src/components/**/*.{ts,tsx}', '!**/node_modules'],
};Create a playroom.config.js file in your project root. The components path is required. Other options allow you to customize themes, viewports, snippets, and custom components.
Required Options:
components: Path to a file exporting your component library (object or named exports).Common Optional Options:
outputPath: Where to build assets (e.g., ./dist/playroom).title: The title of your Playroom instance.themes: Path to a file exporting theme objects.widths: Array of viewport widths (e.g., [320, 768, 1024]).snippets: Path to a file defining code snippets.frameComponent: Path to a custom React component for wrapping frames.frameSettings: Array of setting objects (see Frame Settings).exampleCode: A string of JSX to show by default.scope: Path to a file exporting a useScope hook.port: Port for the dev server (default 9000).openBrowser: Whether to open the browser on start (default true).paramType: How parameters are passed in the URL ('search' or 'hash').baseUrl: The base URL for the Playroom instance.iframeSandbox: String for the iframe sandbox attribute (must include allow-scripts).module.exports = {
components: './src/components',
outputPath: './dist/playroom',
// Optional:
title: 'My Awesome Library',
themes: './src/themes',
widths: [320, 768, 1024],
snippets: './playroom/snippets.js',
frameComponent: './playroom/FrameComponent.js',
frameSettings: [{ id: 'rtl', label: 'RTL Layout', defaultValue: false }],
exampleCode: `
<Button>
Hello World!
</Button>
`,
cwd: './playroom',
scope: './playroom/useScope.js',
port: 9000,
openBrowser: true,
paramType: 'search', // default is 'hash'
baseUrl: '/playroom/',
webpackConfig: () => ({
// Custom webpack config goes here...
}),
iframeSandbox: 'allow-scripts',
defaultVisibleWidths: [
// subset of widths to display on first load
],
defaultVisibleThemes: [
// subset of themes to display on first load
],
};You can customize the parser options used for TypeScript prop parsing by setting the reactDocgenTypescriptConfig property in your playroom.config.js. This allows you to pass configuration directly to react-docgen-typescript, such as a propFilter function.
module.exports = {
// ...
reactDocgenTypescriptConfig: {
propFilter: (prop, component) => {
// ...
},
},
};Playroom requires a configuration file to run. The CLI automatically searches for the following files in your current working directory (or parent directories) in this order:
playroom.config.jsplayroom.config.mjsplayroom.config.cjsIf you do not have one of these files in your project root, you must specify the path manually using the --config flag.
Access the current state of frame settings via the frameSettings prop in your custom FrameComponent. This allows you to pass settings (like rtl) down to your component library's providers or apply CSS classes based on the toggle state.
import React from 'react';
import { ThemeProvider } from '../path/to/your/theming-system';
export default function FrameComponent({ theme, frameSettings, children }) {
return (
<ThemeProvider theme={theme} rtl={frameSettings?.rtl}>
<div
className={
frameSettings?.showTouchTargets ? 'showTouchTargets' : undefined
}
>
{children}
</div>
</ThemeProvider>
);
}If your components require specific providers (like a ThemeProvider), use the frameComponent option in your config to provide a custom wrapper. The component must export a default React component that receives the following props:
theme: The currently selected theme object.themeName: The name of the currently selected theme.frameSettings: An object mapping setting IDs to their boolean values.children: The rendered Playroom code.import React from 'react';
import { ThemeProvider } from '../path/to/your/theming-system';
export default function FrameComponent({ theme, children }) {
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}Use the scope option to provide extra variables to the JSX environment. The specified file must export a useScope hook that returns a scope object containing the variables you want to expose.
// scope.js
import { useTheme } from '../path/to/your/theming-system';
export default function useScope() {
return {
theme: useTheme(),
};
}