Skip to content
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

Can’t differentiate between focus coming outside and focus coming after the click by option #1458

Open
helgablazhkun opened this issue May 31, 2021 · 0 comments

Comments

@helgablazhkun
Copy link

One of the most straightforward use case is to automatically open the dropdown component on focus if the operation has been initiated from the outside.

Power Select Focus handling documentation says that we can check the 'event.relatedTarget' to know the element that had the focus before. Code example suggests the following:

handleFocus(select, e) {
    console.debug('EPS focused!');
    if (this.focusComesFromOutside(e)) {
      select.actions.open();
    }
  }
 
  // Methods
  focusComesFromOutside(e) {
    let blurredEl = e.relatedTarget;
    if (isBlank(blurredEl)) {
      return false;
    }
    return !blurredEl.classList.contains('ember-power-select-search-input');
  }

If the relatedTarget is not null then we can assume that focus comes from outside and trigger dropdown open event.

But the weak part comes into play when the user focuses dropdown after the non-focusable element (using Tab key)
or when dropdown is the first element in the form. In this case the relatedTarget will be null. And dropdown element won't be opened.
Also when the user picks the dropdown option from the list, the input is refocused. The relatedTarget will be `null as well.
So We can’t distinguish between the cases when the focus comes outside to the dropdown trigger when there was no focused element and when it comes after clicking the dropdown option.

Please look at the twiddle example:

  1. Press 'tab' key focus on city-picker
    Expected result: dropdown is opened. Actual result: dropdown is not opened.
  2. Press 'tab' key to focus on the next input
  3. Press 'shift+tab' key to return back to the city-picker
    Dropdown is opened now.
    Behaviour is not consistent.

I suggest the following solution:
Make dropdown option as focusable element by setting "-1" tabindex. On blur/focus events check the 'event.relatedTarget' to identify exactly that we faced with inner interaction (not the outside element)

function relatedTargetIsTimeOption(relatedTarget: EventTarget | null): boolean {
  if (!relatedTarget) {
    return false;
  }

  return (relatedTarget as HTMLElement).classList.contains('ember-power-select-option');
}

And use it in blur/focus events:

@action
 onFocus(dropdown: Select, event: FocusEvent): void {
   if (!relatedTargetIsTimeOption(event.relatedTarget)) {
     dropdown.actions.open();
   }
 }
 
 @action
 onBlur(_dropdown: Select, event: FocusEvent): void {
   if (relatedTargetIsTimeOption(event.relatedTarget)) {
     return;
   }
 // do required actions on blur
 }

What do you think?

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

No branches or pull requests

1 participant