Skip to content

Commit

Permalink
Roll v2 Keypad Onto Desktop Web (#645)
Browse files Browse the repository at this point in the history
https://github.com/Khan/perseus/assets/23404711/b199ff5b-9db6-4394-8ef3-120531564ab3

Updates Perseus / Math Input to use keypad.

Also changes how it's used: 

- Instead of a set of keys appearing on focus, the button on the right acts as a toggle.
- Instead of a warning icon appearing when there is an parsing, the input shows a red "invalid" state and a tooltip appears with a friendly message.
- ~~There is no longer a `buttonsVisible` prop, since visibility is managed by the toggle. I believe this disabled the buttons in some cases. @jeremywiebe do we still need that ability?~~
  - This has been restored. The three states are:
    - `focused` default behavior, toggle off to start
    - `always` default behavior, toggle on to start
    - `never` toggle button disabled
- ~~`buttonSets` went from "any" that seemed to take an array to an object with fields that reflect the props on Keypad that toggle the presence of tabs.~~
  - `buttonSets` type was restored but marked deprecated in jsDocs
    - `keypadButtonSets` prop added that takes new type
    - `buttonSets` maps to `keypadButtonSets`
- Also adds optional `extraKeys` prop that takes an array of `Keys`.

Author: nedredmond

Reviewers: jeremywiebe, nedredmond, handeyeco

Required Reviewers:

Approved By: jeremywiebe, jeremywiebe

Checks: ✅ finish_coverage, ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 16.x), ✅ Publish npm snapshot (ubuntu-latest, 16.x), ✅ Extract i18n strings (ubuntu-latest, 16.x), ✅ Check builds for changes in size (ubuntu-latest, 16.x), ✅ Cypress Coverage (ubuntu-latest, 16.x), ✅ Jest Coverage (ubuntu-latest, 16.x), ✅ gerald, ✅ Check for .changeset file (ubuntu-latest, 16.x)

Pull Request URL: #645
  • Loading branch information
nedredmond authored Aug 15, 2023
1 parent 196d2a3 commit e036092
Show file tree
Hide file tree
Showing 11 changed files with 431 additions and 318 deletions.
9 changes: 9 additions & 0 deletions .changeset/great-pigs-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@khanacademy/perseus": major
"@khanacademy/perseus-editor": patch
---

# Update MathInput

- `buttonSets` is now deprecated in favor of `keypadButtonSets`, but currently maps to the new prop for backwards compatability.
- `buttonsVisible` is now a bit misleading: "focused" is the default state with a toggle-able keypad and "always" shows the keypad by default.
12 changes: 6 additions & 6 deletions packages/perseus-editor/src/widgets/expression-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class ExpressionEditor extends React.Component<any, any> {

render(): React.ReactNode {
const answerOptions = this.props.answerForms
.map((obj, index) => {
.map((obj: {form: any; simplify: any; value: any; key: number}) => {
const expressionProps = {
// note we're using
// *this.props*.{times,functions,buttonSets} since each
Expand All @@ -112,22 +112,22 @@ class ExpressionEditor extends React.Component<any, any> {
simplify: obj.simplify,
value: obj.value,

onChange: (props) => this.updateForm(index, props),
onChange: (props) => this.updateForm(obj.key, props),
trackInteraction: () => {},

widgetId: this.props.widgetId + "-" + index,
widgetId: this.props.widgetId + "-" + obj.key,
} as const;

return lens(obj)
.merge([], {
draggable: true,
onChange: (props) => this.updateForm(index, props),
onDelete: () => this.handleRemoveForm(index),
onChange: (props) => this.updateForm(obj.key, props),
onDelete: () => this.handleRemoveForm(obj.key),
expressionProps: expressionProps,
})
.freeze();
})
.map((obj, index) => <AnswerOption key={index} {...obj} />);
.map((obj) => <AnswerOption key={obj.key} {...obj} />);

const sortable = (
<SortableArea
Expand Down
25 changes: 0 additions & 25 deletions packages/perseus-editor/src/widgets/interaction-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,13 @@ class PointEditor extends React.Component<PointEditorProps> {
<div className="perseus-widget-row">
Coordinate: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.coordX}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
onChange={this.change("coordX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.coordY}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand Down Expand Up @@ -143,15 +141,13 @@ class LineEditor extends React.Component<LineEditorProps> {
<div className="perseus-widget-row">
Start: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.startX}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
onChange={this.change("startX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.startY}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand All @@ -162,15 +158,13 @@ class LineEditor extends React.Component<LineEditorProps> {
<div className="perseus-widget-row">
End: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.endX}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
onChange={this.change("endX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.endY}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand Down Expand Up @@ -260,14 +254,12 @@ class MovablePointEditor extends React.Component<MovablePointEditorProps> {
<div className="perseus-widget-row">
Start: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.startX}
onChange={this.change("startX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.startY}
onChange={this.change("startY")}
Expand Down Expand Up @@ -340,14 +332,12 @@ class MovableLineEditor extends React.Component<MovableLineEditorProps> {
<div className="perseus-widget-row">
Start: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.startX}
onChange={this.change("startX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.startY}
onChange={this.change("startY")}
Expand All @@ -357,14 +347,12 @@ class MovableLineEditor extends React.Component<MovableLineEditorProps> {
<div className="perseus-widget-row">
End: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.endX}
onChange={this.change("endX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.endY}
onChange={this.change("endY")}
Expand Down Expand Up @@ -440,7 +428,6 @@ class FunctionEditor extends React.Component<FunctionEditorProps> {
<div className="perseus-widget-row">
<TeX>{this.props.funcName + "(x)="}</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.value}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand All @@ -450,15 +437,13 @@ class FunctionEditor extends React.Component<FunctionEditorProps> {
<div className="perseus-widget-row">
Range: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.rangeMin}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
onChange={this.change("rangeMin")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.rangeMax}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand Down Expand Up @@ -541,7 +526,6 @@ class ParametricEditor extends React.Component<ParametricEditorProps> {
<div className="perseus-widget-row">
<TeX>X(t) =</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.x}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand All @@ -551,7 +535,6 @@ class ParametricEditor extends React.Component<ParametricEditorProps> {
<div className="perseus-widget-row">
<TeX>Y(t) =</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.y}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand All @@ -561,15 +544,13 @@ class ParametricEditor extends React.Component<ParametricEditorProps> {
<div className="perseus-widget-row">
Range: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.rangeMin}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
onChange={this.change("rangeMin")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.rangeMax}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand Down Expand Up @@ -657,15 +638,13 @@ class LabelEditor extends React.Component<LabelEditorProps> {
<div className="perseus-widget-row">
Location: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.coordX}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
onChange={this.change("coordX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.coordY}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand Down Expand Up @@ -726,15 +705,13 @@ class RectangleEditor extends React.Component<RectangleEditorProps> {
<div className="perseus-widget-row">
Bottom left: <TeX>\Large(</TeX>
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.coordX}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
onChange={this.change("coordX")}
/>
<TeX>,</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.coordY}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand All @@ -745,7 +722,6 @@ class RectangleEditor extends React.Component<RectangleEditorProps> {
<div className="perseus-widget-row">
Width:{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.width}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand All @@ -755,7 +731,6 @@ class RectangleEditor extends React.Component<RectangleEditorProps> {
<div className="perseus-widget-row">
Height:{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.height}
// @ts-expect-error [FEI-5003] - TS2554 - Expected 3 arguments, but got 1.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ class ConstraintEditor extends React.Component<Props> {
<div className="perseus-widget-row">
<TeX>x=</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.constraintFn}
onChange={this.change("constraintFn")}
Expand All @@ -89,7 +88,6 @@ class ConstraintEditor extends React.Component<Props> {
<div className="perseus-widget-row">
<TeX>y=</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.constraintFn}
onChange={this.change("constraintFn")}
Expand All @@ -102,14 +100,12 @@ class ConstraintEditor extends React.Component<Props> {
<div className="perseus-widget-row">
<TeX>x \in \Large[</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.constraintXMin}
onChange={this.change("constraintXMin")}
/>
<TeX>, </TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.constraintXMax}
onChange={this.change("constraintXMax")}
Expand All @@ -121,14 +117,12 @@ class ConstraintEditor extends React.Component<Props> {
<div className="perseus-widget-row">
<TeX>y \in \Large[</TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.constraintYMin}
onChange={this.change("constraintYMin")}
/>
<TeX>, </TeX>{" "}
<MathInput
buttonSets={[]}
buttonsVisible="never"
value={this.props.constraintYMax}
onChange={this.change("constraintYMax")}
Expand Down
20 changes: 16 additions & 4 deletions packages/perseus/src/components/__stories__/math-input.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ export default {
} as Story;

const defaultObject = {
buttonSets: ["basic"],
keypadButtonSets: {
advancedRelations: true,
basicRelations: true,
divisionKey: true,
logarithms: true,
preAlgebra: true,
trigonometry: true,
},
onChange: () => {},
} as const;

Expand All @@ -22,9 +29,14 @@ export const DefaultWithBasicButtonSet = (
): React.ReactElement => {
return <MathInput {...defaultObject} />;
};
export const AlwaysVisibleButtonSet = (args: StoryArgs): React.ReactElement => {
return <MathInput {...defaultObject} buttonsVisible="always" />;
};
export const DefaultWithAriaLabel = (args: StoryArgs): React.ReactElement => {
return <MathInput {...defaultObject} labelText="Sample label" />;
};

export const KeypadOpenByDefault = (args: StoryArgs): React.ReactElement => {
return <MathInput {...defaultObject} buttonsVisible="always" />;
};

export const KeypadNeverVisible = (args: StoryArgs): React.ReactElement => {
return <MathInput {...defaultObject} buttonsVisible="never" />;
};
Loading

0 comments on commit e036092

Please sign in to comment.