Last active
March 4, 2020 01:16
-
-
Save tchayen/363abcbec312909195e947b5f23fb44c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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