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(Modal|Popup|Portal): fix usage of eventStack sub/unsub #2099

Merged
merged 4 commits into from
Sep 23, 2017

Conversation

austinfox
Copy link
Contributor

@austinfox austinfox commented Sep 21, 2017

fixes #2075

Without this change, any event handlers added to EventStack under the 'Portal' namespace will be appended to an array. If another Portal is then mounted, new event handlers will be added to the EventStack and take precedence over the original portal's event handlers.

This change allows each portal to store its event handlers under its own namespace in EventStack, so when you click from one portal to another, the first one is appropriately closed.

@codecov-io
Copy link

codecov-io commented Sep 21, 2017

Codecov Report

Merging #2099 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2099      +/-   ##
==========================================
+ Coverage   99.76%   99.76%   +<.01%     
==========================================
  Files         149      149              
  Lines        2598     2599       +1     
==========================================
+ Hits         2592     2593       +1     
  Misses          6        6
Impacted Files Coverage Δ
src/addons/Portal/Portal.js 100% <100%> (ø) ⬆️
src/modules/Modal/Modal.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e2fc8f5...f217ef9. Read the comment docs.

Copy link
Member

@layershifter layershifter left a comment

Choose a reason for hiding this comment

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

@austinfox thanks for picking up this 👍

Proposed changes useless, because in fact it's equals to default pool of the eventStack. My initial proposal about the exclusive prop is also not ideal.

Problem

We have a couple of bugs with multiple Modals, eventStack solves them and improves performance.

What eventStack actually does? It has an entity called pool. Event handlers that included in default pool will be fired usual. But, only the last added event handler to the named pool will be fired when corresponding event will be occured.

You can open this Modal example. Open both modals and then press Esc key. Only top modal will be closed and it's correct. But, as we can see it causes problems for Popups.

Solution

So, my idea is to add the eventPool prop to the Portal which defaults to default:

const { eventPool } = this.props

eventStack.sub('keydown', this.handleEscape, eventPool)

This prop should be also added to Modal and Popup, where it will be defaults to Modal and default accordingly. It will keep Modal working correctly and solve the problem with event propagation in Popup.

Let me know what you think.

@layershifter layershifter changed the title Fix for Portal usage of EventStack sub/unsub fix(Modal|Popup|Portal): if usage of eventStack sub/unsub Sep 22, 2017
@layershifter layershifter changed the title fix(Modal|Popup|Portal): if usage of eventStack sub/unsub fix(Modal|Popup|Portal): fix usage of eventStack sub/unsub Sep 22, 2017
@austinfox
Copy link
Contributor Author

@layershifter Yea I was thinking about adding a prop to Modal, Popup, and Portal. I'm not convinced it will be clear to others how to prevent this bug though even if we add eventPool as a prop. If they have an in-depth knowledge about the inner workings of Portal and eventStack, then yes they will be able to fix the problem. But by default, clicking on a popup and then clicking on another popup will be broken. Why not default to having each Popup use its own eventPool? I think that is standard behavior, whenever you click away from a popup is should almost always close.

@austinfox
Copy link
Contributor Author

@layershifter ignore my last comment. Taking a look at the EventStack code, I now understand what you mean. When the 'default' poolName is used, all handlers are called for that event. This will work just fine, I'll modify the PR in a few hours. Is there any way we can get this change into a new version of SUI react asap? My team site is currently breaking for IE users because we cannot use this feature. I had to rely on='focus' and do some other hacks that work well for chrome, Firefox, safari, and edge, but... sigh, IE...

Copy link
Member

@layershifter layershifter left a comment

Choose a reason for hiding this comment

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

Looks good to me. I left some comments about styling.

@@ -115,6 +115,9 @@ class Portal extends Component {
/** Controls whether or not the portal should open when mousing over the trigger. */
openOnTriggerMouseEnter: PropTypes.bool,

/** Event pool namespace that is used to handle component events */
eventPool: PropTypes.string,
Copy link
Member

Choose a reason for hiding this comment

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

Please add prop in alphabetical order.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

didn't know about this, done :)

@@ -126,6 +129,7 @@ class Portal extends Component {
closeOnDocumentClick: true,
closeOnEscape: true,
openOnTriggerClick: true,
eventPool: 'default',
Copy link
Member

Choose a reason for hiding this comment

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

^

@@ -374,6 +378,7 @@ class Portal extends Component {
const {
mountNode = isBrowser ? document.body : null,
prepend,
eventPool,
Copy link
Member

Choose a reason for hiding this comment

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

^

@@ -394,6 +399,8 @@ class Portal extends Component {

debug('unmountPortal()')

const { eventPool } = this.props
Copy link
Member

Choose a reason for hiding this comment

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

New line before this declaration is useless.

@layershifter
Copy link
Member

When the 'default' poolName is used, all handlers are called for that event.

Exactly 👍

Is there any way we can get this change into a new version of SUI react asap?

I will perform style changes tomorrow, if you will not do them before me 😄 I want to hear there @levithomason, too. I think that we can include it to next release on this weekend.

@levithomason
Copy link
Member

I've been following this issue/PR and I'm happy with this result 👍. Thanks for hashing it out guys.

@levithomason levithomason merged commit de091e6 into Semantic-Org:master Sep 23, 2017
@levithomason
Copy link
Member

Released in semantic-ui-react@0.74.0

@austinfox austinfox deleted the portal-eventstack-bug branch September 25, 2017 20:27
@drewsbrew
Copy link

Looking at the multiple modals example in the docs for v0.76, a single press of the Escape key closes both modals. I am seeing the same behavior in my project even with unique eventPool props values. Has this regressed or am I missing something?

@brianespinosa
Copy link
Member

@drewsbrew If that is what you are experiencing, please open up a separate bug report form with a codesandbox example.

@layershifter
Copy link
Member

@drewsbrew Bug actually exists, however @brianespinosa please create new issues instead of necroposting.

Will be fixed in #2329.

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

Successfully merging this pull request may close these issues.

eventStack: Multiple Popups do not behave correctly
6 participants