From f0fbf6ae0edb1890996e3b686ae4fb2460676c82 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 17:09:59 +0300 Subject: [PATCH 01/16] docs: add CanvasWrapper component to render a code editor inside it --- .../canvas-wrapper/CanvasWrapper.module.scss | 28 +++++++++++++++++++ .../canvas-wrapper/CanvasWrapper.tsx | 28 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.module.scss create mode 100644 packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx diff --git a/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.module.scss b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.module.scss new file mode 100644 index 0000000000..2f70716782 --- /dev/null +++ b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.module.scss @@ -0,0 +1,28 @@ +.editorContainer { + position: relative; + top: -40px; + width: 100%; + background: transparent; + max-height: 0; + opacity: 0; + transition: max-height 0.1s ease-out, opacity 0.1s ease-out; + overflow: auto; + border-radius: 0 0 4px 4px; + box-shadow: rgba(0, 0, 0, 0.1) 0 1px 3px 0; + border: 1px solid hsla(203, 50%, 30%, 0.15); + border-top: none; + + &[data-editor-open="true"] { + max-height: 500px; + opacity: 1; + } + + & :global(.cm-editor) { + padding: var(--sb-spacing-medium); + } +} + +.canvas:has(+ [data-editor-open="true"]) { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} diff --git a/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx new file mode 100644 index 0000000000..d65de6d9b6 --- /dev/null +++ b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx @@ -0,0 +1,28 @@ +import { Canvas, useOf } from "@storybook/blocks"; +import { ComponentProps, FC, useMemo, useState } from "react"; +import styles from "./CanvasWrapper.module.scss"; + +type CanvasWrapper = ComponentProps; + +const CanvasWrapper: FC = ({ of }) => { + const [open, setOpen] = useState(false); + + const { story } = useOf(of || "story", ["story"]); + + const toggleCodeAction = useMemo( + () => ({ + title: "Toggle code editor", + onClick: () => setOpen(prev => !prev) + }), + [] + ); + + return ( + <> + +
+ + ); +}; + +export default CanvasWrapper; From d303e16a14750838d5f478d42860c2583b2afaf4 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 17:11:23 +0300 Subject: [PATCH 02/16] docs: make CanvasWrapper the default Canvas unless imported in an mdx --- packages/core/.storybook/preview.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/.storybook/preview.tsx b/packages/core/.storybook/preview.tsx index 0312da1724..043d4b22ba 100644 --- a/packages/core/.storybook/preview.tsx +++ b/packages/core/.storybook/preview.tsx @@ -28,6 +28,7 @@ import { MultipleStoryElementsWrapper, StorybookLink } from "vibe-storybook-components"; +import CanvasWrapper from "../src/storybook/components/canvas-wrapper/CanvasWrapper"; import { ComponentNameDecorator, PropsTable, RelatedComponentsDecorator } from "../src/storybook"; import "monday-ui-style/dist/index.min.css"; import "vibe-storybook-components/dist/index.css"; @@ -53,6 +54,7 @@ const preview: Preview = { ), page: DocsPage, components: { + Canvas: CanvasWrapper, Controls: PropsTable, PropsTable, h1: ComponentNameDecorator, From 0fa24e548f65b4520560b702dd7fa08827f3f8e7 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 17:34:22 +0300 Subject: [PATCH 03/16] docs: add LiveEditor component for editing stories --- packages/core/package.json | 1 + .../components/live-editor/LiveEditor.tsx | 34 +++++++++++++++++++ yarn.lock | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/storybook/components/live-editor/LiveEditor.tsx diff --git a/packages/core/package.json b/packages/core/package.json index 557035e779..7c6ae8f4b1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -229,6 +229,7 @@ "prettier": "^2.5.1", "react": "^16.14.0", "react-dom": "^16.14.0", + "react-live": "^4.1.6", "react-markdown": "^7.1.0", "react-resizable": "^3.0.4", "react-test-renderer": "^16.14.0", diff --git a/packages/core/src/storybook/components/live-editor/LiveEditor.tsx b/packages/core/src/storybook/components/live-editor/LiveEditor.tsx new file mode 100644 index 0000000000..493b2639d4 --- /dev/null +++ b/packages/core/src/storybook/components/live-editor/LiveEditor.tsx @@ -0,0 +1,34 @@ +import React, { forwardRef } from "react"; +import CodeMirror, { Extension, ReactCodeMirrorRef, BasicSetupOptions } from "@uiw/react-codemirror"; + +interface EditorProps { + code: string; + onChange: (newVal: string) => void; + placeholder?: string; + loading?: boolean; + theme?: "light" | "dark" | Extension; + style?: React.CSSProperties; + extensions?: Extension[]; + setup?: BasicSetupOptions; +} + +type EditorComponent = React.ForwardRefExoticComponent>; + +const LiveEditor: EditorComponent = forwardRef( + ({ code, onChange, placeholder, theme = "light", style, extensions, setup }, ref) => { + return ( + + ); + } +); + +export default LiveEditor; diff --git a/yarn.lock b/yarn.lock index 77618c1310..0483dd16f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16540,7 +16540,7 @@ react-is@^17.0.0, react-is@^17.0.1: resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-live@^4.1.5: +react-live@^4.1.5, react-live@^4.1.6: version "4.1.6" resolved "https://registry.npmjs.org/react-live/-/react-live-4.1.6.tgz#6d9b7d381bd2b359ca859767501135112b6bab33" integrity sha512-2oq3MADi3rupqZcdoHMrV9p+Eg/92BDds278ZuoOz8d68qw6ct0xZxX89MRxeChrnFHy1XPr8BVknDJNJNdvVw== From 0e4a32eec91799ef3b8e2fd82f86ba6eba637651 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 17:35:23 +0300 Subject: [PATCH 04/16] docs: add withLiveEdit decorator to wrap all stories with a decorator that includes a live editor --- packages/core/.eslintrc.js | 6 +- packages/core/.storybook/preview.tsx | 11 +-- packages/core/package.json | 5 +- .../components/live-preview/LivePreview.tsx | 16 ++++ .../withLiveEdit/withLiveEdit.module.scss | 11 +++ .../decorators/withLiveEdit/withLiveEdit.tsx | 74 +++++++++++++++++++ yarn.lock | 53 +++++++++++-- 7 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 packages/core/src/storybook/components/live-preview/LivePreview.tsx create mode 100644 packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss create mode 100644 packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx diff --git a/packages/core/.eslintrc.js b/packages/core/.eslintrc.js index ed22a8090a..22d991d846 100644 --- a/packages/core/.eslintrc.js +++ b/packages/core/.eslintrc.js @@ -100,7 +100,11 @@ module.exports = { } }, { - files: ["*.stories.@(js|jsx|ts|tsx)", "*.stories.helpers.@(js|jsx|ts|tsx)"], + files: [ + "*.stories.@(js|jsx|ts|tsx)", + "*.stories.helpers.@(js|jsx|ts|tsx)", + "src/storybook/decorators/**/with*.{js,jsx,ts,tsx}" + ], rules: { ...commonRules, "react-hooks/rules-of-hooks": "off", diff --git a/packages/core/.storybook/preview.tsx b/packages/core/.storybook/preview.tsx index 043d4b22ba..1f9b20494a 100644 --- a/packages/core/.storybook/preview.tsx +++ b/packages/core/.storybook/preview.tsx @@ -29,10 +29,12 @@ import { StorybookLink } from "vibe-storybook-components"; import CanvasWrapper from "../src/storybook/components/canvas-wrapper/CanvasWrapper"; +import withGlobalStyle from "../src/storybook/decorators/withGlobalStyle/withGlobalStyle"; import { ComponentNameDecorator, PropsTable, RelatedComponentsDecorator } from "../src/storybook"; import "monday-ui-style/dist/index.min.css"; import "vibe-storybook-components/dist/index.css"; import introCode from "../src/storybook/stand-alone-documentaion/playground/playground-helpers"; +import withLiveEdit from "../src/storybook/decorators/withLiveEdit/withLiveEdit"; const fontLoader = async () => ({ fonts: await document.fonts.ready // Fixing Chromatic tests flakiness - taking snapshots after fonts are loaded @@ -107,13 +109,8 @@ const preview: Preview = { } }, decorators: [ - (Story, { className }: { className: string }) => { - return ( - - - - ); - }, + withGlobalStyle, + withLiveEdit, withMemoryStats, // Should always be the last decorator (stories hooks issues otherwise) - bug in the addon withThemeByClassName({ diff --git a/packages/core/package.json b/packages/core/package.json index 7c6ae8f4b1..80a34f8c62 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -183,6 +183,9 @@ "@types/react-window": "^1.8.5", "@typescript-eslint/eslint-plugin": "^5.36.1", "@typescript-eslint/parser": "^5.36.1", + "@uiw/codemirror-extensions-langs": "^4.21.25", + "@uiw/codemirror-theme-vscode": "^4.21.25", + "@uiw/react-codemirror": "^4.21.25", "acorn": "^8.7.1", "autoprefixer": "^10.4.0", "babel-core": "^6.26.3", @@ -229,7 +232,7 @@ "prettier": "^2.5.1", "react": "^16.14.0", "react-dom": "^16.14.0", - "react-live": "^4.1.6", + "react-live": "^4.1.5", "react-markdown": "^7.1.0", "react-resizable": "^3.0.4", "react-test-renderer": "^16.14.0", diff --git a/packages/core/src/storybook/components/live-preview/LivePreview.tsx b/packages/core/src/storybook/components/live-preview/LivePreview.tsx new file mode 100644 index 0000000000..4ff195ead2 --- /dev/null +++ b/packages/core/src/storybook/components/live-preview/LivePreview.tsx @@ -0,0 +1,16 @@ +import React from "react"; +import { withLive } from "react-live"; + +interface LivePreview { + live?: { + // live injects more, currently unneeded, props + error?: string; + element?: React.ComponentType; + }; +} + +const LivePreview: React.FC = ({ live = {} }) => { + const { error, element: Element } = live; + return <>{error ?? (Element && )}; +}; +export default withLive(LivePreview); diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss new file mode 100644 index 0000000000..aecefa5d5b --- /dev/null +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss @@ -0,0 +1,11 @@ +.modifiedVersionIndicator { + position: absolute; + top: 0; + left: calc(50% - var(--sb-spacing-large)); + margin: 0; + border-radius: 0 0 4px 4px; + background: var(--sb-primary-color); + color: var(--sb-text-color-on-primary); + padding: var(--sb-spacing-xs); + font-size: 10px; +} diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx new file mode 100644 index 0000000000..ed243143ea --- /dev/null +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -0,0 +1,74 @@ +import { Decorator } from "@storybook/react"; +import { useRef, useState } from "react"; +import { vscodeDark } from "@uiw/codemirror-theme-vscode"; +import { langs } from "@uiw/codemirror-extensions-langs"; +import * as VibeComponents from "../../../components"; +import * as VibeComponentsNext from "../../../next"; +import * as VibeIcons from "../../../components/Icon/Icons"; +import { createPortal } from "react-dom"; +import { LiveProvider } from "react-live"; +import LivePreview from "../../components/live-preview/LivePreview"; +import styles from "./withLiveEdit.module.scss"; +import LiveEditor from "../../components/live-editor/LiveEditor"; + +const globalScope = { ...VibeComponents, VibeIcons, VibeNext: VibeComponentsNext }; + +const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }) => { + const scope = { ...globalScope, ...parameters.liveEdit?.scope }; + const originalCode = useRef(extractCodeFromSource(parameters.docs.source?.originalSource) || ""); + const [code, setCode] = useState(originalCode.current); + const [dirty, setDirty] = useState(false); + + const handleChange = (newVal: string) => { + setCode(newVal); + setDirty(true); + }; + + return ( + <> + {dirty ? ( + <> +
Modified Version
+ + + + + ) : ( + + )} + {viewMode === "docs" && + createPortal( + , + document.getElementById(id) || document.body + )} + + ); +}; + +function extractCodeFromSource(csfSource: string): string { + // capture "render:" from the string + if (!csfSource) { + return ""; + } + const match = csfSource.match(/render:\s*(?:\(\)\s*=>\s*)?([\s\S]*?)(?=\s*,\s*[\w]+:\s*|}$)/); + + if (!match?.[1]) { + return ""; + } + + return match[1].trim(); +} + +export default withLiveEdit; diff --git a/yarn.lock b/yarn.lock index 0483dd16f9..4b2bf08b1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5324,7 +5324,7 @@ "@codemirror/state" "^6.0.0" "@codemirror/view" "^6.0.0" -"@uiw/codemirror-extensions-langs@^4.21.21": +"@uiw/codemirror-extensions-langs@^4.21.21", "@uiw/codemirror-extensions-langs@^4.21.25": version "4.21.25" resolved "https://registry.npmjs.org/@uiw/codemirror-extensions-langs/-/codemirror-extensions-langs-4.21.25.tgz#8e5f0215e0f763f3848349c9254d5d3cbe073563" integrity sha512-d+lJnY1pXC+dyhIZkTfsKtiizrtoWSDgSfT+OfvZC6Ga3IodEx0MtHi3MFA0P5xnReTqaKQebmwV87NPRxjHPg== @@ -5357,7 +5357,23 @@ "@replit/codemirror-lang-svelte" "^6.0.0" codemirror-lang-mermaid "^0.5.0" -"@uiw/react-codemirror@^4.21.21": +"@uiw/codemirror-theme-vscode@^4.21.25": + version "4.21.25" + resolved "https://registry.npmjs.org/@uiw/codemirror-theme-vscode/-/codemirror-theme-vscode-4.21.25.tgz#cf868c219e2ca8253dd2845e451c92920bea27ce" + integrity sha512-1gubCz7kHE5XH3H1IUTSrnyK/G3dQRmOIgPFsefE9e+TizhBJnkbKSDSfRfpm5l7jl1G7v/as0HQvN3cYg/Rkg== + dependencies: + "@uiw/codemirror-themes" "4.21.25" + +"@uiw/codemirror-themes@4.21.25": + version "4.21.25" + resolved "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.21.25.tgz#562e7e4d36b34329858ffe9c9c06d7f50cfe0d3c" + integrity sha512-C3t/voELxQj0eaVhrlgzaOnSALNf8bOcRbL5xN9r2+RkdsbFOmvNl3VVhlxEB7PSGc1jUZwVO4wQsB2AP178ag== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + +"@uiw/react-codemirror@^4.21.21", "@uiw/react-codemirror@^4.21.25": version "4.21.25" resolved "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.25.tgz#1efb7737b907fde6f8f7552b5f43b33eec0b7a86" integrity sha512-mBrCoiffQ+hbTqV1JoixFEcH7BHXkS3PjTyNH7dE8Gzf3GSBRazhtSM5HrAFIiQ5FIRGFs8Gznc4UAdhtevMmw== @@ -16540,7 +16556,7 @@ react-is@^17.0.0, react-is@^17.0.1: resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-live@^4.1.5, react-live@^4.1.6: +react-live@^4.1.5: version "4.1.6" resolved "https://registry.npmjs.org/react-live/-/react-live-4.1.6.tgz#6d9b7d381bd2b359ca859767501135112b6bab33" integrity sha512-2oq3MADi3rupqZcdoHMrV9p+Eg/92BDds278ZuoOz8d68qw6ct0xZxX89MRxeChrnFHy1XPr8BVknDJNJNdvVw== @@ -18189,7 +18205,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18275,7 +18300,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18296,6 +18321,13 @@ strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -20123,7 +20155,7 @@ workerpool@6.2.1: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20141,6 +20173,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 01dd01d51d2743d4f051e5299cf71bc5d4271f8c Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 17:39:27 +0300 Subject: [PATCH 05/16] docs: encapsulate MultipleStoryElementsWrapper into a global style decorator, add custom padding --- packages/core/.storybook/preview.tsx | 1 + .../withGlobalStyle/withGlobalStyle.module.scss | 3 +++ .../decorators/withGlobalStyle/withGlobalStyle.tsx | 14 ++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.module.scss create mode 100644 packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx diff --git a/packages/core/.storybook/preview.tsx b/packages/core/.storybook/preview.tsx index 1f9b20494a..06c998fc60 100644 --- a/packages/core/.storybook/preview.tsx +++ b/packages/core/.storybook/preview.tsx @@ -45,6 +45,7 @@ const preview: Preview = { controls: { sort: "alpha" }, + layout: "fullscreen", docs: { container: ({ children, context }: { children: any; context: any }) => ( diff --git a/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.module.scss b/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.module.scss new file mode 100644 index 0000000000..5a841e90d6 --- /dev/null +++ b/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.module.scss @@ -0,0 +1,3 @@ +.storyWrapper { + padding: var(--spacing-xl) var(--spacing-large); +} \ No newline at end of file diff --git a/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx b/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx new file mode 100644 index 0000000000..0e49a1885d --- /dev/null +++ b/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx @@ -0,0 +1,14 @@ +import { MultipleStoryElementsWrapper } from "vibe-storybook-components"; +import cx from "classnames"; +import styles from "./withGlobalStyle.module.scss"; +import { StoryFn } from "@storybook/react"; + +const WithGlobalStyle = (Story: StoryFn, { className }: { className: string }) => { + return ( + + + + ); +}; + +export default WithGlobalStyle; From 479c48d7b6f3144bdad532892e7a271c1a36516f Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 20:18:33 +0300 Subject: [PATCH 06/16] docs: show default padded layout for story view and iframe view --- packages/core/.storybook/preview.tsx | 6 ++++-- .../decorators/withGlobalStyle/withGlobalStyle.tsx | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/core/.storybook/preview.tsx b/packages/core/.storybook/preview.tsx index 06c998fc60..7ce61d8308 100644 --- a/packages/core/.storybook/preview.tsx +++ b/packages/core/.storybook/preview.tsx @@ -45,8 +45,10 @@ const preview: Preview = { controls: { sort: "alpha" }, - layout: "fullscreen", docs: { + canvas: { + layout: "fullscreen" + }, container: ({ children, context }: { children: any; context: any }) => ( @@ -110,8 +112,8 @@ const preview: Preview = { } }, decorators: [ - withGlobalStyle, withLiveEdit, + withGlobalStyle, withMemoryStats, // Should always be the last decorator (stories hooks issues otherwise) - bug in the addon withThemeByClassName({ diff --git a/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx b/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx index 0e49a1885d..38c239f49d 100644 --- a/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx +++ b/packages/core/src/storybook/decorators/withGlobalStyle/withGlobalStyle.tsx @@ -1,11 +1,11 @@ import { MultipleStoryElementsWrapper } from "vibe-storybook-components"; import cx from "classnames"; import styles from "./withGlobalStyle.module.scss"; -import { StoryFn } from "@storybook/react"; +import { Decorator } from "@storybook/react"; -const WithGlobalStyle = (Story: StoryFn, { className }: { className: string }) => { +const WithGlobalStyle: Decorator = (Story, { className, viewMode }) => { return ( - + ); From 9da8856bc1d3c4ac5c0502d5b5331d1d1179abd5 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 20:20:07 +0300 Subject: [PATCH 07/16] docs: allow disabling entire live edit experience for specific story --- packages/core/.storybook/preview.tsx | 3 +++ .../components/canvas-wrapper/CanvasWrapper.tsx | 11 +++++++++-- .../decorators/withLiveEdit/withLiveEdit.tsx | 13 +++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/core/.storybook/preview.tsx b/packages/core/.storybook/preview.tsx index 7ce61d8308..9d344ed01c 100644 --- a/packages/core/.storybook/preview.tsx +++ b/packages/core/.storybook/preview.tsx @@ -46,6 +46,9 @@ const preview: Preview = { sort: "alpha" }, docs: { + liveEdit: { + enableLiveEdit: true + }, canvas: { layout: "fullscreen" }, diff --git a/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx index d65de6d9b6..cc86b6badb 100644 --- a/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx +++ b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx @@ -17,10 +17,17 @@ const CanvasWrapper: FC = ({ of }) => { [] ); + const liveEditEnabledForStory = story.parameters.docs?.liveEdit?.enableLiveEdit; + return ( <> - -
+ + {liveEditEnabledForStory &&
} ); }; diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx index ed243143ea..dbacbbbec5 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -1,5 +1,6 @@ import { Decorator } from "@storybook/react"; import { useRef, useState } from "react"; +import { Decorator, Parameters as StorybookParameters } from "@storybook/react"; import { vscodeDark } from "@uiw/codemirror-theme-vscode"; import { langs } from "@uiw/codemirror-extensions-langs"; import * as VibeComponents from "../../../components"; @@ -13,7 +14,14 @@ import LiveEditor from "../../components/live-editor/LiveEditor"; const globalScope = { ...VibeComponents, VibeIcons, VibeNext: VibeComponentsNext }; -const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }) => { +type Parameters = StorybookParameters & { + liveEdit?: { + scope?: Record; + enableLiveEdit?: boolean; + }; +}; + +const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters) => { const scope = { ...globalScope, ...parameters.liveEdit?.scope }; const originalCode = useRef(extractCodeFromSource(parameters.docs.source?.originalSource) || ""); const [code, setCode] = useState(originalCode.current); @@ -23,6 +31,7 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }) => { setCode(newVal); setDirty(true); }; + const shouldAllowLiveEdit = viewMode === "docs" && parameters.docs?.liveEdit?.enableLiveEdit; return ( <> @@ -36,7 +45,7 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }) => { ) : ( )} - {viewMode === "docs" && + {shouldAllowLiveEdit && createPortal( Date: Sun, 31 Mar 2024 20:20:54 +0300 Subject: [PATCH 08/16] docs: format code on initial load of editor --- .../decorators/withLiveEdit/prettier-utils.ts | 17 +++++++++++++++++ .../decorators/withLiveEdit/withLiveEdit.tsx | 12 +++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts diff --git a/packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts b/packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts new file mode 100644 index 0000000000..68c99cac9a --- /dev/null +++ b/packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts @@ -0,0 +1,17 @@ +import { format, Options } from "prettier"; +import parserHtml from "prettier/parser-html"; +import parserTypeScript from "prettier/parser-typescript"; + +export function formatCode(code: string): string { + const options: Options = { + parser: "typescript", + arrowParens: "avoid", + trailingComma: "es5", + plugins: [parserHtml, parserTypeScript] + }; + try { + return format(code, options).replace(/;\s*$/, ""); + } catch (e) { + throw new Error(`[Playground Error]: Error formatting code: ${e}`); + } +} diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx index dbacbbbec5..fd8efe98a5 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -1,6 +1,5 @@ -import { Decorator } from "@storybook/react"; -import { useRef, useState } from "react"; import { Decorator, Parameters as StorybookParameters } from "@storybook/react"; +import { useEffect, useRef, useState } from "react"; import { vscodeDark } from "@uiw/codemirror-theme-vscode"; import { langs } from "@uiw/codemirror-extensions-langs"; import * as VibeComponents from "../../../components"; @@ -11,6 +10,7 @@ import { LiveProvider } from "react-live"; import LivePreview from "../../components/live-preview/LivePreview"; import styles from "./withLiveEdit.module.scss"; import LiveEditor from "../../components/live-editor/LiveEditor"; +import { formatCode } from "./prettier-utils"; const globalScope = { ...VibeComponents, VibeIcons, VibeNext: VibeComponentsNext }; @@ -31,6 +31,11 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters setCode(newVal); setDirty(true); }; + + useEffect(() => { + setCode(code => formatCode(code)); + }, []); + const shouldAllowLiveEdit = viewMode === "docs" && parameters.docs?.liveEdit?.enableLiveEdit; return ( @@ -57,7 +62,8 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters setup={{ lineNumbers: false, foldGutter: false, - highlightActiveLine: false + highlightActiveLine: false, + autocompletion: false }} />, document.getElementById(id) || document.body From 612ad57a9a7a0dd1a3d7ee886e1f6edf388d9a04 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 20:21:39 +0300 Subject: [PATCH 09/16] docs: make the indicator have no pointer events --- .../storybook/decorators/withLiveEdit/withLiveEdit.module.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss index aecefa5d5b..c5765d70dd 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.module.scss @@ -8,4 +8,6 @@ color: var(--sb-text-color-on-primary); padding: var(--sb-spacing-xs); font-size: 10px; + pointer-events: none; + user-select: none; } From 125815d3220c7a47626764de00e307b602b9321e Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 31 Mar 2024 20:22:34 +0300 Subject: [PATCH 10/16] docs(Button): add edit experience for button stories --- packages/core/src/components/Button/__stories__/button.mdx | 2 +- .../core/src/components/Button/__stories__/button.stories.tsx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/core/src/components/Button/__stories__/button.mdx b/packages/core/src/components/Button/__stories__/button.mdx index 674e4338f2..e0c3a1a18e 100644 --- a/packages/core/src/components/Button/__stories__/button.mdx +++ b/packages/core/src/components/Button/__stories__/button.mdx @@ -1,5 +1,5 @@ import Button from "../Button"; -import { Canvas, Meta } from "@storybook/blocks"; +import { Meta } from "@storybook/blocks"; import { BUTTON_GROUP, BADGE, diff --git a/packages/core/src/components/Button/__stories__/button.stories.tsx b/packages/core/src/components/Button/__stories__/button.stories.tsx index 5bb92461d5..330025a7ec 100644 --- a/packages/core/src/components/Button/__stories__/button.stories.tsx +++ b/packages/core/src/components/Button/__stories__/button.stories.tsx @@ -26,6 +26,9 @@ export const Overview = { name: "Overview", args: { children: "Button" + }, + parameters: { + liveEdit: { enableLiveEdit: false } } }; From ad9e9463a2950da8448381e2d65e86d4ceb75865 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Mon, 1 Apr 2024 11:18:45 +0300 Subject: [PATCH 11/16] docs(Button): disable live edit for overview story, add Calendar icon to scope of live edit --- .../components/Button/__stories__/button.stories.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/core/src/components/Button/__stories__/button.stories.tsx b/packages/core/src/components/Button/__stories__/button.stories.tsx index 330025a7ec..ec579d73e9 100644 --- a/packages/core/src/components/Button/__stories__/button.stories.tsx +++ b/packages/core/src/components/Button/__stories__/button.stories.tsx @@ -28,7 +28,9 @@ export const Overview = { children: "Button" }, parameters: { - liveEdit: { enableLiveEdit: false } + docs: { + liveEdit: { enableLiveEdit: false } + } } }; @@ -102,7 +104,12 @@ export const Icons = { ), - name: "Icons" + name: "Icons", + parameters: { + docs: { + liveEdit: { scope: { Calendar } } + } + } }; export const LoadingState = { From 177786943ca35fba3de280e05b8a7d9871b18c3e Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Mon, 1 Apr 2024 11:47:00 +0300 Subject: [PATCH 12/16] docs(withLiveEdit): do not fail when prettier fails to format prettier fails because the parsing method at withLiveEdit is currently not generic enough --- .../storybook/decorators/withLiveEdit/prettier-utils.ts | 2 +- .../storybook/decorators/withLiveEdit/withLiveEdit.tsx | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts b/packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts index 68c99cac9a..4d45b279aa 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts +++ b/packages/core/src/storybook/decorators/withLiveEdit/prettier-utils.ts @@ -12,6 +12,6 @@ export function formatCode(code: string): string { try { return format(code, options).replace(/;\s*$/, ""); } catch (e) { - throw new Error(`[Playground Error]: Error formatting code: ${e}`); + throw new Error(`[LiveEdit Error]: Error formatting code: ${e}`); } } diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx index fd8efe98a5..08b0d5cdb9 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -33,7 +33,14 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters }; useEffect(() => { - setCode(code => formatCode(code)); + setCode(code => { + try { + return formatCode(code); + } catch (e) { + console.error(e); + return originalCode.current; + } + }); }, []); const shouldAllowLiveEdit = viewMode === "docs" && parameters.docs?.liveEdit?.enableLiveEdit; From 51a17309f075e408dd4ed1190c9aa21439bf6f64 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Thu, 4 Apr 2024 18:12:05 +0300 Subject: [PATCH 13/16] refactor: rename to isEnabled --- packages/core/.storybook/preview.tsx | 2 +- .../src/components/Button/__stories__/button.stories.tsx | 2 +- .../storybook/components/canvas-wrapper/CanvasWrapper.tsx | 5 +++-- .../src/storybook/decorators/withLiveEdit/withLiveEdit.tsx | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/core/.storybook/preview.tsx b/packages/core/.storybook/preview.tsx index 9d344ed01c..e656ec9f89 100644 --- a/packages/core/.storybook/preview.tsx +++ b/packages/core/.storybook/preview.tsx @@ -47,7 +47,7 @@ const preview: Preview = { }, docs: { liveEdit: { - enableLiveEdit: true + isEnabled: true }, canvas: { layout: "fullscreen" diff --git a/packages/core/src/components/Button/__stories__/button.stories.tsx b/packages/core/src/components/Button/__stories__/button.stories.tsx index ec579d73e9..817e297e48 100644 --- a/packages/core/src/components/Button/__stories__/button.stories.tsx +++ b/packages/core/src/components/Button/__stories__/button.stories.tsx @@ -29,7 +29,7 @@ export const Overview = { }, parameters: { docs: { - liveEdit: { enableLiveEdit: false } + liveEdit: { isEnabled: false } } } }; diff --git a/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx index cc86b6badb..eb356ace7d 100644 --- a/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx +++ b/packages/core/src/storybook/components/canvas-wrapper/CanvasWrapper.tsx @@ -7,7 +7,8 @@ type CanvasWrapper = ComponentProps; const CanvasWrapper: FC = ({ of }) => { const [open, setOpen] = useState(false); - const { story } = useOf(of || "story", ["story"]); + // resolve Storybook story module to get the story id and parameters of current rendered story + const { story } = useOf(of, ["story"]); const toggleCodeAction = useMemo( () => ({ @@ -17,7 +18,7 @@ const CanvasWrapper: FC = ({ of }) => { [] ); - const liveEditEnabledForStory = story.parameters.docs?.liveEdit?.enableLiveEdit; + const liveEditEnabledForStory = story.parameters.docs?.liveEdit?.isEnabled; return ( <> diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx index 08b0d5cdb9..12ec155ba2 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -17,7 +17,7 @@ const globalScope = { ...VibeComponents, VibeIcons, VibeNext: VibeComponentsNext type Parameters = StorybookParameters & { liveEdit?: { scope?: Record; - enableLiveEdit?: boolean; + isEnabled?: boolean; }; }; @@ -43,7 +43,7 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters }); }, []); - const shouldAllowLiveEdit = viewMode === "docs" && parameters.docs?.liveEdit?.enableLiveEdit; + const shouldAllowLiveEdit = viewMode === "docs" && parameters.docs?.liveEdit?.isEnabled; return ( <> From db9360bea5441ef378d66c9e7a1c729644b2eb15 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Fri, 5 Apr 2024 11:39:46 +0300 Subject: [PATCH 14/16] refactor(withLiveEdit): only render portal of id div exists for story --- .../src/storybook/decorators/withLiveEdit/withLiveEdit.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx index 12ec155ba2..09df2de8d9 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -58,6 +58,7 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters )} {shouldAllowLiveEdit && + document.getElementById(id) && createPortal( , - document.getElementById(id) || document.body + document.getElementById(id) )} ); From 7d86de247d1a46e4eda42a89a81feb37fafc94b1 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Fri, 5 Apr 2024 11:48:42 +0300 Subject: [PATCH 15/16] docs(SplitButton): enable LiveEdit --- .../components/Button/__stories__/button.mdx | 2 +- .../Button/__stories__/button.stories.tsx | 12 +----- .../SplitButton/__stories__/splitButton.mdx | 2 +- .../__stories__/splitButton.stories.js | 41 ++++++++++++++++--- .../decorators/withLiveEdit/withLiveEdit.tsx | 2 +- 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/packages/core/src/components/Button/__stories__/button.mdx b/packages/core/src/components/Button/__stories__/button.mdx index e0c3a1a18e..674e4338f2 100644 --- a/packages/core/src/components/Button/__stories__/button.mdx +++ b/packages/core/src/components/Button/__stories__/button.mdx @@ -1,5 +1,5 @@ import Button from "../Button"; -import { Meta } from "@storybook/blocks"; +import { Canvas, Meta } from "@storybook/blocks"; import { BUTTON_GROUP, BADGE, diff --git a/packages/core/src/components/Button/__stories__/button.stories.tsx b/packages/core/src/components/Button/__stories__/button.stories.tsx index 817e297e48..5bb92461d5 100644 --- a/packages/core/src/components/Button/__stories__/button.stories.tsx +++ b/packages/core/src/components/Button/__stories__/button.stories.tsx @@ -26,11 +26,6 @@ export const Overview = { name: "Overview", args: { children: "Button" - }, - parameters: { - docs: { - liveEdit: { isEnabled: false } - } } }; @@ -104,12 +99,7 @@ export const Icons = { ), - name: "Icons", - parameters: { - docs: { - liveEdit: { scope: { Calendar } } - } - } + name: "Icons" }; export const LoadingState = { diff --git a/packages/core/src/components/SplitButton/__stories__/splitButton.mdx b/packages/core/src/components/SplitButton/__stories__/splitButton.mdx index d40864de51..c9acb81731 100644 --- a/packages/core/src/components/SplitButton/__stories__/splitButton.mdx +++ b/packages/core/src/components/SplitButton/__stories__/splitButton.mdx @@ -1,4 +1,4 @@ -import { Canvas, Meta } from "@storybook/blocks"; +import { Meta } from "@storybook/blocks"; import { Link, UsageGuidelines } from "vibe-storybook-components"; import SplitButton from "../SplitButton"; import Button from "../../Button/Button"; diff --git a/packages/core/src/components/SplitButton/__stories__/splitButton.stories.js b/packages/core/src/components/SplitButton/__stories__/splitButton.stories.js index 6c36283053..b91913b34b 100644 --- a/packages/core/src/components/SplitButton/__stories__/splitButton.stories.js +++ b/packages/core/src/components/SplitButton/__stories__/splitButton.stories.js @@ -51,6 +51,11 @@ export const Overview = { ) + }, + parameters: { + docs: { + liveEdit: { isEnabled: false } + } } }; @@ -89,7 +94,13 @@ export const Types = { ), - name: "Types" + name: "Types", + + parameters: { + docs: { + liveEdit: { scope: { Check, Announcement } } + } + } }; export const Sizes = { @@ -128,7 +139,12 @@ export const Sizes = { ), - name: "Sizes" + name: "Sizes", + parameters: { + docs: { + liveEdit: { scope: { Check, Announcement } } + } + } }; export const SplitButtonWithIcons = { @@ -159,7 +175,12 @@ export const SplitButtonWithIcons = { ), - name: "Split button with icons" + name: "Split button with icons", + parameters: { + docs: { + liveEdit: { scope: { Add, Check, Announcement } } + } + } }; export const SplitButtonAsThePrimaryAction = { @@ -176,7 +197,12 @@ export const SplitButtonAsThePrimaryAction = { /> ), - name: "Split button as the primary action" + name: "Split button as the primary action", + parameters: { + docs: { + liveEdit: { scope: { Download, Upload } } + } + } }; export const SecondarySplitButton = { @@ -217,5 +243,10 @@ export const CustomMenu = { ), - name: "Custom menu" + name: "Custom menu", + parameters: { + docs: { + liveEdit: { scope: { Sun, Moon, Favorite } } + } + } }; diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx index 09df2de8d9..cecd0540f6 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -22,7 +22,7 @@ type Parameters = StorybookParameters & { }; const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters) => { - const scope = { ...globalScope, ...parameters.liveEdit?.scope }; + const scope = { ...globalScope, ...parameters.docs?.liveEdit?.scope }; const originalCode = useRef(extractCodeFromSource(parameters.docs.source?.originalSource) || ""); const [code, setCode] = useState(originalCode.current); const [dirty, setDirty] = useState(false); From e40d7de1be41cfe85fd5ca3f3d02a15fcd13cb75 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Sun, 7 Apr 2024 10:25:07 +0300 Subject: [PATCH 16/16] docs(withLiveEdit): better coding - do not use effect - set on initial state + exit immediately if edit is disabled --- .../decorators/withLiveEdit/withLiveEdit.tsx | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx index cecd0540f6..3315b93210 100644 --- a/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx +++ b/packages/core/src/storybook/decorators/withLiveEdit/withLiveEdit.tsx @@ -1,5 +1,5 @@ import { Decorator, Parameters as StorybookParameters } from "@storybook/react"; -import { useEffect, useRef, useState } from "react"; +import { useRef, useState } from "react"; import { vscodeDark } from "@uiw/codemirror-theme-vscode"; import { langs } from "@uiw/codemirror-extensions-langs"; import * as VibeComponents from "../../../components"; @@ -21,10 +21,25 @@ type Parameters = StorybookParameters & { }; }; +function getInitialCodeValue(code: string): string { + try { + return formatCode(code); + } catch (e) { + console.error(e); + return code; + } +} + const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters) => { const scope = { ...globalScope, ...parameters.docs?.liveEdit?.scope }; + const shouldAllowLiveEdit = viewMode === "docs" && parameters.docs?.liveEdit?.isEnabled; + + if (!shouldAllowLiveEdit) { + return ; + } + const originalCode = useRef(extractCodeFromSource(parameters.docs.source?.originalSource) || ""); - const [code, setCode] = useState(originalCode.current); + const [code, setCode] = useState(getInitialCodeValue(originalCode.current)); const [dirty, setDirty] = useState(false); const handleChange = (newVal: string) => { @@ -32,19 +47,6 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters setDirty(true); }; - useEffect(() => { - setCode(code => { - try { - return formatCode(code); - } catch (e) { - console.error(e); - return originalCode.current; - } - }); - }, []); - - const shouldAllowLiveEdit = viewMode === "docs" && parameters.docs?.liveEdit?.isEnabled; - return ( <> {dirty ? ( @@ -57,8 +59,7 @@ const withLiveEdit: Decorator = (Story, { id, parameters, viewMode }: Parameters ) : ( )} - {shouldAllowLiveEdit && - document.getElementById(id) && + {document.getElementById(id) && createPortal(