Expo
@prodtype/async-button
@prodtype/async-button
import React, { useState } from "react"; import { TouchableOpacity, View, Text, ActivityIndicator, Platform, } from "react-native"; import { FontAwesome5 } from "@expo/vector-icons"; import tailwind from "twrnc"; const tw = (styles, customStyles = {}, name) => { const custom = name ? customStyles[name] : ""; return tailwind`${styles} ${custom}`; }; export const Button = (props) => { const { text, loadingText, icon, isLoading, onPress, onLongPress } = props; const styles = props?.styles || {}; return ( <TouchableOpacity style={[ tw("rounded-lg", styles, "container"), { ...(Platform.OS === "web" ? { // outlineColor: getColor("primary-400"), outlineColor: "transparent", outlineWidth: 2, } : {}), }, ]} onPress={onPress} onLongPress={onLongPress} > <View style={[ tw( "w-full h-10 flex items-center justify-center bg-blue-500 rounded-lg", styles, "button" ), ]} > {isLoading ? ( <View style={tw("w-full flex flex-row justify-center items-center")}> <ActivityIndicator color={tw("text-white", styles, "loading").color} /> {loadingText && ( <Text style={tw( "text-center text-white text-base pl-2", styles, "loadingText" )} > {loadingText} </Text> )} </View> ) : ( <View style={tw("flex flex-row items-center", styles, "content")}> {text && ( <Text style={tw( "text-center text-white text-base leading-none", styles, "text" )} > {text} </Text> )} {icon && ( <FontAwesome5 solid={true} name={icon} style={tw("text-white p-2", styles, "icon")} /> )} </View> )} </View> </TouchableOpacity> ); }; export const timeout = async (ms: number) => { return new Promise((resolve) => { setTimeout(() => { resolve(true); }, ms); }); }; export default function App() { const [isLoading, SetIsLoading] = useState(false); return ( <View style={tw( "flex-1 w-full px-4 py-12 flex justify-between items-center mx-auto max-w-[400px]" )} > <View style={tw("w-full")}> <Text style={tw("font-medium text-gray-400 pb-2 px-2")}>Text</Text> <Button text="Submit" isLoading={isLoading} onPress={async () => { SetIsLoading(true); await timeout(3000); SetIsLoading(false); }} /> </View> <View style={tw("w-full")}> <Text style={tw("font-medium text-gray-400 pb-2 px-2")}>Icon</Text> <Button icon="arrow-right" isLoading={isLoading} onPress={async () => { SetIsLoading(true); await timeout(3000); SetIsLoading(false); }} /> </View> <View style={tw("w-full")}> <Text style={tw("font-medium text-gray-400 pb-2 px-2")}> Text & Icon </Text> <Button text="Submit" icon="arrow-right" isLoading={isLoading} onPress={async () => { SetIsLoading(true); await timeout(3000); SetIsLoading(false); }} /> </View> <View style={tw("w-full")}> <Text style={tw("font-medium text-gray-400 pb-2 px-2")}> Custom Loading Text </Text> <Button text="Submit" loadingText="Submitting..." isLoading={isLoading} onPress={async () => { SetIsLoading(true); await timeout(3000); SetIsLoading(false); }} /> </View> <View style={tw("w-full")}> <Text style={tw("font-medium text-gray-400 pb-2 px-2")}> Custom Styling </Text> <Button styles={{ button: "bg-pink-500", text: "text-orange-200", loading: "text-teal-200", }} text="Submit" isLoading={isLoading} onPress={async () => { SetIsLoading(true); await timeout(3000); SetIsLoading(false); }} /> </View> </View> ); }