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
Feature: Implement cursor navigation with navigation keys #404
Conversation
@@ -0,0 +1,58 @@ | |||
import {fireEvent} from '@testing-library/dom' |
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 are your opinions on using this kind of code organization? I noticed there is 3 files for typing:
- utils
- type
- type-modifiers
I think navigation keys will end up adding a chunk (but not massive) amount of code. I opted for a new file but I am willing to move things around.
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.
I probably wouldn't have bothered making the new file myself, but I'm ok with it.
src/__tests__/type.js
Outdated
"Bre{CURSOR}" -> "Brea{CURSOR}" | ||
input[value="Brea"] - keyup: a (97) | ||
input[value="Brea"] - keydown: ArrowLeft (37) | ||
input[value="Brea"] - select |
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.
I am thinking a select event should show the before and after of the cursor position:
input[value="Brea"] - keydown: ArrowLeft (37)
input[value="Brea"] - select
"Brea{CURSOR}" -> "Bre{CURSOR}a"
input[value="Brea"] - keyup: ArrowLeft (37)
What do y'all think?
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.
For posterity's sake: there was an earlier comment and it got 1 response.
I'm not sure. Based on the playground we shouldn't fire a select event at all I think (though it may be unfortunately unavoidable).
I made a new comment thread to leave the unexpected {CURSOR}
position bits out of this.
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.
I agree
Any update here? We could really use the ability to use type the arrow key for a couple reasons.
|
Agree with CWSites. This would greatly simplify testing things like: MaterialUI TextField[type="time"]. |
I'm sure @juanca would be more than happy to have either of you pick up where they left off and address the merge conflicts and other issues in this PR :) |
Hi! This is something I recently came across with, and I'd be happy to help if it needs picking up 😃 |
Go for it 👍 |
@jesujcastillom Thanks for the offer! I would greatly appreciate the help. I've been nerd-sniped into other projects for my free time. Let me know if anyone needs any context, happy to provide it whenever. |
aab8cfa
to
e254f1c
Compare
src/__tests__/type.js
Outdated
expect(() => { | ||
navigationKey('SOME_INVALID_KEY') | ||
}).toThrowError(TypeError) | ||
}) |
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.
I've modified the function to hit all the lines (default
wasn't reachable) now the question is, should I include this test to make sure we throw a TypeError
(and also throw it in the function)` if we don't get a valid key, or leave it without throwing, since it's an internal function anyway.
In summary, removing the last commit entirely, we still get 💯 coverage, but it's not really covered if an invalid key is passed, any thoughts? @juanca @kentcdodds
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.
Note, modified the commit because I didn't have my git config setup properly in this machine, but yeah, same changes 😅
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 this even possible? We're the only ones who call navigationKey
and we always call it properly. I'd just remove that logic.
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.
No, it isn't I'll remove it :)
Codecov Report
@@ Coverage Diff @@
## master #404 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 12 13 +1
Lines 482 494 +12
Branches 134 136 +2
=========================================
+ Hits 482 494 +12
Continue to review full report at Codecov.
|
3c0fccc
to
45445c3
Compare
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.
Thanks for picking this up! Here's some feedback for you.
src/type.js
Outdated
@@ -44,6 +45,8 @@ const modifierCallbackMap = { | |||
} | |||
|
|||
const specialCharCallbackMap = { | |||
'{arrowleft}': navigationKey('ArrowLeft'), | |||
'{arrowright}': navigationKey( 'ArrowRight'), |
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.
'{arrowright}': navigationKey( 'ArrowRight'), | |
'{arrowright}': navigationKey('ArrowRight'), |
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.
Done!
expect(getEventSnapshot()).toMatchInlineSnapshot(` | ||
Events fired on: input[value="Brekafast"] | ||
|
||
input[value=""] - pointerover |
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.
I just tried this in the playground and here's what I got for the events (Note, I ignored mouse/pointer move events because they're too noisy in the playground):
textarea#textarea[value=""] - pointerdown
textarea#textarea[value=""] - mousedown
textarea#textarea[value=""] - focusin
textarea#textarea[value=""] - pointerup
textarea#textarea[value=""] - mouseup
textarea#textarea[value=""] - click
textarea#textarea[value=""] - keydown
textarea#textarea[value=""] - keypress
textarea#textarea[value="b"] - input
textarea#textarea[value="b"] - keyup
textarea#textarea[value="b"] - keydown
textarea#textarea[value="b"] - keypress
textarea#textarea[value="br"] - input
textarea#textarea[value="br"] - keyup
textarea#textarea[value="br"] - keydown
textarea#textarea[value="br"] - keypress
textarea#textarea[value="bre"] - input
textarea#textarea[value="bre"] - keyup
textarea#textarea[value="bre"] - keydown
textarea#textarea[value="bre"] - keypress
textarea#textarea[value="brea"] - input
textarea#textarea[value="brea"] - keyup
textarea#textarea[value="brea"] - keydown // <- here's the arrow down to go left
textarea#textarea[value="brea"] - keyup
textarea#textarea[value="brea"] - keydown
textarea#textarea[value="brea"] - keypress
textarea#textarea[value="breka"] - input
textarea#textarea[value="breka"] - keyup
textarea#textarea[value="breka"] - keydown // <- here's the arrow down to go right
textarea#textarea[value="breka"] - keyup
textarea#textarea[value="breka"] - keydown
textarea#textarea[value="breka"] - keypress
textarea#textarea[value="brekaf"] - input
textarea#textarea[value="brekaf"] - keyup
textarea#textarea[value="brekaf"] - keydown
textarea#textarea[value="brekaf"] - keypress
textarea#textarea[value="brekafa"] - input
textarea#textarea[value="brekafa"] - keyup
textarea#textarea[value="brekafa"] - keydown
textarea#textarea[value="brekafa"] - keypress
textarea#textarea[value="brekafas"] - input
textarea#textarea[value="brekafas"] - keyup
textarea#textarea[value="brekafas"] - keydown
textarea#textarea[value="brekafas"] - keypress
textarea#textarea[value="brekafast"] - input
textarea#textarea[value="brekafast"] - keyup
Notice that there's no "select" event in there. I'm not sure whether it's possible to avoid that event, but it would be good to avoid if we can.
Also, I think this test could be simplified if we change the input to: b{arrowleft}a{arrowright}c
(which would result in abc
, and much fewer events for the snapshot).
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.
At least from what I could investigate, the [setSelectionRange](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setselectionrange] will fire a select
event, and I can't really seem to find another way to move the cursor.
src/__tests__/type.js
Outdated
expect(() => { | ||
navigationKey('SOME_INVALID_KEY') | ||
}).toThrowError(TypeError) | ||
}) |
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 this even possible? We're the only ones who call navigationKey
and we always call it properly. I'd just remove that logic.
45445c3
to
522a362
Compare
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.
Looks good to me, but I don't think I can merge this until @juanca removes the draft status of this pr.
@all-contributors please add @juanca for code and tests @all-contributors please add @jesujcastillom for code and tests |
I could not determine your intention. Basic usage: @all-contributors please add @Someone for code, doc and infra For other usages see the documentation |
@all-contributors please add @juanca for code and tests |
I've put up a pull request to add @juanca! 🎉 |
@all-contributors please add @jesujcastillom for code and tests |
I've put up a pull request to add @jesujcastillom! 🎉 |
🎉 This PR is included in version 12.2.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
Forgive my ignorance, but why only implement arrowright and arrowleft? Why not include up and down? My original interest in this issue was checking number inputs and the value associated when changing step by step. |
Up and down would be extremely difficult 😬 |
@kentcdodds What makes up and down harder than left and right? |
It comes down to where the cursor goes. In a textarea it depends on the size of the textarea as well as the font size. This would take a ridiculous amount of work (would probably require an environment that supports layout, so jsdom is out). Just too much work in afraid. |
Note: WIP! I am running into a few problems and would like advice.
What:
Implements navigation keys support in
type
method:Why:
It is reasonable for a user to use keyboard navigation while interacting with an interactive element. An interactive element could be an input (where a user would type into) or an accessible UI with keyboard support (no typing but it handles key events).
How:
Brek{arrowleft}a{arrowright}fast
->Breakfast
Breakfast{shift}{arrowleft}{/shift}
->Breakfas{selection}t{/selection}
Checklist:
Closes: #354