Skip to content

Commit

Permalink
feat: new design (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
YossiSaadi authored May 12, 2024
1 parent 4ee3343 commit a911376
Show file tree
Hide file tree
Showing 28 changed files with 845 additions and 247 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
dist/
assets/icons
node_modules/
storybook-static/
build-storybook.log
.DS_Store
.env
/.idea/
/.idea/
139 changes: 40 additions & 99 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,22 @@
# Storybook Addon Playground
# Playground - Storybook Addon

![img.png](assets/img.png)

## Develop locally

Install dependencies and start

```bash
yarn
yarn start
```
This addon enhances your Storybook experience by allowing you to interactively play with your components. It's perfect for developers looking to experiment in real time, debug issues, or build complex compositions.

Or

```bash
npm i
npm start
```

Go to [localhost:6006](http://localhost:6006)
![img.png](assets/img.png)

## How to add to your Storybook project
## Installation

### Install
To install the addon, run one of the following commands in your project directory:

```bash
yarn add -D storybook-addon-playground
```

Or

```bash
# or
npm install -D storybook-addon-playground
```

### Register addon
## Configuration

On your `.storybook/main.ts` file, add the following:
Add the addon to your Storybook configuration in `.storybook/main.js` or `.storybook/main.ts`:

```js
const config = {
Expand All @@ -47,16 +27,16 @@ const config = {
};
```

### Addon Configuration
The addon configuration is done through Storybook's `preview` parameters.

The addon configuration is done through Storybook's `preview`. Few of the parameters are required for the addon to work properly:

- `storyId`: **Required**. The story id that your playground has on Storybook.
- `components`: **Required**. An object with the components that should be rendered in the playground. The key is the component name and the value is the component itself.
- `autocompletions`: Optional. An array of autocompletions that should be used on the playground. Default is an empty array. We recommend on using `react-docgen` to generate a documentation output and run our util function on the output. You can use whatever tool you'd like as long as it matches the expected format in the addon. _Default is no autocompletions._
- `editorTheme`: Optional. The theme that should be used on the playground. _Default is your Storybook theme._
- `initialCode`: Optional. The initial code ("welcome") that should be rendered on the playground. _Default is empty editor._
- `share`: Optional. A boolean that allow users to share the code. _Default is false._
| Parameter | Required | Default | Description |
|------------------|----------|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `storyId` | `true` | | The story id that your playground has on Storybook. |
| `components` | `true` | | An object with the components that should be rendered in the playground. The key is the component name and the value is the component itself. |
| `autocompletions`| `false` | `[]` | An array of autocompletions that should be used on the playground. Recommended to use `react-docgen` for generating documentation outputs. |
| `editorTheme` | `false` | Your Storybook theme | The theme that should be used on the playground. |
| `initialCode` | `false` | Empty editor | The initial code ("welcome") that should be rendered on the playground. |
| `share` | `false` | `false` | Whether to allow share capabilities. |

On your `.storybook/preview.ts` file, you should add something similar to the following:

Expand All @@ -79,9 +59,7 @@ const preview = {
};
```

### Render a story including the playground in the sidebar

Create a story with the following content:
Set up the playground environment in your Storybook stories:

```js
import { withPlayground } from "storybook-addon-playground";
Expand All @@ -94,78 +72,41 @@ export default {
export const Playground = {};
```

## Build
## Usage

### Vite
To use the Playground, navigate to the Storybook UI and select a story that has the playground decorator. In your addons panel, see an interactive code editor alongside your component, where you can modify the code and immediately see your changes reflected.

Vite is used to build the local Storybook for testing and dev purposes
## Contributing

### Rollup
Contributions are welcome! Feel free to open an issue or submit a pull request.

Rollup is used to build the addon for publishing
### Develop locally

```mermaid
graph TD;
subgraph ADDON
A{{Rollup}}
B[index.ts]
C[manager.ts]
D[Panel addon]
E[Tool addon]
F[withPlayground]
U[generateAutocompletions]
G[PlaygroundPreview]
H[react-live]
I[Editor]
J[useCopyToClipboard]
K[usePlaygroundArgs]
Q[useInitialCode]
R[useBroadcastEditorChanges]
S[usePlaygroundState]
T[useEditorTheme]
L[useToolbarActions]
M[prettier]
N[react-codemirror]
Install dependencies and start

O[Toolbar icon]
```bash
yarn
yarn start
```

P[Storybook Addon API]
Go to [localhost:6006](http://localhost:6006)

A -->|Entry| B
A -->|Entry| C
### Add new icons

B -->|Exports| F
B -->|Exports| U
Icons are generated using [svgr](https://react-svgr.com/docs/).

P --> D
P --> E
In order to add new icons to the addon, drop the icons somewhere in the repo and run the following command:

E -->|Renders| O
```bash
yarn build:icons path/to/your/icons
```

C -->|Registers Addons| P
### Build

F -->|Renders in a story| G
G ======>|Using lib| H
#### Rollup

D -->|Calls| Q
D -->|Calls| R
R -->|Uses| S
D --->|Renders| I
I ====>|Using lib| N
I -->|Uses| L
I -->|Uses| K
I -->|Uses| T
I -->|Uses| J
Rollup is used to build the addon for publishing.

L ===>|Using lib| M
end
#### Vite

subgraph UI
X{{Vite}}
Z["Storybook UI (.storybook - Testing and Development)"]
X --> Z
end
```
Vite serves the build to a local Storybook for testing and dev purposes.
Binary file modified assets/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"test:watch": "yarn test -- -w",
"build": "rollup -c",
"build:watch": "yarn build -- -w",
"build:icons": "yarn svgr --typescript --no-svgo --out-dir src/icons",
"lint": "eslint . --max-warnings 0",
"lint:fix": "yarn lint -- --fix",
"storybook": "storybook dev -p 6006",
Expand All @@ -56,6 +57,7 @@
"dependencies": {
"@storybook/addon-links": "^7.6.4",
"@uiw/codemirror-extensions-langs": "^4.21.21",
"@uiw/codemirror-theme-github": "^4.21.21",
"@uiw/react-codemirror": "^4.21.21",
"classnames": "^2.3.2",
"lodash-es": "^4.17.21",
Expand All @@ -74,6 +76,7 @@
"@storybook/react": "^7.6.4",
"@storybook/react-vite": "^7.6.4",
"@storybook/theming": "^7.6.4",
"@svgr/cli": "^8.1.0",
"@testing-library/jest-dom": "^6.1.6",
"@testing-library/react": "^14.1.2",
"@types/lodash-es": "^4.17.12",
Expand Down
44 changes: 10 additions & 34 deletions src/components/Addons/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Suspense, useCallback, useMemo, useRef } from "react";
import { Editor, EditorTabs, EditorToolbar } from "../Editor";
import React, { Suspense, useMemo, useRef } from "react";
import { Editor, EditorToolbar } from "../Editor";
import {
useInitialCode,
useBroadcastEditorChanges,
Expand Down Expand Up @@ -36,47 +36,21 @@ const Panel: React.FC<Addon_RenderOptions> = ({ active }) => {
ADDON_ID_FOR_PARAMETERS,
DEFAULT_ADDON_PARAMETERS
);
const [state, setState] = useAddonState<PlaygroundState>(
PANEL_ID,
DEFAULT_ADDON_STATE
);
const [state] = useAddonState<PlaygroundState>(PANEL_ID, DEFAULT_ADDON_STATE);

const extensions = useMemo<Record<Tab, Extension[]>>(
() => ({
jsx: [
langs.html(),
langs.javascript(),
playgroundAutocompletion(autocompletions),
keymap.of(playgroundKeymaps),
langs.javascript({ jsx: true, typescript: true }),
],
css: [langs.css()],
}),
[autocompletions]
);

const { code, selectedTab, fontSize, hasInitialCodeLoaded, editorState } =
state;

const onTabChange = useCallback(
(newTab: Tab) => {
setState((prev) => {
const updates = {
...prev,
selectedTab: newTab,
};
const editorStateJson =
editorRef.current?.view?.state?.toJSON?.(EDITOR_STATE_FIELDS);
if (editorStateJson) {
updates.editorState = {
...prev.editorState,
[prev.selectedTab]: editorStateJson,
};
}
return updates;
});
},
[setState]
);
const { code, selectedTab, hasInitialCodeLoaded, editorState } = state;

const editorInitialState = useMemo(
() => ({
Expand All @@ -89,9 +63,8 @@ const Panel: React.FC<Addon_RenderOptions> = ({ active }) => {
return (
<AddonPanel active={active}>
<div className={styles.panel}>
<EditorToolbar />
<EditorToolbar editorRef={editorRef} />
<div className={styles.editorWrapper}>
<EditorTabs selectedTab={selectedTab} onTabChange={onTabChange} />
<div className={styles.editor}>
<Suspense fallback={"Loading Editor..."}>
<Editor
Expand All @@ -102,9 +75,12 @@ const Panel: React.FC<Addon_RenderOptions> = ({ active }) => {
code={code[selectedTab]}
theme={theme}
extensions={extensions[selectedTab]}
style={{ fontSize }}
style={{ fontSize: 13 }}
onChange={updateCode}
initialState={editorInitialState}
setup={{
foldGutter: false,
}}
/>
</Suspense>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/Addons/PanelTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from "react";
import { Icons } from "@storybook/components";
import styles from "./PanelTitle.module.css";
import { Beaker } from "@/icons";

const PanelTitle: React.FC = () => (
<span className={styles.title}>
<Beaker />
Playground
<Icons icon="beaker" />
</span>
);
export default PanelTitle;
10 changes: 10 additions & 0 deletions src/components/Editor/Editor.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,13 @@
) {
margin-right: 8px;
}

:global(.cm-theme),
:global(.cm-editor) {
height: 100%;
}

:global(.cm-gutter.cm-lineNumbers .cm-gutterElement) {
min-width: 35px;
padding-inline: 8px;
}
6 changes: 3 additions & 3 deletions src/components/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
import { Loader } from "@storybook/components";
const CodeMirror = lazy(() => import("@uiw/react-codemirror"));
import "./Editor.module.css";
import { EditorInitialState } from "@/types";
import { EditorInitialState, EditorTheme } from "@/types";

interface EditorProps {
code: string;
onChange: (newVal: string) => void;
placeholder?: string;
loading?: boolean;
theme?: "light" | "dark" | Extension;
theme: EditorTheme;
style?: React.CSSProperties;
extensions?: Extension[];
setup?: BasicSetupOptions;
Expand All @@ -32,7 +32,7 @@ const Editor: EditorComponent = forwardRef(
onChange,
placeholder,
loading,
theme = "light",
theme,
style,
extensions,
setup,
Expand Down
Loading

0 comments on commit a911376

Please sign in to comment.