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

Fix collapse with focused input #33695

Closed
wants to merge 2 commits into from

Conversation

alpadev
Copy link
Contributor

@alpadev alpadev commented Apr 20, 2021

Closes #33682

Background

Our inputs are using transitions for the focus effect. If a nested input got focus right before clicking the collapse button, the input triggers a transitionend event that causes the transition of the collapse module to end prematurely.

@alpadev alpadev requested a review from a team as a code owner April 20, 2021 01:33
// if event is dispatched by a nested element reschedule the event handler
if (event.target !== this._element) {
EventHandler.one(this._element, 'transitionend', complete)
emulateTransitionEnd(this._element, transitionDuration)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I can tell, it should work without emulateTransitionEnd but the test did fail in that case. Either we leave this here or dispatch the event manually in the spec. Not sure what is preferred.

Copy link
Member

Choose a reason for hiding this comment

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

If it's only for our tests, we should handle that there. But only if we are 100% sure it affects the tests only :)

Copy link
Contributor Author

@alpadev alpadev Apr 27, 2021

Choose a reason for hiding this comment

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

@XhmikosR appreciate your response. That made me think a little more about this. 👍

So here is the thing. If I understand the purpose of emulateTransitionEnd() correctly, it's some kind of fallback for browsers that don't support transitionend events natively. Since it uses the triggerTransitionEnd() function, which dispatches a custom transitionend event that doesn't bubble, it shouldn't be possible to reach that if-block in those browsers.

IMO event.target !== this._element can only be true if the event is coming from a nested element. In that case calling emulateTransitionEnd() is kind of irrelevant, because if it's a bubbling event it's likely because there is native support.

But there is more to emulateTransitionEnd(). It will queue triggerTransitionEnd(), which is only called after the transition-duration and in case no other transitionend event happened during that duration. Although it doesn't care if the transitionend event came from a nested element. (Maybe it makes sense to change it there too, but this could introduce problems all over the place. 🤔)

To summarize the behavior:

In a browser that supports transitionend natively, there will be two events dispatched by the browser. One from the input (that bubbles) and another from the collapse. The event from the input will be handled by the if-condition and the event from the collapse will run complete like it used to. emulateTransitionEnd() (within the if-block) shouldn't do anything here because it's cancelled by the collapse's event so it wouldn't be necessary to put it there IMO.

In a browser that doesn't support transitionend, there will be no event for the input but only for the collapse dispatched by emulateTransitionEnd(). So the if-condition is never met and complete will just go through.

In our unit tests, we don't rely on the transitions in our CSS but only on those triggered by JS. In this specific case, in the spec, I'm manually dispatching the event (that bubbles like the native ones) on the input. This prevents emulateTransitionEnd() from dispatching a custom transitionend (on the collapse element), so complete would be called only once by the event from the input. This event branches through the if-condition and only because I'm calling emulateTransitionEnd() within the if-block it's queuing another (custom) transitionend event that will call complete a second time. This could be replaced with a manual dispatched event in the spec.

So..

  • Either I will leave it like it is..
  • Or remove emulateTransitionEnd() from the if block and dispatch the event manually in the spec..
  • Or change emulateTransitionEnd() to ignore events from nested elements which prevents it from dispatching the custom transitionend. This means I wouldn't have to call emulateTransitionEnd() within the if-block nor manually dispatch an event in the spec.

Your call😊

P.S. I hope it makes sense what I wrote here

@alpadev
Copy link
Contributor Author

alpadev commented May 6, 2021

Closing this in favor of #33845

@alpadev alpadev closed this May 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Collapse with a nested input that is focused while closing, causes transition issues.
2 participants