diff --git a/.changeset/sweet-zebras-impress.md b/.changeset/sweet-zebras-impress.md new file mode 100644 index 0000000000..1d94e5f0f4 --- /dev/null +++ b/.changeset/sweet-zebras-impress.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus-editor": patch +--- + +[Storybook: Editor Page] Add a storybook-only preview for the questions and hints in the EditorPage component diff --git a/packages/perseus-editor/src/__stories__/editor-page-with-storybook-preview.tsx b/packages/perseus-editor/src/__stories__/editor-page-with-storybook-preview.tsx new file mode 100644 index 0000000000..b2e859b1ec --- /dev/null +++ b/packages/perseus-editor/src/__stories__/editor-page-with-storybook-preview.tsx @@ -0,0 +1,168 @@ +import { + Renderer, + type APIOptions, + type DeviceType, + type Hint, + type PerseusAnswerArea, + type PerseusRenderer, +} from "@khanacademy/perseus"; +import Button from "@khanacademy/wonder-blocks-button"; +import {View} from "@khanacademy/wonder-blocks-core"; +import IconButton from "@khanacademy/wonder-blocks-icon-button"; +import {Strut} from "@khanacademy/wonder-blocks-layout"; +import {color, spacing} from "@khanacademy/wonder-blocks-tokens"; +import {LabelLarge} from "@khanacademy/wonder-blocks-typography"; +import xIcon from "@phosphor-icons/core/regular/x.svg"; +import {action} from "@storybook/addon-actions"; +import {StyleSheet} from "aphrodite"; +import * as React from "react"; + +// eslint-disable-next-line import/no-relative-packages +import {mockStrings} from "../../../perseus/src/strings"; +import EditorPage from "../editor-page"; + +import {flags} from "./flags-for-api-options"; + +type Props = { + apiOptions?: APIOptions; + question?: PerseusRenderer; + hints?: ReadonlyArray; +}; + +const onChangeAction = action("onChange"); + +function EditorPageWithStorybookPreview(props: Props) { + const [previewDevice, setPreviewDevice] = + React.useState("phone"); + const [jsonMode, setJsonMode] = React.useState(false); + const [answerArea, setAnswerArea] = React.useState< + PerseusAnswerArea | undefined | null + >(); + const [question, setQuestion] = React.useState( + props.question, + ); + const [hints, setHints] = React.useState | undefined>( + props.hints, + ); + + const [panelOpen, setPanelOpen] = React.useState(true); + + const apiOptions = props.apiOptions ?? { + isMobile: false, + flags, + }; + + return ( + + + setPreviewDevice(newDevice) + } + developerMode={true} + jsonMode={jsonMode} + answerArea={answerArea} + question={question} + hints={hints} + frameSource="about:blank" + previewURL="about:blank" + itemId="1" + onChange={(props) => { + onChangeAction(props); + + if ("jsonMode" in props) { + setJsonMode(props.jsonMode); + } + if ("answerArea" in props) { + setAnswerArea(props.answerArea); + } + if ("question" in props) { + setQuestion(props.question); + } + if ("hints" in props) { + setHints(props.hints); + } + }} + /> + + {/* Button to open panel */} + {!panelOpen && ( + + )} + + {/* Panel to show the question/hint previews */} + {panelOpen && ( + + {/* Close button */} + setPanelOpen(!panelOpen)} + style={styles.closeButton} + /> + + + {/* Question preview */} + + + + {/* Hints preview */} + {hints?.map((hint, index) => ( + + + {`Hint ${index + 1}`} + + + ))} + + )} + + ); +} + +const styles = StyleSheet.create({ + panel: { + position: "fixed", + right: 0, + height: "90vh", + overflow: "auto", + flex: "none", + backgroundColor: color.fadedBlue16, + padding: spacing.medium_16, + borderRadius: spacing.small_12, + alignItems: "end", + }, + panelInner: { + flex: "none", + backgroundColor: color.white, + borderRadius: spacing.xSmall_8, + marginTop: spacing.medium_16, + width: "100%", + padding: spacing.xSmall_8, + }, + closeButton: { + margin: 0, + }, + openPanelButton: { + position: "fixed", + right: spacing.medium_16, + // Extra space so it doesn't get covered up by storybook's + // "Style warnings" button. + bottom: spacing.xxxLarge_64, + }, +}); + +export default EditorPageWithStorybookPreview; diff --git a/packages/perseus-editor/src/__stories__/editor-page.stories.tsx b/packages/perseus-editor/src/__stories__/editor-page.stories.tsx index 0af4a00cdd..286452723b 100644 --- a/packages/perseus-editor/src/__stories__/editor-page.stories.tsx +++ b/packages/perseus-editor/src/__stories__/editor-page.stories.tsx @@ -10,6 +10,7 @@ import {EditorPage} from ".."; import {segmentWithLockedFigures} from "../../../perseus/src/widgets/__testdata__/interactive-graph.testdata"; import {registerAllWidgetsAndEditorsForTesting} from "../util/register-all-widgets-and-editors-for-testing"; +import EditorPageWithStorybookPreview from "./editor-page-with-storybook-preview"; import {flags} from "./flags-for-api-options"; import type { @@ -28,67 +29,12 @@ export default { const onChangeAction = action("onChange"); export const Demo = (): React.ReactElement => { - const [previewDevice, setPreviewDevice] = - React.useState("phone"); - const [jsonMode, setJsonMode] = React.useState(false); - const [answerArea, setAnswerArea] = React.useState< - PerseusAnswerArea | undefined | null - >(); - const [question, setQuestion] = React.useState< - PerseusRenderer | undefined - >(); - const [hints, setHints] = React.useState | undefined>(); - - return ( - setPreviewDevice(newDevice)} - developerMode={true} - jsonMode={jsonMode} - answerArea={answerArea} - question={question} - hints={hints} - frameSource="about:blank" - previewURL="about:blank" - itemId="1" - onChange={(props) => { - onChangeAction(props); - - if ("jsonMode" in props) { - setJsonMode(props.jsonMode); - } - if ("answerArea" in props) { - setAnswerArea(props.answerArea); - } - if ("question" in props) { - setQuestion(props.question); - } - if ("hints" in props) { - setHints(props.hints); - } - }} - /> - ); + return ; }; export const MafsWithLockedFiguresCurrent = (): React.ReactElement => { - const [previewDevice, setPreviewDevice] = - React.useState("phone"); - const [jsonMode, setJsonMode] = React.useState(false); - const [answerArea, setAnswerArea] = React.useState< - PerseusAnswerArea | undefined | null - >(); - const [question, setQuestion] = React.useState( - segmentWithLockedFigures, - ); - const [hints, setHints] = React.useState | undefined>(); - return ( - { }, }, }} - previewDevice={previewDevice} - onPreviewDeviceChange={(newDevice) => setPreviewDevice(newDevice)} - developerMode={true} - jsonMode={jsonMode} - answerArea={answerArea} - question={question} - hints={hints} - frameSource="about:blank" - previewURL="about:blank" - itemId="1" - onChange={(props) => { - onChangeAction(props); - - if ("jsonMode" in props) { - setJsonMode(props.jsonMode); - } - if ("answerArea" in props) { - setAnswerArea(props.answerArea); - } - if ("question" in props) { - setQuestion(props.question); - } - if ("hints" in props) { - setHints(props.hints); - } - }} + question={segmentWithLockedFigures} /> ); }; @@ -138,19 +59,8 @@ MafsWithLockedFiguresCurrent.parameters = { }; export const MafsWithLockedFiguresM2Flag = (): React.ReactElement => { - const [previewDevice, setPreviewDevice] = - React.useState("phone"); - const [jsonMode, setJsonMode] = React.useState(false); - const [answerArea, setAnswerArea] = React.useState< - PerseusAnswerArea | undefined | null - >(); - const [question, setQuestion] = React.useState( - segmentWithLockedFigures, - ); - const [hints, setHints] = React.useState | undefined>(); - return ( - { }, }, }} - previewDevice={previewDevice} - onPreviewDeviceChange={(newDevice) => setPreviewDevice(newDevice)} - developerMode={true} - jsonMode={jsonMode} - answerArea={answerArea} - question={question} - hints={hints} - frameSource="about:blank" - previewURL="about:blank" - itemId="1" - onChange={(props) => { - onChangeAction(props); - - if ("jsonMode" in props) { - setJsonMode(props.jsonMode); - } - if ("answerArea" in props) { - setAnswerArea(props.answerArea); - } - if ("question" in props) { - setQuestion(props.question); - } - if ("hints" in props) { - setHints(props.hints); - } - }} + question={segmentWithLockedFigures} /> ); }; @@ -200,50 +85,8 @@ MafsWithLockedFiguresM2Flag.parameters = { }; export const MafsWithLockedFiguresM2bFlag = (): React.ReactElement => { - const [previewDevice, setPreviewDevice] = - React.useState("phone"); - const [jsonMode, setJsonMode] = React.useState(false); - const [answerArea, setAnswerArea] = React.useState< - PerseusAnswerArea | undefined | null - >(); - const [question, setQuestion] = React.useState( - segmentWithLockedFigures, - ); - const [hints, setHints] = React.useState | undefined>(); - return ( - setPreviewDevice(newDevice)} - developerMode={true} - jsonMode={jsonMode} - answerArea={answerArea} - question={question} - hints={hints} - frameSource="about:blank" - previewURL="about:blank" - itemId="1" - onChange={(props) => { - onChangeAction(props); - - if ("jsonMode" in props) { - setJsonMode(props.jsonMode); - } - if ("answerArea" in props) { - setAnswerArea(props.answerArea); - } - if ("question" in props) { - setQuestion(props.question); - } - if ("hints" in props) { - setHints(props.hints); - } - }} - /> + ); };