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>
);
}