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

Portal #43

Closed
satya164 opened this issue Oct 26, 2016 · 7 comments
Closed

Portal #43

satya164 opened this issue Oct 26, 2016 · 7 comments

Comments

@satya164
Copy link
Member

satya164 commented Oct 26, 2016

Description

Elements like FAB and Snackbar render on a different plane above the content in z-axis. Many other elements such as bottom sheets, modals etc. need to be rendered above content too. It'll be useful to have a single Portal component to handle these cases.

To determine which elements exist on which plane, we need to refer to their elevation - https://material.google.com/material-design/elevation-shadows.html#elevation-shadows-elevation-android

Use cases

  • Elements with same elevation should be grouped in the same layer along the z-axis (e.g. FAB, Snackbar)
  • Grouped elements should move together, e.g. when a Snackbar slides in from button, the FAB should move up

Detailed design

Props

The Portal component will accept two props, elevation and layered.

The elevation prop determines the elevation of the layer in the z-axis. There will be predefined elevations for internal use according to material design guidelines:

const Elevations = {
  DIALOG: 24, // Dialogs and Pickers
  DRAWER: 16, // Drawer, Bottom sheet
  FAB_RAISED: 12, // Floating action button (raised)
  CARD_RAISED: 8, // Card (raised), Button (raised), Bottom navigation, Menu
  FAB_RESTING: 6, // Floating action button, Snackbar
  APPBAR: 4, // Floating action button, Snackbar
  CARD_RESTING: 2, // Card, Button, Search bar
}

This is not the full list of elevations, rather the ones we need. Naming is up-to-debate. This will be internal for now, so we can change them later.

The layered prop is a boolean which determines whether the item is grouped with other layered items in a single layer. Grouped items are rendered under the same View and positioned using flexbox, so items will appear one below another. When the layered prop is false or not passed, the items will be positioned absolutely instead. Non-layered items will render below layered elements.

Usage

<Portal elevation={Elevations.FAB_RESTING} layered>
  <View style={styles.snackbar}>
    Hey! I'm a `Snackbar` :)
  </View>
</Portal>

Animations

The main motivation behind this is animations, i.e. when you show a new Snackbar, it should slide in from the bottom and move everything else up (FAB). The easiest way seems to be to handle the animation inside Portal. This is how it'll work:

  1. On initial render, render everything normally.
  2. When a new element is rendered later, render it offscreen and measure the height ({ position: 'absolute', left: 0, right: 0, bottom: -9999 }).
  3. Now render the element normally, but also apply a translateY of height to all the elements. This should have no visual difference.
  4. Animate the translateY to 0 so everything moves up.
  5. When the element is removed, animate the translateY to height so everything moves down.
  6. Now remove that element and reset the translateY to 0
  7. If new elements are added/removed mid-transition, it'll wait till the transition is complete to reflect the changes.

This approach assumes that all the elements in a layer are going to use the same slide up/slide down animations for appearing/disappearing.

@clauderic
Copy link

clauderic commented Oct 28, 2016

As discussed on slack, the portal wrapper/provider should live at the root level of the application, so as to be able to absolute position portals on top of the rest of the application.

We can use context to communicate between the portal wrapper and child <Portal> components that may be nested arbitrarily deep in the component tree.

@satya164 satya164 added the wip label Nov 22, 2016
@ahmedlhanafy
Copy link
Contributor

@satya164 shouldn't this be closed?

@ahmedlhanafy
Copy link
Contributor

@clauderic @satya164 Please re-open if needed

@satya164 satya164 reopened this Dec 6, 2017
@ferrannp ferrannp removed the wip label Apr 4, 2018
@satya164 satya164 mentioned this issue May 6, 2018
5 tasks
@ferrannp ferrannp modified the milestone: 2.0.0 May 9, 2018
@jsamr
Copy link

jsamr commented Dec 28, 2019

@ahmedlhanafy @satya164 So what happened to the very promising features described in the OP? I don't see any elevation or layered prop in the Portal component. Has it been dropped because of its complexity, or somehow replaced but I couldn't find the implementation? I would be very interested in having FAB and Bottom nav aware snackbars... that would feel native ❤️

@kopax
Copy link

kopax commented Mar 27, 2020

@satya164, I just opened this: #1762

I found it impossible to use the Portal in my app because it breaks my app bar actions.

The elevation settings would have saved it, I hope this can be included one day.

@acro5piano
Copy link

FYI: could <Portal.Host> solve the problem?

https://callstack.github.io/react-native-paper/portal-host.html

@sepsol
Copy link

sepsol commented Sep 29, 2021

This information should be in the docs. Unfortunately, I had to dig for it.

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

No branches or pull requests

8 participants