[Feature] Keyboard focus remains in text field while changing selection
Use case
Please tell us the problem you are running into that led to you wanting a new feature.
Is your feature request related to a problem? Please give a clear and concise description of what the problem is.
My primary use case is on Mac where traversing a form using the keyboard is important, and the focus traversal strategy implemented currently does not follow established convention and makes it hard to move keyboard focus to the next input in a form.
Specifically, it's very unusual in common autocomplete implementations for keyboard focus to traverse the list of selections when the user presses up or down. This prevents the user from continuing to type unless they return focus to the input themselves. Even worse, when the suggestions menu is open, pressing tab will currently move focus to the first element in the list instead of to the next input in the form.
Describe the alternative solutions you've considered. Can this feature be added from the outside, without needing to change the package itself?
This behavior is baked into the _SuggestionsBoxTraversalConnectorState which calls node.focusInDirection(TraversalDirection.up) (and down). It's impossible to work around this from outside.
Proposal
Briefly but precisely describe what you would like the flutter_typeahead package to be able to do.
I'd like flutter_typeahead to maintain selection state, modify it using keyboard shortcuts/actions and use pass the selection state to the widget responsible for rendering the list items (which is the approach taken by Flutter's built-in Autocomplete widget, incidentally). And retain keyboard focus in the text input at all times.
Hi,
Thank you for your issue. The current approach is unfortunately rather janky, as we need to two-way sync state and focus and it becomes very tedious to enforce this without ending up in endless loops.
Looking at Autocomplete, it doesnt seem like it keeps track of a selected entry in any way, rather, it calls onSelected exactly when the user interacts with one of the the items. This is equivalent to TypeAheadField.onSelected.
"Selection" is therefore not related to the item which is currently focused. Focus is only meant to allow users to navigate selecting items via keyboard. I believe it is better if the package stays agnostic to how the onSelected callback is used and the user keeps track of what item was last selected themselves, if necessary. There are many use-cases where this would not be required.
The Autocomplete widget also allows users to navigate the list of suggestions via up and down keyboard keys.
It does however not intercept Tab, allowing users to move to the next field.
I could imagine adding an option to disable _SuggestionsBoxTraversalConnectorState's behaviour, therefore making selection via up and down keys no longer possible.
I could also imagine looking closer into how autocomplete achieves their way of up and down arrow key selection while not intercepting tab and trying to recreate this here.
What would be your preferred outcome?
Hi @clragon,
Sorry, I think I've used the wrong terminology - I'm not actually talking about selection, rather highlighting the option which will become selected when the user presses enter.
The list of options displayed in the popover has a currently-highlighted option which is implemented using keyboard focus. flutter_typeahead moves the highlight up or down the list when the user presses the arrow keys by calling node.focusInDirection().
My feature request, and my preferred outcome, is: retain keyboard focus in the textarea at all times and maintain the currently-highlighted item using internal state, e.g. an index.
I could also imagine looking closer into how autocomplete achieves their way of up and down arrow key selection while not intercepting tab and trying to recreate this here.
It's implemented using Shortcuts. See the relevant code here: https://github.com/flutter/flutter/blob/3.19.5/packages/flutter/lib/src/widgets/autocomplete.dart#L577-L580
Thank you for this information. I was not aware that Autocomplete manually implements this, very interesting. I can imagine that we could follow suit on this and remove the complex focus code I have written - since it is unsightly. I will look into this.
The current way that focus is implemented in the TypeAhead package as of its latest version does indeed seem to cause a lot of trouble. I think we will swap over to the same technique that Autocomplete is using to rectify all this and in the process simplify a lot of the code. Hopefully I'll find time for that soon.
This change might also come with some more freedom so we can fix some other complaints as well. We might make it easier to customize even more of the field.
Thank you for your extensive amount of patience.
I have now implemented this feature on the master branch. Highlighted suggestions are now entirely driven by the SuggestionsController and now longer related to what is focused.
There is probably still some more work needed there, and more of the focus controlling code that I have previously written can be removed now that this new mechanic is in place.
If you would like to, please try out these changes and let me know if they serve your needs.
For myself, heres a quick note:
- [ ] Write migration guide to version 6
- [x] Check if the "enter" shortcut needs to be disabled when no suggestion is selected
- [x] Check if focus control can be removed from suggestions box entirely
@clragon any update when the version 6 is released, or need any help before releasing it?
Preferrably I would like to implement #577 before releasing version 6, as it might also contain breaking changes.
This will probably take some time.
@clragon could you also look into #555 before you release? Thanks!
Hi @shatanikmahanty
The reason we are holding back the release to address #579 first, is because it contains potentially breaking changes to the API surface.
While #555 is an unfortunate bug, it is just a bug and fixing it will most likely be a patch version at a later date, as it does not require any changes on behalf of the package users.
Version 6 will therefore not address #555 or any other currently open bugs, if not already explicitly stated.
Thanks!
Hi @shatanikmahanty
The reason we are holding back the release to address #579 first, is because it contains potentially breaking changes to the API surface.
While #555 is an unfortunate bug, it is just a bug and fixing it will most likely be a patch version at a later date, as it does not require any changes on behalf of the package users.
Version 6 will therefore not address #555 or any other currently open bugs, if not already explicitly stated.
Thanks!
Thanks for explaining @clragon, wish you all the best for the updates ❤️
Currently this behavior generate an accessibility issue too, because break rule about keyboard. If no one couldn't solve this, I will change my component to use Flutter AutoComplete widget :(
Hello @clragon, just wanted to check how you're doing with 6.0? Is there anything we could do to help? The issue with switching focus between fields is quite a bummer. I'm considering just using the master branch instead of the official package for now, but maybe it could be released as 6.0 beta without the other ticket?