Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Interactive Graph Editor] Stop cursor jumps in number input fields #1912

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/neat-kiwis-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus-editor": patch
---

[Interactive Graph Editor] Stop cursor jumps in number input fields
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ import type {PropsFor} from "@khanacademy/wonder-blocks-core";
/**
* This is a custom text field of type="number" for use in Perseus Editors.
*
* This makes it so that the text field's input number updates on scroll
* without scrolling the page.
* This component makes it so that
* 1. the text field's input number updates on scroll without
* scrolling the page.
* 2. the input is controlled as long as it does not have focus.
* While it is focused, it becomes editable and emits onChange
* events. This is useful to make sure that input behavior
* remains predictable, rather than possibly having the cursor
* jump around uenxpectedly.
*
* NOTE 1: Native HTML number inputs do not update the number value on scroll,
* they only scroll the page. Inputs in React do NOT work this way (explanation
Expand All @@ -16,10 +22,14 @@ import type {PropsFor} from "@khanacademy/wonder-blocks-core";
* the page to scroll. The behavior in this component is an improvement on
* the React behavior, but it's the opposite of the native HTML behavior.
*
* NOTE 2: Firefox seems to have a custom override for this. Even with this
* stopPropogation, Firefox matches the native HTML behavior.
* NOTE 2: Firefox seems to have a custom override for input scroll. Even
* with this stopPropogation, Firefox matches the native HTML behavior.
*/
const ScrolllessNumberTextField = (props: PropsFor<typeof TextField>) => {
const {value, onChange, ...restOfProps} = props;
const [focused, setFocused] = React.useState(false);
const [wipValue, setWipValue] = React.useState("");

const inputRef = React.useRef<HTMLInputElement>(null);

React.useEffect(() => {
Expand All @@ -39,7 +49,33 @@ const ScrolllessNumberTextField = (props: PropsFor<typeof TextField>) => {
};
}, [inputRef]);

return <TextField type="number" {...props} ref={inputRef} />;
return (
<TextField
{...restOfProps}
type="number"
value={focused ? wipValue : value}
onChange={(newValue) => {
setWipValue(newValue);
onChange(newValue);
}}
onFocus={(e) => {
setWipValue(value);
setFocused(true);

if (props.onFocus) {
props.onFocus(e);
}
}}
onBlur={(e) => {
setFocused(false);

if (props.onBlur) {
props.onBlur(e);
}
}}
ref={inputRef}
/>
);
};

export default ScrolllessNumberTextField;
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const LockedPointSettings = (props: Props) => {
onRemove,
// defining point props
showPoint,
error,
expanded,
onTogglePoint,
onToggle,
Expand Down Expand Up @@ -215,6 +216,7 @@ const LockedPointSettings = (props: Props) => {
coord={coord}
style={styles.spaceUnder}
onChange={handleCoordChange}
error={!!error}
/>

{/* Toggle switch */}
Expand Down