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
Proposal: Alternative Overlay API #811
Comments
👍 Would be really awesome! |
Huge 👍 I've been wanting to propose such a change as well. There's a lot less mental overhead to understand this. |
This is cool. Two notes -
|
👍 |
That said, is there any way we could reduce the boilerplate with this implementation? One nice thing with the current I'm not sure happy about having to explicitly deal with component state whenever I want a modal or overlay - I would prefer a pattern that could take care of that for me, as much as possible. The container is not entirely ideal, but it does buy you that convenience. |
I think so, I actually think the current OverlayTrigger (in some form) is a nice compromise for tooltips and popovers where you might have a bunch of them and explicitly managing that all state is annoying. I think tho if the trigger simply wrapped up the state/handler logic instead of also managing the overlay, you get a better seperation, and the tooltips and popovers would make better primitives by themselves. One potential issue with the current Trigger api is that it takes a ReactElement instead of of a Type, so the Trigger would have to clone it (not a huge issue) to add show/hide logic |
The overlay/tooltip can't position itself without a reference to the trigger of some sort, though - per your example, it is a little awkward to get that working. My ideal tooltip API would actually look something like <TooltipTrigger tooltip="here is a tooltip">
<a href="...">whatever</a>
</TooltipTrigger> Which is not dissimilar to what we have right now, just far less verbose. |
If we are going to have a Trigger component, I like that. That feels less like we are pushing our desire to have a common underlying implementation on users like not idiomatic react...but we could also do something weird like having a convention on <Tooltip>
<button>open tooltip<button/>
"here is the tooltip"
</Tooltip> |
It would definitely be nice to see the more declarative style easier to do. All of our modals are externally controlled and right now we have to maintain or own We are also using fluxible which uses the context, so passing that context to the components within the modal is important. |
I'm biased by the existing syntax, but I think unidiomatically using I like the ergonomics of my strawman Definitely it'd be an important benefit of your proposal that it'd be possible to inject the "shown" status as an external prop from a Flux framework, though I wonder if that wouldn't be possible with the triggers as well. This is more relevant for modals than for overlays by a long shot. ETA: Corrected many poor/incorrect wordings. Sorry. |
just spitballing some more for tooltip api options...we could go the higher order component route as well render(){
let TooltipTrigger = createTooltip(<span><strong>I am</strong> a tooltip</span>)
render (
<TooltipTrigger postion='left' trigger='focus'>
<button/>show</button>
</TooltipTrigger>
)
} Over all I think any of these options can fit into my initial proposal where |
Your strawman there is potentially a lot worse from a performance PoV - you're generating a new component class every time <TooltipTrigger
position='top'
tooltip={<span><strong>I am</strong> a tooltip</span>}
>
<button>show</button>
</TooltipTrigger> |
@taion question about context, is ContextWrapper currently just there to make sure the parent based context is passed to the overlay? It is just silencing the warning right now? I have been watching the react PR's on this, there should be a proper API to handle that case in react 0.14, so that might solve some issues there as well. |
It's about silencing the warning. I'm not aware of better options under 0.13. What will 0.14 add for managing this? |
I have complained about this concern a bunch, so I know that the react team is aware of it and giving it due priority. AFAIK there is no better way in 0.13 :/... the current iteration of the new API is this: https://github.com/facebook/react/blob/master/src/addons/renderSubtreeIntoContainer.js which is just a render() that passes along the current context |
Makes sense. Guess we'll have to deprecate the context forwarding stuff then. |
Had some (pleasently) unexpected free time recently, and made some attempts at this; in https://github.com/react-bootstrap/react-bootstrap/tree/wip-overlays Feedback appreciated. there are a bunch of experiments in there around the triggers, and the current version is doing some odd things to avoid extra wrapping components. obviously still not ready for prime time, no tests, no reasonable depreciations, etc. |
I haven't had time to fully look through this in depth, but it looks like a step in the right direction. That said, I'd be extremely careful with the overlay HOC. As mentioned above, it seems like it'd be very difficult to use correctly, so we should probably note that it should not be directly used except as a module-level thing. Also, when I get a chance this weekend, I'm going to try out something slightly different for resolving the RootClose issue. |
yes! the goal with any of the HOC helpers is to be used only at the module level, just like you would a mixin. as you say, creating classes in a render is a big perf concern |
Reading through the code on the branch, I think there are a lot of good ideas, but I think I'd organize them somewhat differently.
I think the benefits of this approach are:
|
me and @taion had a good chat about the above points in gitter the other day, and I will try most of them out and see how that feels api-wise. I did think of another concern that could have an impact on the discussion. I think tooltips, popovers, and modals should be responsible for their own show/hide logic, instead of that being higher up in the componenl that renders them into a new subtree (OverlayHolder). The main reason for this is that when the unmount logic is higher up the tree, nothing farther down can interrupt or delay it, which puts us in a place where <Fade>
{ props.show && <ToolTip/> }
</Fade> Where The downside to this approach though is that it means that something like OverlayHolder, wouldn't be able to add show/hide logic to arbitrary markup, and each would need to handle it themselves, which isn't to difficult, but is an extra step, it also creates an implicit requirement that components impliment this contract to work with the Trigger component. Alternatively we move the Fade logic out of the tooltips/popovers/modals completely, and put it in the OverlayHolder, but that feels a bit odd to me... |
I think it'd make sense to put the show/hide/fade logic in something like Something like <OverlayHolder>
<MyPopover />
</OverlayHolder> and MyPopover = createOverlay(MyPopover); is not that big - the main difference is just that the former gives you a bit more flexibility of doing the HOC wrapping wherever you want (e.g. in the http://martyjs.org/guides/containers/index.html |
I think that the Fade logic belongs wherever the hide/show logic is, so |
Most recent updates adds a I left the Positioning logic out of it for now. It still feels awkward to me for that to be with Layer/Overlay/Portal logic, since it creates an implicit contract between it and its child, passing positioning data as props to it, which to my mind limits its potential uses. Modals for example don't need positioning coordinates, and especially don't need arrow offset coords :P If the current HoC for positioning feels out of line with the rest of the library we could always just make a |
I think the I think the |
closed with #855 |
The current overlay API has always felt a bit wonky to me, I think in part because the React ecosystem seems to have now "standardized" around specific patterns with overlays, and the RTBS overlays are showing their age a bit. Specifically, they make the declarative opening and closing of overlays more difficult than it should be, because the logic is specified indirectly via a
OverlayTrigger
child. It would be nice if the below could be possible without much rigmarole.This doesn't require much more code than the current implementation, but is a good bit more declarative and flexible, and inline with the React ecosystem. It also doesn't require needing to create a whole new Modal class every time you want to use a Modal.
In the case of tooltips and popovers the problem is a bit harder, because the trigger is needed to position the overlay. I don't have a great solution, and maybe the current API is best for this sort of thing, but this is a possible alternative.
These api's don't even need to be mutually exclusive,
OverlayTrigger
could encapsulate the above logic fairly easily, while still allowing fine grained control over the overlays if a consumer wants it.I'll admit that a fair bit of this is a matter of opinion, but to me this strike me as more "React like" in its explicitness. Would love feedback, and any additional thoughts
The text was updated successfully, but these errors were encountered: