i-like-robots/react-tags

blur programatically

Opened this issue · 8 comments

Describe the solution you'd like

Currently, the suggestions element is opened on focus and stays so until the user clicks on another element (focus is lost). I'd like to close the suggestions element once the user has picked one of the values. Unless I'm missing something, this is not possible currently.

Describe alternatives you've considered

I'm not really sure which is the best way to implement this. My two main ideas are:

a) implement a blur() method
b) implement options to allow the developer specify if the suggestions element should be opened when adding or deleting tags

Additional context

N/A

Note that I know that this can be achieved with a reference to the react-tag-autocomplete element and then doing this.reactTags.current.input.current.input.current.blur(), but this just looks awful.

Maybe a good approach would be to pass the reference of the react-tag-autocomplete element to all event handlers (the props that start with on), so they can dynamically react to any event.

With my accessibility hat on I'd recommend not calling .blur() on an an interactive element and instead move cursor focus to an appropriate new target. Otherwise keyboard users and those relying on assistive devices will have their cursor shifted back up to the window which can be very frustrating and confusing!

Sure, I see your point. But let me show you the visual problem of this:

Grabación de pantalla 2020-11-06 a las 15 28 23

The gif shows two different problems:

  1. When the user is adding new elements, the currently added elements are not visible. I made a workaround with a reverse intersection between the available elements and the selected elements, so the suggestions element is showing only "what is left" to pick up. Still, just a workaround, not an actual fix, as the selected elements are still not visible, and the user is forced to click "outside" in order to see them.

  2. This one is more frustrating. When removing elements, the suggestions element is shown, which doesn't make any sense from the UX point of view. "Why would I want to add an element if I'm removing elements?"

So, as I said, I totally see your point and I totally agree with the accessibility use case, but maybe implement "something" that would allow the developer to decide between accessibility and UI / UX.

Thanks for the clarification, the animation is very useful. I assume you have defined minQueryLength as 0, is this correct?

There have been discussions about cursor focus in the past (#207) - the question is that when destroying an interactive element the cursor focus must go somewhere, but where that should be?

The code to handle this is here and the current intention is that the closest interactive element within the component is selected:

https://github.com/i-like-robots/react-tags/blob/master/lib/ReactTags.js#L201-L219

But in your case... where do you think would be most appropriate?

I assume you have defined minQueryLength as 0, is this correct?

Yes, that is correct. I have a use case in which the user might not know the "name" of all the options, so I use minQueryLength=0 in order to trigger the suggestions when the input is focused.

I just read the entire #207 thread, and I must say that I totally agree with "keep the focus on the input" on that use case, because the selected tags are rendered "inside" the input, so the user would expect to be able to continue deleting elements with the backspace without having to focus again on the input.

My use case it a little bit different. My tags are rendered beneath the input, and removing (with the mouse, not with the backspace) them without triggering a focus makes sense.

Which leads me to the same conclusion you already got in #226 (comment) , which is: "There must be a high-level feature that can allow developers to control those cases".

I guess a good no-compromises solution would be to pass the reference of the react-tag-autocomplete instance to all the callbacks (all the onSomething methods) and let the developer decide what to do.

Re-reading the original issue (#207) I think the idea of recording where focus comes from and returning it to this location after the tag element is destroyed still seems like a good one. Unfortunately, I forgot about this idea and have not revisited the initial behaviour I implemented since. I work with a few accessibility experts so I will consult them too.

Either way, perhaps a new prop which can disable this behaviour entirely might be worthwhile. Such a change would allow the implementor to do whatever they wish with cursor focus within existing callbacks.

https://github.com/i-like-robots/react-tags/blob/master/lib/ReactTags.js#L201

As for passing references... that sounds reasonable and I think has been discussed before.

Okey, so I can go ahead and add the ref as a parameter to the callbacks?
Do you want that to be a ref parameter onSomething(ref) or an object which can contain the reference and any future parameters you'd like to add onSomething({ref})?