Skip to content

Commit f89e3f6

Browse files
Add new editingDisabled feature to our Perseus Editors (#2958)
## Summary: <img width="930" height="480" alt="notouching" src="https://github.com/user-attachments/assets/66531ce4-0bda-44ab-9d77-8c1a868efb68" /> This PR is a proposal for implementing an `editingDisabled` feature to our Perseus Editors, which will allow us to stop Content Creators from performing any changes during a Content Backfill. Essentially, I've added a new `editingDisabled` property to our APIOptions, that I then use to do the following: 1. I've added a fieldset and a class around our Editors that becomes disabled when `editingDisabled` is true. This ensures that all of our interactive elements are clearly "disabled" by giving them a slight fade and a darker background for our inputs. 2. I've also had to pipe down the value to several widget editors in order to solve some unique edge cases: Plotter, Dropdown, Interactive Graph, Matrix, Table, Grapher, Label Image. I've used editingDisabled whenever we're dealing with larger wrapper components, and I've used disabled when I need to access the value in more generic form control components. As part of this work, I updated a couple editor inputs to use Wonderblocks instead of the link `<a>` tags we were abusing previously. This provides improved a11y, design, and the ability to properly disable the elements. [Storybook Exercise Editor Page with Editing Disabled](https://650db21c3f5d1b2f13c02952-xfzsqzdoaj.chromatic.com/?path=/story/editors-editorpage--with-editing-disabled) [Storybook Article Editor with Editing Disabled](https://650db21c3f5d1b2f13c02952-xfzsqzdoaj.chromatic.com/?path=/story/editors-articleeditor--with-editing-disabled) **Note:** Ideally, we'd have this property directly applied to all inputs in the widget editors. I could certainly do that, but I was looking for a compromise between time investment and maintainability. I'm open to push back on this, and I could either hook everything up in this PR or make a ticket to do this in the near future. Issue: CP-9813 ## Test plan: - Manual Testing - Tests pass - New "WithEditingDisabled" Story pages for the Article and Exercise Editors, which includes all available widgets. Author: SonicScrewdriver Reviewers: SonicScrewdriver, nishasy, jeremywiebe, ivyolamit, mark-fitzgerald, anakaren-rojas Required Reviewers: Approved By: nishasy, jeremywiebe Checks: ✅ 10 checks were successful Pull Request URL: #2958
1 parent c9f7b12 commit f89e3f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1566
-288
lines changed

.changeset/stale-elephants-bake.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@khanacademy/perseus": minor
3+
"@khanacademy/perseus-editor": minor
4+
---
5+
6+
Creation of a new editingDisabled mode for our Perseus Editors

.storybook/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ const config: StorybookConfig = {
105105
body {
106106
font-size: 1.4rem;
107107
padding: 1.6rem 1.6rem 1.6rem 4.8rem !important;
108+
line-height: 1.4;
108109
}
109110
</style>
110111
`,

.storybook/preview-head.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787
<style>
8888
body {
8989
font-family: "Lato", sans-serif;
90-
font-size: 16px !important;
9190
}
9291

9392
/* Overrides the ArgTypes table tabs to avoid some z-index issues with

.storybook/styles/base-page-styles.css

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
html element. This allow us to use 10px as the base font size for scaling
1414
rem units properly. */
1515
font-size: var(--wb-sizing-size_140);
16-
line-height: var(--wb-sizing-size_140);
16+
line-height: 1.4;
1717
height: 100%;
1818
margin: var(--wb-sizing-size_0);
1919
color: var(--wb-semanticColor-core-foreground-neutral-strong);
@@ -40,4 +40,12 @@
4040
.box-sizing-content-box-reset * {
4141
box-sizing: inherit;
4242
}
43+
44+
/* Reset fieldset styles to prevent layout issues and replicate production styles */
45+
fieldset {
46+
margin: 0;
47+
padding: 0;
48+
border: none;
49+
min-inline-size: 0;
50+
}
4351
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {ApiOptions} from "@khanacademy/perseus";
2+
import * as React from "react";
3+
import {useRef} from "react";
4+
5+
import {testDependenciesV2} from "../../../../testing/test-dependencies";
6+
import {comprehensiveQuestion} from "../__testdata__/all-widgets.testdata";
7+
import ArticleEditor from "../article-editor";
8+
import {registerAllWidgetsAndEditorsForTesting} from "../util/register-all-widgets-and-editors-for-testing";
9+
import "../styles/perseus-editor.css"; // This helps ensure the styles are loaded correctly and timely
10+
11+
// This is to address timing - Perseus widget editor registry accessed before initialization!
12+
registerAllWidgetsAndEditorsForTesting();
13+
14+
export default {
15+
title: "Editors/ArticleEditor/Visual Regression Tests",
16+
component: ArticleEditor,
17+
tags: ["!dev"],
18+
parameters: {
19+
docs: {
20+
description: {
21+
component:
22+
"Visual regression tests for the article editor in initial state.",
23+
},
24+
},
25+
chromatic: {disableSnapshot: false, delay: 500},
26+
},
27+
};
28+
29+
export const WithEditingDisabled = (): React.ReactElement => {
30+
const articleEditorRef = useRef();
31+
const disabledApiOptions = {
32+
...ApiOptions.defaults,
33+
editingDisabled: true,
34+
};
35+
36+
return (
37+
<ArticleEditor
38+
dependencies={testDependenciesV2}
39+
apiOptions={disabledApiOptions}
40+
imageUploader={() => {}}
41+
json={[comprehensiveQuestion]}
42+
onChange={() => {}}
43+
previewURL="/perseus/frame"
44+
ref={articleEditorRef as any}
45+
/>
46+
);
47+
};

packages/perseus-editor/src/__docs__/article-editor.stories.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import * as React from "react";
44
import {useRef, useState} from "react";
55

66
import {testDependenciesV2} from "../../../../testing/test-dependencies";
7+
import {comprehensiveQuestion} from "../__testdata__/all-widgets.testdata";
78
import ArticleEditor from "../article-editor";
89
import ContentPreview from "../content-preview";
910
import {registerAllWidgetsAndEditorsForTesting} from "../util/register-all-widgets-and-editors-for-testing";
1011

1112
import PreviewPanel from "./preview-panel";
13+
import "../styles/perseus-editor.css"; // This helps ensure the styles are loaded correctly and timely
1214

1315
// This is to address timing - Perseus widget editor registry accessed before initialization!
1416
registerAllWidgetsAndEditorsForTesting();
@@ -54,3 +56,23 @@ export const Demo = (): React.ReactElement => {
5456
</View>
5557
);
5658
};
59+
60+
export const WithEditingDisabled = (): React.ReactElement => {
61+
const articleEditorRef = useRef();
62+
const disabledApiOptions = {
63+
...ApiOptions.defaults,
64+
editingDisabled: true,
65+
};
66+
67+
return (
68+
<ArticleEditor
69+
dependencies={testDependenciesV2}
70+
apiOptions={disabledApiOptions}
71+
imageUploader={() => {}}
72+
json={[comprehensiveQuestion]}
73+
onChange={() => {}}
74+
previewURL="/perseus/frame"
75+
ref={articleEditorRef as any}
76+
/>
77+
);
78+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as React from "react";
2+
3+
import {comprehensiveQuestion} from "../__testdata__/all-widgets.testdata";
4+
import {registerAllWidgetsAndEditorsForTesting} from "../util/register-all-widgets-and-editors-for-testing";
5+
6+
import EditorPageWithStorybookPreview from "./editor-page-with-storybook-preview";
7+
import "../styles/perseus-editor.css"; // This helps ensure the styles are loaded correctly and timely
8+
9+
// This is to address timing - Perseus widget editor registry accessed before initialization!
10+
registerAllWidgetsAndEditorsForTesting();
11+
12+
export default {
13+
title: "Editors/EditorPage/Visual Regression Tests",
14+
tags: ["!dev"],
15+
parameters: {
16+
docs: {
17+
description: {
18+
component:
19+
"Visual regression tests for the editor page in initial state.",
20+
},
21+
},
22+
chromatic: {disableSnapshot: false, delay: 500},
23+
},
24+
};
25+
26+
export const WithEditingDisabled = (): React.ReactElement => {
27+
const disabledApiOptions = {
28+
editingDisabled: true,
29+
isMobile: false,
30+
};
31+
32+
return (
33+
<EditorPageWithStorybookPreview
34+
question={comprehensiveQuestion}
35+
apiOptions={disabledApiOptions}
36+
/>
37+
);
38+
};

packages/perseus-editor/src/__docs__/editor-page.stories.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import {PerseusFeatureFlags} from "@khanacademy/perseus-core";
22
import * as React from "react";
33

4+
import {comprehensiveQuestion} from "../__testdata__/all-widgets.testdata";
5+
import {question as definitionQuestion} from "../__testdata__/definition.testdata";
6+
import {question1} from "../__testdata__/numeric-input.testdata";
7+
import {singleSelectQuestion} from "../__testdata__/radio.testdata";
48
import {registerAllWidgetsAndEditorsForTesting} from "../util/register-all-widgets-and-editors-for-testing";
59

610
import EditorPageWithStorybookPreview from "./editor-page-with-storybook-preview";
11+
import "../styles/perseus-editor.css"; // This helps ensure the styles are loaded correctly and timely
712

813
// This is to address timing - Perseus widget editor registry accessed before initialization!
914
registerAllWidgetsAndEditorsForTesting();
@@ -37,3 +42,33 @@ export const WithAllFlags = (): React.ReactElement => {
3742
/>
3843
);
3944
};
45+
46+
export const WithNumericInput = (): React.ReactElement => {
47+
return <EditorPageWithStorybookPreview question={question1} />;
48+
};
49+
50+
export const WithRadioWidget = (): React.ReactElement => {
51+
return <EditorPageWithStorybookPreview question={singleSelectQuestion} />;
52+
};
53+
54+
export const WithDefinitionWidget = (): React.ReactElement => {
55+
return <EditorPageWithStorybookPreview question={definitionQuestion} />;
56+
};
57+
58+
export const WithEditingDisabled = (): React.ReactElement => {
59+
const disabledApiOptions = {
60+
editingDisabled: true,
61+
isMobile: false,
62+
};
63+
64+
return (
65+
<EditorPageWithStorybookPreview
66+
question={comprehensiveQuestion}
67+
apiOptions={disabledApiOptions}
68+
/>
69+
);
70+
};
71+
72+
export const WithAllWidgets = (): React.ReactElement => {
73+
return <EditorPageWithStorybookPreview question={comprehensiveQuestion} />;
74+
};

packages/perseus-editor/src/__docs__/item-editor.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const Wrapper = (props: Props) => {
2121
onChange?.(e); // to register action in storybook
2222
setExtras((prevExtras) => ({...prevExtras, ...e}));
2323
}}
24+
editingDisabled={false}
2425
/>
2526
);
2627
};

0 commit comments

Comments
 (0)