-
Notifications
You must be signed in to change notification settings - Fork 350
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Perseus Editor: Add ContentPreview component (#1521)
## Summary: This PR introduces a new editor component: `ContentPreview`. It is a thin wrapper around `ServerItemRenderer` which provides an easy way for editors to preview a given Perseus Item. It should be noted that due to current Perseus styling, the preview will _not_ match production 100%. This is because Perseus styles are adjusted based `@media` queries on device width. <img width="768" alt="image" src="https://github.com/user-attachments/assets/6b0a9369-f814-446f-9ce5-0f3c6db94518"> Issue: LEMS-1809 ## Test plan: View the prevew in Storybook. `yarn start` ==> http://localhost:6006/?path=/docs/perseuseditor-content-preview--docs Author: jeremywiebe Reviewers: jeremywiebe, mpolyak, #perseus, mahtabsabet Required Reviewers: Approved By: mpolyak Checks: ✅ Upload Coverage (ubuntu-latest, 20.x), ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Jest Coverage (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald Pull Request URL: #1521
- Loading branch information
1 parent
6db145f
commit a9292af
Showing
11 changed files
with
370 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@khanacademy/perseus": patch | ||
--- | ||
|
||
Migrate Lint component to use WonderBlocks ToolTip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@khanacademy/perseus-editor": minor | ||
--- | ||
|
||
Add ContentPreview component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@khanacademy/perseus-dev-ui": patch | ||
--- | ||
|
||
Update vite config to alias `/strings` expots to correct strings.ts file per package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
packages/perseus-editor/src/__stories__/content-preview.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import {View} from "@khanacademy/wonder-blocks-core"; | ||
import {spacing} from "@khanacademy/wonder-blocks-tokens"; | ||
import {useState} from "react"; | ||
|
||
import {articleWithImages} from "../../../perseus/src/__testdata__/article-renderer.testdata"; | ||
import {mockStrings} from "../../../perseus/src/strings"; | ||
import {question} from "../../../perseus/src/widgets/__testdata__/radio.testdata"; | ||
import DeviceFramer from "../components/device-framer"; | ||
import ViewportResizer from "../components/viewport-resizer"; | ||
import ContentPreview from "../content-preview"; | ||
|
||
import type {DeviceType} from "@khanacademy/perseus"; | ||
import type {Meta, StoryObj} from "@storybook/react"; | ||
|
||
import "../styles/perseus-editor.less"; | ||
|
||
const PreviewWrapper = (props) => { | ||
const [previewDevice, setPreviewDevice] = useState<DeviceType>("phone"); | ||
|
||
return ( | ||
<View> | ||
<ViewportResizer | ||
deviceType={previewDevice} | ||
onViewportSizeChanged={setPreviewDevice} | ||
/> | ||
<DeviceFramer nochrome={false} deviceType={previewDevice}> | ||
<ContentPreview {...props} /> | ||
</DeviceFramer> | ||
</View> | ||
); | ||
}; | ||
|
||
const meta: Meta<typeof ContentPreview> = { | ||
title: "PerseusEditor/Content Preview", | ||
component: ContentPreview, | ||
args: { | ||
strings: mockStrings, | ||
}, | ||
decorators: [ | ||
(Story) => ( | ||
<View style={{margin: spacing.xxSmall_6}}> | ||
<Story /> | ||
</View> | ||
), | ||
], | ||
render: (props) => <PreviewWrapper {...props} />, | ||
}; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof ContentPreview>; | ||
|
||
export const Exercise: Story = { | ||
args: { | ||
question, | ||
}, | ||
}; | ||
|
||
export const Article: Story = { | ||
args: { | ||
question: articleWithImages, | ||
}, | ||
}; | ||
|
||
export const WithLintErrors: Story = { | ||
args: { | ||
linterContext: { | ||
contentType: "exercise", | ||
highlightLint: true, | ||
stack: [], | ||
paths: [], | ||
}, | ||
question: { | ||
content: `# H1s bad | ||
Here is some unclosed math: $1+1=3 | ||
We should use \`\\dfrac{}\` instead of \`\\frac{}\`: $\\frac{3}{5}$ | ||
What is the best color in the world? | ||
[[☃ radio 1]]`, | ||
widgets: { | ||
"radio 1": { | ||
type: "radio", | ||
options: { | ||
choices: [ | ||
{content: "Red"}, | ||
{content: "# Green"}, | ||
{content: "Blue", correct: true}, | ||
{ | ||
content: "None of these!", | ||
isNoneOfTheAbove: true, | ||
}, | ||
], | ||
}, | ||
}, | ||
}, | ||
images: {}, | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { | ||
KeypadContext, | ||
StatefulKeypadContextProvider, | ||
} from "@khanacademy/keypad-context"; | ||
import {MobileKeypad} from "@khanacademy/math-input"; | ||
import { | ||
Renderer, | ||
constants, | ||
type APIOptions, | ||
type DeviceType, | ||
type PerseusRenderer, | ||
} from "@khanacademy/perseus"; | ||
import {View} from "@khanacademy/wonder-blocks-core"; | ||
import {spacing} from "@khanacademy/wonder-blocks-tokens"; | ||
import {StyleSheet} from "aphrodite"; | ||
|
||
import type {LinterContextProps} from "@khanacademy/perseus-linter"; | ||
import type {PropsFor} from "@khanacademy/wonder-blocks-core"; | ||
|
||
/** | ||
* The `ContentPreview` component provides a simple preview system for Perseus | ||
* Content. Due to how Persus styles are built, the preview styling matches the | ||
* current device based on the viewport width (using `@media` queries for | ||
* `min-width` and `max-width`). | ||
* | ||
* The preview will render the mobile variant (styling and layout) when the | ||
* `previewDevice` is phone or tablet. Note that the styling cannot be matched | ||
* 100% due to the above `@media` query limitation. | ||
*/ | ||
function ContentPreview({ | ||
question, | ||
apiOptions, | ||
seamless, | ||
linterContext, | ||
legacyPerseusLint, | ||
previewDevice, | ||
strings, | ||
}: { | ||
question?: PerseusRenderer; | ||
apiOptions?: APIOptions; | ||
seamless?: boolean; | ||
linterContext?: LinterContextProps; | ||
legacyPerseusLint?: ReadonlyArray<string>; | ||
previewDevice: DeviceType; | ||
strings: PropsFor<typeof Renderer>["strings"]; | ||
}) { | ||
const isMobile = previewDevice !== "desktop"; | ||
|
||
const className = isMobile ? "perseus-mobile" : ""; | ||
|
||
return ( | ||
<View | ||
className={`framework-perseus ${className}`} | ||
style={[styles.container, !seamless ? styles.gutter : undefined]} | ||
> | ||
<StatefulKeypadContextProvider> | ||
<KeypadContext.Consumer> | ||
{({setKeypadActive, keypadElement, setKeypadElement}) => ( | ||
<> | ||
<Renderer | ||
strings={strings} | ||
apiOptions={{...apiOptions, isMobile}} | ||
keypadElement={keypadElement} | ||
linterContext={linterContext} | ||
legacyPerseusLint={legacyPerseusLint} | ||
{...question} | ||
/> | ||
|
||
<MobileKeypad | ||
onAnalyticsEvent={() => Promise.resolve()} | ||
onDismiss={() => setKeypadActive(false)} | ||
onElementMounted={setKeypadElement} | ||
/> | ||
</> | ||
)} | ||
</KeypadContext.Consumer> | ||
</StatefulKeypadContextProvider> | ||
</View> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
padding: spacing.xxxSmall_4, | ||
containerType: "inline-size", | ||
containerName: "perseus-root", | ||
}, | ||
gutter: {marginRight: constants.lintGutterWidth}, | ||
}); | ||
|
||
export default ContentPreview; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.