Skip to content

Instantly share code, notes, and snippets.

@tchayen
Last active March 4, 2020 01:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tchayen/363abcbec312909195e947b5f23fb44c to your computer and use it in GitHub Desktop.
Save tchayen/363abcbec312909195e947b5f23fb44c to your computer and use it in GitHub Desktop.
import React, { Component, createContext, useState } from "react";
import {
Animated,
TouchableOpacity,
View,
Text,
StyleSheet,
Platform
} from "react-native";
import { borderRadius, colors } from "./consts";
const styles = StyleSheet.create({
position: {
position: "absolute",
bottom: 16,
left: 0,
width: "100%",
flexDirection: "row",
justifyContent: "center"
},
snackbar: {
backgroundColor: colors.primary,
height: 48,
alignItems: "center",
paddingLeft: 24,
flexDirection: "row",
borderRadius
},
text: {
fontFamily: "regular",
fontSize: 16,
color: colors.white
},
dismiss: {
paddingHorizontal: 24,
height: 48,
justifyContent: "center",
alignItems: "center"
},
dismissText: {
fontFamily: "regular",
fontSize: 16,
color: colors.white,
opacity: 0.8
}
});
type Props = {
children: string;
onDismiss?: () => void;
dismissable?: boolean;
};
type SnackbarContextType = {
mount: (props: Props) => void;
unmount: () => void;
};
const SnackbarContext = createContext<SnackbarContextType>(null);
export const SnackbarProvider = ({ children }) => {
const [value] = useState(new Animated.Value(0));
const [props, setProps] = useState<Props>(null);
const showConfig = {
toValue: 1,
duration: 300,
useNativeDriver: Platform.OS !== "web"
};
const hideConfig = {
toValue: 0,
duration: 300,
useNativeDriver: Platform.OS !== "web"
};
const mount = (props: Props) => {
setProps(props);
Animated.timing(value, showConfig).start();
};
const unmount = () => {
Animated.timing(value, hideConfig).start(() => {
if (typeof props.onDismiss === "function") {
props.onDismiss();
}
setProps(null);
});
};
return (
<SnackbarContext.Provider value={{ mount, unmount }}>
{children}
{props && (
<View style={styles.position}>
<Animated.View style={[styles.snackbar, { opacity: value }]}>
<Text style={styles.text}>{props.children}</Text>
{props.dismissable && (
<TouchableOpacity activeOpacity={0.8} onPress={unmount}>
<View style={styles.dismiss}>
<Text style={styles.dismissText}>dismiss</Text>
</View>
</TouchableOpacity>
)}
</Animated.View>
</View>
)}
</SnackbarContext.Provider>
);
};
export default class Snackbar extends Component<Props> {
static contextType = SnackbarContext;
componentDidMount() {
this.context.mount(this.props);
}
componentWillUnmount() {
this.context.unmount();
}
render() {
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment