Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Allow arrow keys navigation in autocomplete list #2966

Merged
merged 7 commits into from
Jun 13, 2019

Conversation

npny
Copy link
Contributor

@npny npny commented May 14, 2019

(Referencing element-hq/element-web#4737)

This allows left/right arrow keys to navigate backwards/forwards in the autocomplete list (on top of the up/down arrow keys which already did that).

The first commit is the minimal code change for that, while the rest are follow-up cleanup/refactor (now that names like onVerticalArrow, onUpArrow and onDownArrow make less sense).

Misc notes
  • this.direction = '' needs to be at the top before the bunch of autocomplete.moveSelection, as the latter calls setState, which triggers onChange, which looks at this.direction, somewhere in the middle. It would be at the last keyDown event's value if it wasn't reset here first, which is incorrect.
  • It arguably also should not be set by the current keyDown event, as this isn't supposed to be textual navigation, but instead is supposed to be "swallowed up" by the autocomplete list. This is why the rest of the // skip void nodes block is after the autocomplete.moveSelections, so that it only happens if the latter didn't match and didn't return true first.
  • The switch condition can be collapsed further (see below), by relying on fall-through behaviour, but that was deemed unnecessarily confusing for future readers so I kept it as is.
switch (ev.keyCode) {
    case KeyCode.LEFT:
        this.autocomplete.moveSelection(-1);
    case KeyCode.RIGHT:
        this.autocomplete.moveSelection(+1);
    case KeyCode.UP:
        this.autocomplete.moveSelection(-1);
    case KeyCode.DOWN:
        this.autocomplete.moveSelection(+1);
        
    ev.preventDefault();
    return true;
}
  • I took the liberty of removing the this.moveAutocompleteSelection -> this.autocomplete.onUpArrow indirection step as it didn't really add anything.

Signed-off-by: Pierre Boyer <pierre.s.boyer@gmail.com>

@jryans jryans requested a review from a team May 14, 2019 10:45
@bwindels bwindels requested review from bwindels and removed request for a team May 16, 2019 18:27
@bwindels
Copy link
Contributor

bwindels commented May 16, 2019

Hi, thank you for your PR!

We've recently introduced a new composer for editing messages (currently under a labs flag, in src/components/views/elements/MessageEditor.js). The new editor shares the Autocomplete component with the MessageComposerInput. I'm still changing bits in the auto complete support there, so would rather wait until that stabilizes to see how these changes can be merged in.

Will report back here when that's done. Thanks for your patience.

@bwindels bwindels self-assigned this May 16, 2019
Copy link
Contributor

@bwindels bwindels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from needing a few further changes, looking good already!

// selectionOffset 0 means autocomplete inactive, while 1 means 0th item selected, hence the -1/+1
let index = this.state.selectionOffset - 1;
index = (index + delta + completionCount) % completionCount;
this.setSelection(index + 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this prevent from ever going back selectionOffset=0 again? E.g. you'll just be able to cycle through pills without having the step with just the text you typed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, good catch, I see the point behind the %(completionCount+1) now!

I've updated the above to:

// Note: selectionOffset 0 represents the unsubstituted text, while 1 means first pill selected
const index = (this.state.selectionOffset + delta + completionCount + 1) % (completionCount + 1);
this.setSelection(index);

src/components/views/rooms/Autocomplete.js Show resolved Hide resolved
@npny npny force-pushed the npny/autocomplete-arrow-keys branch from a33afa1 to ed64275 Compare June 4, 2019 11:26
Copy link
Contributor

@bwindels bwindels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes! Apart from left/right arrow comments, looks good! Still need to test it locally as well, but almost there :)

this._getAutocompleterComponent().moveSelection(+1);
}

onLeftArrow() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to add left/right arrow keys for the new composer yet, I need to test if it doesn't interfere with caret navigation. Let's just do enough here so it isn't broken.

@@ -116,6 +116,10 @@ export default class MessageEditor extends React.Component {
autoComplete.onUpArrow(event); break;
case "ArrowDown":
autoComplete.onDownArrow(event); break;
case "ArrowLeft":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to add left/right arrow keys for the new composer yet, I need to test if it doesn't interfere with caret navigation. Let's just do enough here so it isn't broken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roger that, removed.

Copy link
Contributor

@bwindels bwindels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it locally, works well! Sorry it took so long. This looks good to merge now.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants