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

Displace action button/content instead of overlaying #11

Open
JulianKingman opened this issue Dec 30, 2016 · 25 comments
Open

Displace action button/content instead of overlaying #11

JulianKingman opened this issue Dec 30, 2016 · 25 comments

Comments

@JulianKingman
Copy link

Material design recommends that the snackbar not overlay an action button, is it possible to do that with this package?

here: https://material.io/guidelines/components/snackbars-toasts.html#snackbars-toasts-usage

@cooperka
Copy link
Owner

Hi @JulianKingman, thanks for the link. I agree we should follow this recommendation as closely as possible. Unfortunately there's no real way for us to know if the app has an action button or not, so we can't make it happen automatically, but I wonder if we could support some sort of redux event to broadcast how tall the snackbar is at any given point (or at least broadcast when it toggles visible/hidden).

For now, there is no easy solution for you, but I do want to support this soon. I'm considering re-writing the entire module to be pure JS instead of native, and that would make this type of thing easier to support.

I'll update you here when there's a change. Curious to hear your thoughts about this, too!

@JulianKingman
Copy link
Author

JulianKingman commented Jan 19, 2017

What if you require manually adding the snackbar component, that way it could actually take up space on the layout, and be positioned in the right place for it?
For example:

render() {
  <View>
    <Toolbar />
    <Content>
      <ActionButton />
    </Content>
    <Snackbar />
  </View>
}

@cooperka
Copy link
Owner

cooperka commented Jan 19, 2017

@JulianKingman that's a good idea, but currently the Snackbar UI is implemented natively, so I don't think that would be possible without rewriting the whole thing in JS. That's something I want to do, but it's a big change and probably won't be done for a while!

We could add a dummy component that simply takes up space underneath the native Snackbar, but that's hacky and may not work very well if it just pushes up all content. However, it might work if you include it in a view with just your FAB... something like this:

<View>
  <FloatingActionButton />
  <SnackbarDummy />
</View>

Android uses a CoordinatorLayout to handle this when the FAB is also native, but in your case you have a native Snackbar and a JS FAB so it's more tricky ;)

Are you willing to make a PR for this?

@cooperka cooperka changed the title Possible to displace action button/content instead of overlaying? Displace action button/content instead of overlaying Apr 28, 2017
@iRoachie
Copy link
Contributor

iRoachie commented May 22, 2017

If you're using react-native-material-ui's ActionButton, I just sent in a pr that implements this. xotahal/react-native-material-ui#144

@cooperka
Copy link
Owner

@iRoachie that's a neat workaround, but I don't think that's the right way to go about it. What about exporting a SnackbarAvoidingView component that does the exact same thing, but from this library? Then it's generalizable and can be used by anyone for anything, not just that specific library.

Slightly modified from the original suggestion above, it could be used like:

<SnackbarAvoidingView>
  <ActionButton />
</SnackbarAvoidingView>

or as a HOC:

render() {
  const SnackbarAvoidingActionButton = withSnackbarAvoidingView(ActionButton);
  return <SnackbarAvoidingActionButton />;
}

@iRoachie
Copy link
Contributor

@cooperka We'd still need a way, to notify the view when the snackbar is showing as well as the duration, and height, etc. so I'm not seeing any difference. Am I missing something?

@cooperka
Copy link
Owner

The difference is that SnackbarAvoidingView is the one that animates its height, rather than ActionButton. So instead of needing to send a PR to every library that has a component that might want to animate away from a snackbar, we can just export a wrapper from this library and anyone can use it.

@iRoachie
Copy link
Contributor

Ah gotcha 👍

@iRoachie
Copy link
Contributor

@cooperka Fresh off the press. https://github.com/iRoachie/react-native-snackbar-avoiding-view

@cooperka
Copy link
Owner

Hey, nice work!

Would you mind also submitting a PR to add that as a dependency to this library, and simply export it (so people don't need to install both modules separately)? Seems like it would be common enough to want both. It's cool that your module can be used as a standalone too.

@cooperka
Copy link
Owner

I wonder if we could also hook it up to (optionally) automatically call avoidSnackbar() during Snackbar.show(). That would be awesome.

@iRoachie
Copy link
Contributor

@cooperka that sounds good actually, just wondering. Is an ActionButton the only use case that the snackbar avoids?

@cooperka
Copy link
Owner

Anything with the same z-index as the snackbar should move to avoid it, per material design specs (because in real life, things can't occupy the same space). The only other thing defined to have the same z-index (6) is the FAB: https://material.io/guidelines/material-design/elevation-shadows.html#elevation-shadows-elevation-android

So yes, that's pretty much the only thing you need to worry about.

@iRoachie
Copy link
Contributor

iRoachie commented Jun 3, 2017

@cooperka Soo my method behind doing that is to pass a ref to the SnackbarAvoidView into the options for Snackbar.show, getting a red warning that I have no idea how to fix.

Invalid data message - all must be length 11

Snackbar.show({
      title: 'That\' right FAB, move!',
      duration: Snackbar.LENGTH_LONG,
      ref: this.refs.avoidingView
})

@cooperka
Copy link
Owner

cooperka commented Jun 3, 2017

@iRoachie try cleaning all caches and starting fresh. I got that message before when running mismatched versions of React Native (one in JS and a different one in native code).

@cooperka
Copy link
Owner

@iRoachie did you end up getting it to work?

@iRoachie
Copy link
Contributor

@cooperka Sorry about that, went on the backlog for a bit. Will knock up something between now and weekend

@aMarCruz
Copy link

aMarCruz commented Feb 9, 2018

@cooperka , if you expose onShow and onHide events this issue have an easy solution.
Anyway, your lib is a great work, thanks.

@cooperka
Copy link
Owner

cooperka commented Feb 9, 2018

Hmm, that's an interesting idea @aMarCruz. It seems like there might be some delay using events though, which could look janky (if your FAB rises up 100 ms after the snackbar appears).

It would be a decent temporary solution and I'm happy to accept a PR for it!

@aMarCruz
Copy link

@cooperka , Unfortunately I don't have enough experience on Android and know nothing about iOS, but will try to make something about this.

@cooperka
Copy link
Owner

The event could be fired from JS, no native code needed. Have a look at src/index.js show().

@aMarCruz
Copy link

mmm... I'm thinking about the native "onDismiss" method of Snackbar.Callback to catch dismiss events, it works without CoordinatorLayout, by anyway I'll make a try. Thanks.

@dantman
Copy link
Contributor

dantman commented Feb 10, 2018

Animated.event with useNativeDriver: true on events like onScroll can handle event animations entirely natively. I wonder if it's possible for libraries to define their own events that do the same.

Then we could fire some sort of onSnackbarOffsetChange on every frame while the snackbar is sliding in or out, and as long as transform and useNativeDriver are used on whatever else is being animated the animation will be kept in sync.

@cooperka
Copy link
Owner

@dantman nice suggestion, that method would be ideal if anyone is up for implementing it.

@dantman
Copy link
Contributor

dantman commented Feb 10, 2018

The Snackbar's class on Android doesn't seem to have animation information, so perhaps we'll have to trick CoordinatorLayout to giving us the information we need. Possibly using CoordinatorLayout.Behavior#onApplyWindowInsets if that works.

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

5 participants