-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Improve arrow nav (horizontal only) #2431
Conversation
e0aa5ea
to
cfdcc38
Compare
Codecov Report
@@ Coverage Diff @@
## master #2431 +/- ##
==========================================
- Coverage 26.44% 25.69% -0.76%
==========================================
Files 157 157
Lines 4851 5079 +228
Branches 819 894 +75
==========================================
+ Hits 1283 1305 +22
- Misses 3015 3152 +137
- Partials 553 622 +69
Continue to review full report at Codecov.
|
I wonder if it's a good idea to add some static methods to Editable for Editable specific logic, and getting the next editor etc. |
Several notes here:
Basically, What I'm proposing is something like this: if ( isEdge( currentTabbable ) ) {
const nextTabbable = getNextTabbable( currentTabbable );
focusBeginingOrEndOfNextTabbbable( nextTabbable );
} with TinyMCE as a special case of "tabbable", and handled like a special case inside these functions. Is it possible this way? |
That's what it's doing, using the TinyMCE API. But we have to fall back to onFocus if there is no editable (or nothing at all) in the next block, no?
Hm, I'm not sure how to reproduce.
Sounds good to me. Sounds like it's the same thing but slightly abstracted. |
Do you think we should do #2424 first? |
I do feel like we should try to handle keys at the source. So Editable or a modified textarea would signal when to handle focus. Instead of a wrapper around all of it which tries to handle the keys without context. |
Understood, I was thinking we could consider the block's wrapper as a "tabbable" but the question would be how we decide what's tabbable and what's not? I also raise this concern because the component in #2424 would be less "generic", it will be aware of blocks and state... Maybe we could resolve this by providing a prop
Me neither :) I don't know what happened
I'm fine either way :) we could also just extract the behavior in this PR |
What if we use HOCs and force everything "tabbable" in the editor to be wrapped? FlowedTextarea, FlowedInput, FlowedEditableList etc. (I'm also bad with naming.) Then we know exactly what we have. If the block doesn't have anything, we use the wrapper of the block. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Firefox, when moving to previous or next editable by arrow key, the focused block changes, but the editable is not focused, so I lose the text caret.
followingEditor.selection.select( followingEditor.getBody(), true ); | ||
followingEditor.selection.collapse( false ); | ||
} else { | ||
followingEditor.selection.setCursorLocation(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this do? Can we comment as such?
followingEditor.focus(); | ||
|
||
if ( reverse ) { | ||
followingEditor.selection.select( followingEditor.getBody(), true ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the reason we get TinyMCE instance primarily to have access to its APIs for selecting the end of the next block? Native APIs aren't quite as nice, but not absurd:
const range = document.createRange();
range.selectNodeContents( followingEditor );
range.collapse( false );
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange( range );
I think I might be more okay with this when we pull out and isolate these behaviors, as in #2424.
const left = keyCode === LEFT; | ||
const right = keyCode === RIGHT; | ||
|
||
if ( up || down || left || right ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pyramid of if
could be improved if we delegated this to some helper methods that had early returns (as previously with handleArrowKey
). See below comment too where we have early return that will inadvertently skip other onKeyDown
logic.
const followingBlock = reverse ? previousBlock : nextBlock; | ||
|
||
if ( ! isEdge( { editor, reverse } ) ) { | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A return
here makes me wary since we don't isolate this logic from other onKeyDown
handlers. Currently the only remaining logic which would be skipped is the ENTER
handling, that would never coincide with this, but seems easy to overlook in future maintenance.
An alternative PR was merged. |
Same as #2296, but without repositioning vertically.
Fixes various browser issues with arrow key navigation. #2124
Fixes link boundaries. #2104