React Native Glow UI v1 is out now!
Logo
Components

Button

Button component for React Native

Installation

npx rn-glow add button

⚙️ Props

PropTypeDefaultDescription
titlestringrequiredText to display on the button.
isLoadingbooleanrequiredWhether the button is in a loading state.
onPress() => voidrequiredFunction to call when the button is pressed.
widthnumberundefinedWidth of the button in its expanded state.
heightnumberundefinedHeight of the button.
backgroundColorstringundefinedBackground color of the button (ignored if gradientColors is provided).
textColorstringundefinedColor of the button text.
fontSizenumberundefinedFont size of the button text.
iconkeyof typeof Feather.glyphMapundefinedOptional Feather icon name to display before the text.
iconSizenumberundefinedSize of the icon.
iconColorstringtextColorColor of the icon. Defaults to textColor.
borderRadiusnumberautoBorder radius of the button. Automatically calculated if not provided.
gradientColorsstring[]undefinedGradient color array (overrides backgroundColor if present).
styleViewStyleundefinedCustom style for the button container.
textStyleTextStyleundefinedCustom style for the button text.
withPressAnimationbooleanfalseWhether to apply a press animation effect.
loadingComponentReact.ReactNodeundefinedCustom loading component (overrides default spinner).
loadingIndicatorColorstringundefinedColor of the default loading spinner (if used).
animationConfig{ damping?: number; stiffness?: number; duration?: number; }{}Optional animation configuration for expansion/press effects.
disabledbooleanfalseWhether the button is disabled.

🚀 Example

// @glow-ui - React Native
// @button/demo-usage example

// @ts-check
import React, { useCallback, useState, memo } from "react";
import {
  View,
  Text,
  ScrollView,
  SafeAreaView,
  useWindowDimensions,
  StyleSheet,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { ExpandableButton } from "@/components";

const ButtonDemo: React.FC = (_$_): React.ReactNode => {
  const [primaryLoading, setPrimaryLoading] = useState<boolean>(false);
  const [gradientLoading, setGradientLoading] = useState<boolean>(false);
  const [githubLoading, setGithubLoading] = useState<boolean>(false);
  const [dangerLoading, setDangerLoading] = useState<boolean>(false);
  const [outlineLoading, setOutlineLoading] = useState<boolean>(false);
  const [disabledExample, setDisabledExample] = useState<boolean>(false);

  const width = useWindowDimensions().width;
  const handlePrimaryPress = useCallback<() => any | Function>(() => {
    setPrimaryLoading(true);
    setTimeout(() => {
      setPrimaryLoading(false);
    }, 2000);
  }, []);

  const handleGradientPress = useCallback<() => any | Function>(() => {
    setGradientLoading(true);
    setTimeout(() => {
      setGradientLoading(false);
    }, 2500);
  }, []);

  const handleGithubPress = useCallback<() => any | Function>(() => {
    setGithubLoading(true);
    setTimeout(() => {
      setGithubLoading(false);
    }, 3000);
  }, []);

  const handleDangerPress = useCallback<() => any | Function>(() => {
    setDangerLoading(true);
    setTimeout(() => {
      setDangerLoading(false);
    }, 1500);
  }, []);

  const handleOutlinePress = useCallback<() => any | Function>(() => {
    setOutlineLoading(true);
    setTimeout(() => {
      setOutlineLoading(false);
    }, 2000);
  }, []);

  const toggleDisabled = useCallback<() => any | Function>(() => {
    setDisabledExample(!disabledExample);
  }, [disabledExample]);

  return (
    <SafeAreaView style={styles.container}>
      <ScrollView
        contentContainerStyle={styles.scrollContent}
        showsVerticalScrollIndicator={false}
        scrollEnabled
        contentInsetAdjustmentBehavior="always"
      >
        <View style={styles.content}>
          <View style={styles.header}>
            <Ionicons name="radio-button-on" size={24} color="#6366f1" />
            <Text style={styles.title}>Button</Text>
          </View>

          <Text style={styles.subtitle}>
            Comprehensive examples demonstrating all button variants and
            configurations
          </Text>

          <View style={styles.exampleSection}>
            <Text style={styles.exampleTitle}>Primary Button</Text>
            <Text style={styles.exampleDescription}>
              Standard button with custom styling, icon, and loading state
            </Text>
            <ExpandableButton
              title="Launch Application"
              isLoading={primaryLoading}
              onPress={handlePrimaryPress}
              width={width - 80}
              height={52}
              backgroundColor="#6366f1"
              textColor="#ffffff"
              fontSize={16}
              icon="aperture"
              iconSize={18}
              iconColor="#ffffff"
              borderRadius={12}
              style={styles.primaryButtonStyle}
              textStyle={styles.primaryTextStyle}
              withPressAnimation={true}
              loadingIndicatorColor="#ffffff"
              animationConfig={{
                damping: 15,
                stiffness: 150,
                duration: 300,
              }}
              disabled={false}
            />
          </View>

          <View style={styles.exampleSection}>
            <Text style={styles.exampleTitle}>Gradient Button</Text>
            <Text style={styles.exampleDescription}>
              Beautiful gradient background with custom animation timing
            </Text>
            <ExpandableButton
              title="Start Journey"
              isLoading={gradientLoading}
              onPress={handleGradientPress}
              width={width - 80}
              height={56}
              gradientColors={["#667eea", "#764ba2"]}
              textColor="#ffffff"
              fontSize={17}
              icon="compass"
              iconSize={20}
              iconColor="#ffffff"
              borderRadius={28}
              style={styles.gradientButtonStyle}
              textStyle={styles.gradientTextStyle}
              withPressAnimation={true}
              loadingIndicatorColor="#ffffff"
              animationConfig={{
                damping: 20,
                stiffness: 200,
                duration: 250,
              }}
              disabled={false}
            />
          </View>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#0a0a0a",
  },
  scrollContent: {
    paddingBottom: 40,
  },
  content: {
    paddingHorizontal: 24,
    paddingVertical: 32,
    gap: 32,
  },
  header: {
    flexDirection: "row",
    alignItems: "center",
    gap: 12,
    marginBottom: 8,
  },
  title: {
    fontSize: 28,
    fontWeight: "700",
    color: "#ffffff",
    letterSpacing: -0.5,
  },
  subtitle: {
    fontSize: 16,
    color: "#6b7280",
    lineHeight: 24,
    marginBottom: 16,
  },
  exampleSection: {
    gap: 12,
    paddingVertical: 8,
  },
  exampleTitle: {
    fontSize: 20,
    fontWeight: "600",
    color: "#ffffff",
    marginBottom: 4,
  },
  exampleDescription: {
    fontSize: 14,
    color: "#9ca3af",
    lineHeight: 20,
    marginBottom: 16,
  },
  disabledContainer: {
    gap: 16,
    alignItems: "center",
  },
  features: {
    gap: 16,
    marginTop: 24,
  },
  featuresTitle: {
    fontSize: 22,
    fontWeight: "600",
    color: "#ffffff",
    marginBottom: 8,
  },
  feature: {
    flexDirection: "row",
    alignItems: "center",
    gap: 12,
    paddingVertical: 8,
  },
  featureText: {
    fontSize: 15,
    color: "#9ca3af",
    fontWeight: "500",
    flex: 1,
  },
  primaryButtonStyle: {
    shadowColor: "#6366f1",
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.25,
    shadowRadius: 8,
    elevation: 6,
  },
  primaryTextStyle: {
    fontWeight: "600",
    letterSpacing: 0.3,
  },
  gradientButtonStyle: {
    shadowColor: "#667eea",
    shadowOffset: { width: 0, height: 6 },
    shadowOpacity: 0.3,
    shadowRadius: 12,
    elevation: 8,
  },
  gradientTextStyle: {
    fontWeight: "700",
    letterSpacing: 0.5,
  },
  githubButtonStyle: {
    shadowColor: "#000000",
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.4,
    shadowRadius: 6,
    elevation: 4,
  },
  githubTextStyle: {
    fontWeight: "500",
    letterSpacing: 0.2,
  },
  dangerButtonStyle: {
    shadowColor: "#ef4444",
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.3,
    shadowRadius: 10,
    elevation: 6,
  },
  dangerTextStyle: {
    fontWeight: "600",
    letterSpacing: 0.3,
  },
  outlineButtonStyle: {
    borderWidth: 2,
    borderColor: "#6366f1",
    shadowColor: "#6366f1",
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.15,
    shadowRadius: 4,
    elevation: 2,
  },
  outlineTextStyle: {
    fontWeight: "600",
    letterSpacing: 0.4,
  },
  disabledButtonStyle: {
    opacity: 0.6,
  },
  disabledTextStyle: {
    fontWeight: "500",
  },
  toggleButtonStyle: {
    shadowColor: "#10b981",
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 4,
    elevation: 3,
  },
  bounceButtonStyle: {
    shadowColor: "#f093fb",
    shadowOffset: { width: 0, height: 8 },
    shadowOpacity: 0.35,
    shadowRadius: 16,
    elevation: 10,
  },
  bounceTextStyle: {
    fontWeight: "700",
    letterSpacing: 0.6,
  },
});

export default memo(ButtonDemo);