stipsan / react-spring-bottom-sheet

Accessible ♿️, Delightful ✨, & Fast 🚀
https://react-spring.bottom-sheet.dev/
MIT License
960 stars 132 forks source link

[Need Help] Sheet to appear behind a footer #77

Open ajaypillay opened 3 years ago

ajaypillay commented 3 years ago

Here's a quick video of the problem I'm trying to solve: https://user-images.githubusercontent.com/917752/104208742-cea3b080-546b-11eb-9c62-e334cd10ac5c.mp4

My sheet has a z-index of 1150 and the bar below it has a z-index of 1200. However, when I try to close the sheet it appears in front of the bottom bar, even though the sheet's z-index is 1150 (some parts are 1151, 1153, basically all the z-indexes defined in the default CSS have been incremented by 1150). Also worth noting that I made all the elements in the bottom bar have a z-index of > 1200 for extra measure.

The sheet renders at that position when it's opened, as my bar has a height of 7vh and I changed the bottom offset to bottom 7vh for

[data-rsbs-overlay],
[data-rsbs-backdrop],
[data-rsbs-root]:after

I understand that there's an option to have a footer within the sheet, but here I'm trying to get my footer to be outside the sheet, and depending on what icon you tap in the bottom bar, a different sheet shows up, but renders behind the bar.

How could I accomplish this? Thank you!

stipsan commented 3 years ago

Hmmm, there are two challenges here. The CSS challenge with z-indexes like you're describing, and after you've solved that you'll face the problem of interactivity as the bottom sheet is blocking everything else on the page (unless blocking={false}).

Problem 1, z-indexes

It's not enough with a higher z-index, you must also ensure the footer you want to overlay the bottom sheet has position: absolute, position: fixed or position: relative, for it to take effect. Check this demo and the "Close example" link for a working example: https://react-spring-bottom-sheet.cocody.dev/fixtures/scrollable

This guide is handy for this kind of CSS madness: https://dev.to/sharmakushal/how-to-solve-the-z-index-issue-within-1-minute-4pn9

Problem 2, interactivity

If you checked the demo link: https://react-spring-bottom-sheet.cocody.dev/fixtures/scrollable the "Close example" link here is using the aside prop, this is needed for it to be possible to click on it, navigate to it by keyboard or activating it in a screen reader. This is because blocking={true} ensures you can't accidentally interact with anything outside the bottom sheet in this mode. Most of the time this is what you want. In your case though you want the nav footer to be interactive as an exception.

Putting it in the sibling prop will accomplish exactly that.

It's annoying to render the nav footer twice

I get that. It would be more elegant if blocking had the ability to opt-out using data attributes, similar to how you can with the scrollLocking api. But right now you can't, I'd like to add this ability in the future but for now I recommend you go with the double render approach as it'll cause you the least resistance and fighting with the accessibility related features of the bottom sheet.

Bonus tip in the end

I notice you said you give the bottom sheet a bottom sheet a 7vh offset. I recommend rendering an empty div with a fixed height in the footer prop to accomplish this offset, instead of using a bottom CSS trick or similar. As it'll ensure edge cases keep working nicely.

Your use case is really interesting, I think I'll use it to try and setup an example based off it 😄

ajaypillay commented 3 years ago

Hey @stipsan thank you for the response! So to address the problems, this was my train of thought:

For problem 1 - yes initially I did not want to mess with the z-index, that's why I decided to give it the 7vh offset so it appears above the footer. However - you can see that it overlaps while it transitions, and then the z-index became a problem needing to be solved. And of course problem 2 - blocking became another issue. I wanted initially to find a way to set it such that everything above the sheet is blocked but below it wasn't, but instead just compromised by setting blocking={false}.

Technically right now if I can fix the z-index issue then it works perfectly well if blocking={false}.

Thank you for pointing out the sibling prop, I will try that out, together with the invisible 'footer' in the sheet.

And yes - an example of this would be wonderful! I think this package in and of itself is very powerful, so more examples would be awesome!

ajaypillay commented 3 years ago

Hey @stipsan, here's just an update after a few months (school started and I worked on other aspects of the app I'm building, but revisited the sheet aspect today).

I got this working by passing a duplicate of my navbar as a sibling, I did not need to use the invisible footer or mess around with the z-indexing. I accomplished this by giving it position: absolute, bottom: 0, and z-index: 4 (anything >3 works).

Here's a quick Code Sandbox demo of it in action! :-)

Note that in this demo I had to give the sibling footer a left offset and a bottom offset but the CSS can be changed to suit whatever example needed. For my actual app I just needed bottom: 0 for it to render in the same position. Also I think the CSS used is different from the most recent version. I had to hardcode some values in as my preprocessor Stylus was complaining of some syntax issues. But otherwise there aren't any other variations.

This solution is definitely not ideal due to requiring a second render and overlapping components, but I think it's fine to make do with for now and I don't think there are any performance issues either. Would be great for this to be a feature nonetheless if possible without requiring the re-render.

Thank you again for the help!

ArturGrafTKT commented 1 year ago

why so complicated? Add a global style an it just works: reach-portal { position: relative; z-index: 10; }

fatihbaskaya commented 2 months ago

why so complicated? Add a global style an it just works: reach-portal { position: relative; z-index: 10; }

That worked for me, thanks!