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

Allows for the modal to be appended to another element rather than the document body. #183

Merged
merged 12 commits into from
Dec 6, 2016

Conversation

jshthornton
Copy link
Contributor

@jshthornton jshthornton commented Jun 2, 2016

Use the property parentSelector to either be a string (for query selecting), a function (so that a parent component can supply its node once it has been rendered), or a dom element.

The modal will detect if the parent element has changed and move it accordingly.

The only thing I am skeptical of is if React will remove the node from the parent element's children if other children are rendered (but it hasn't so far in testing).

@claydiffrient
Copy link
Contributor

@jshthornton What's the use case for not appending to the body? I'd like some information about the problem before talking about the solution. In my mind, the body is an element always present when the modal is triggered to open. Also, the place the modal portal ends up being attached isn't all that important as it's just there to make sure that the modal exists outside of the content that gets hidden.

@diasbruno
Copy link
Collaborator

@claydiffrient maybe in a very specific container.

...splitting the view in two parts, the top one has a modal opened, the bottom div is free to perform any actions (?).

@jshthornton this case make sense?

@dannybloe
Copy link

I am very pro this enhancement. I was just looking if this is possible somehow and was about to just implement my own modal panel component until I saw this pull request.
Please merge 👍

We have a web app that allows you to open a help side-panel. However, as soon as you have a modal panel open, and this modal panel has a help button, then the side-panel is behind the overlay. So we want the overlay to be a child of a specific div and not the body.

@rgdelato
Copy link

rgdelato commented Aug 9, 2016

I also have a use case for this and would greatly appreciate having an official, non-hacky way to append the modal to an element other than document.body.

Our use case is that we'd like to re-style the modal content as body content on mobile devices, and so the modal needs to live as a sibling to the main content container.

@diasbruno
Copy link
Collaborator

I tested the branch, it's working and didn't break the tests. some observations...

1 - the ariaAppHider is not updated to use the parentSelector. maybe add a test for this?

2 - the overlay has fixed position and it'll have the same behavior if we change where the modal element should be appended, so you'll need to pass the new overlay style...should the modal update the position to absolute when parentSelector is defined?

3 - still needs testing when more than one modal is in the page.

@@ -10,6 +10,18 @@ var Assign = require('lodash.assign');
var SafeHTMLElement = ExecutionEnvironment.canUseDOM ? window.HTMLElement : {};
var AppElement = ExecutionEnvironment.canUseDOM ? document.body : {appendChild: function() {}};

function getParentElement(parentSelector) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm personally not so much of a fan of handling all these options here. Lately I've felt like maybe just going the function route is the best. That way the prop in all cases is just a function that returns a DOM node. Mixed examples don't have to be created and you don't have any issues with querySelector not returning what you expect it to, etc. Push the selecting of an element all out to userland rather than dealing with it in internal to the library.

@msuperina
Copy link

I don't understand why there is even the question about why one would want to append the modal somewhere else from the body. As a maintainer of my UI I want to organize my DOM in a way that suits me, I don't want to be constrained about the behaviour of a library. This body appending is a valid reason that prevents me to use this module that I would otherwise consider very helpful.

@@ -10,6 +10,18 @@ var Assign = require('lodash.assign');
var SafeHTMLElement = ExecutionEnvironment.canUseDOM ? window.HTMLElement : {};
var AppElement = ExecutionEnvironment.canUseDOM ? document.body : {appendChild: function() {}};

Choose a reason for hiding this comment

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

Why not going to the bottom of it and also modifying the way AppElement is resolved ? It would be great if document.body was never touched if a user wished so.

@jshthornton
Copy link
Contributor Author

Sorry this has taken me so long to get around to commenting on.
So the reason why I specifically needed this was because I had a drag and drop component in my app which allows for any element below it to be dragged into. In my case it was very high up in the component tree to allow for the entire window to be draggable. However, when I threw this module in it rendered itself outside of the tree and was not partial to the dragging.

@claydiffrient
Copy link
Contributor

@jshthornton I'm willing to merge this in once the conflicts are resolved and the comments that have been left have been addressed. As @diasbruno mentioned, this won't actually change anything about how the overlay works since it is fixed position. Everything will behave identically at this point whether you give it document.body or some_random_div other than the ModalPortal element itself will be in another location in the DOM which seems like it isn't really what you want.

@jshthornton
Copy link
Contributor Author

I should be able to find some time during this week to get all of the
conflicts sorted and documented.
Anyone else in this thread have any opinions / proposals for changes of
implementation before I do?

On Tue, 23 Aug 2016 at 13:45 Clay Diffrient notifications@github.com
wrote:

@jshthornton https://github.com/jshthornton I'm willing to merge this
in once the conflicts are resolved and the comments that have been left
have been addressed. As @diasbruno https://github.com/diasbruno
mentioned, this won't actually change anything about how the overlay works
since it is fixed position. Everything will behave identically at this
point whether you give it document.body or some_random_div other than the
ModalPortal element itself will be in another location in the DOM which
seems like it isn't really what you want.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#183 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACrzGjEQwCWy82BijCjMxZup6yQEE_G7ks5qiut6gaJpZM4IsPNL
.

@claydiffrient
Copy link
Contributor

@jshthornton I can't think of any other things about this. Will you have time to get to it soon? I've got a few commits that are on master now that I'd like to get cut into a release. I'm thinking a 2.0.0 release is forthcoming. I think I'd like to get this all squared away before doing that though.

cc/ @diasbruno

vsaarinen added a commit to lucified/minard-ui that referenced this pull request Sep 15, 2016
NOTE: react-modal removed the ability to select where the modal div is inserted into in version 1.3.0. This is because aria-hidden (i.e. "ignore this" for screenreaders) is added to the rest of the app, but now that the modal is also included in the app, it gets hidden from screenreaders as well. There's currently a PR open (reactjs/react-modal#183) that tries to address this, so we might see the return of this feature at some point. We should upgrade then.
@thien-do
Copy link

Hi guys, I'm really interesting in this. It seems @jshthornton is busy, while I have some free time, so I hope I can help. I created a PR (jshthornton#1) to @jshthornton's one, so he can simply merge it when I finish. My PR:

  • Merge from upstream and resolve conflicts. (AFAIK, only one: e5b0181)
  • Allow parent selector to be function only, as suggested by @claydiffrient . However, I don't know should we check and/or throw error here
  • I'm very sorry but I don't understand @msuperina comment so I can't do anything with that. Can someone explain it to me, then I can work on that
  • I'll also add documentation to this PR soon

Merge with upstream master
@thien-do
Copy link

@jshthornton @claydiffrient I have added the documentation for using custom node for the modal, please take a look (because I'm afraid that I'm not good at writing docs)

One last thing, should I apply @msuperina comment? If yes, can anyone explain to me.. because I don't understand his comment

@thien-do
Copy link

thien-do commented Oct 5, 2016

Hi @claydiffrient , do you have sometime to review this PR please?

@thien-do
Copy link

Hi @claydiffrient , do you intent to merge this PR? If so, I will resolve the conflict issues again.

@claydiffrient
Copy link
Contributor

@dvkndn Yes. I do intend to merge it, but I've had very limited time to spend working on this lately :(. I will try and review it this weekend. If you want to solve the conflicts before then that would be great.

# Conflicts:
#	lib/components/Modal.js
@thien-do
Copy link

Thank you @claydiffrient . I have created a PR into @jshthornton PR jshthornton#3

After @jshthornton merge my PR, you can merge his

@thien-do
Copy link

@claydiffrient please take a look when you're free. @jshthornton have merged my PR, so this PR is no longer has conflict

Copy link
Contributor

@claydiffrient claydiffrient left a comment

Choose a reason for hiding this comment

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

Unfortunately when I ran npm test in the repo almost all the tests fail. I wish that I had access to enough of the repo to make Travis run that for you.

The problem as far as I can tell deals with the fact that currently the default parentSelector is document.body whereas it really expects it to be a function so it's failing with parentSelctor is not a function

@@ -37,6 +41,11 @@ var Modal = React.createClass({
closeTimeoutMS: React.PropTypes.number,
ariaHideApp: React.PropTypes.bool,
shouldCloseOnOverlayClick: React.PropTypes.bool,
parentSelector: React.PropTypes.oneOfType([
Copy link
Contributor

Choose a reason for hiding this comment

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

This should only be React.PropTypes.func now correct?

@@ -47,24 +56,36 @@ var Modal = React.createClass({
portalClassName: 'ReactModalPortal',
ariaHideApp: true,
closeTimeoutMS: 0,
shouldCloseOnOverlayClick: true
shouldCloseOnOverlayClick: true,
parentSelector: document.body
Copy link
Contributor

Choose a reason for hiding this comment

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

I think maybe specifying a function here would be best something like () => document.body would probably do.

@thien-do
Copy link

Oh I'm sorry about that. I just merged the PR with upstream. Now I will check the issue

kozborn added a commit to evidenceprime/react-modal that referenced this pull request Nov 7, 2016
@blainekasten
Copy link

Another use-case for this is that it fails when a different element goes into fullscreen. For example, we use this lib to provide a modal over a video. But if you go into fullscreen on the video (which does not target document.body for specific reasons), the modal is now longer visible ever.

Would love to see this get merged.

@thien-do
Copy link

thien-do commented Nov 7, 2016

@claydiffrient I have fixed the issue, now the tests are passed, thank you for pointing out :D
it seems @jshthornton also merged it so you can review now

@thien-do
Copy link

thien-do commented Dec 6, 2016

Hi @claydiffrient is there any update?

@claydiffrient
Copy link
Contributor

@dvkndn I'm sorry. Life has been super busy and I haven't had a moment to look at this. I'll re-review it quickly and see about getting it merged.

@claydiffrient claydiffrient merged commit de14816 into reactjs:master Dec 6, 2016
@claydiffrient
Copy link
Contributor

Released in 1.6.0

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

Successfully merging this pull request may close these issues.

8 participants