Button

The Button component is a fundamental building block for displaying text in your React Native applications. It is designed to render styled text with various customization options, making it versatile for a wide range of use cases.

Expo component example
Button

Installation

To use the Input component, make sure first that you have initiated the library.

CLI

This command will add the Input component file to your project and install any necessary dependencies.

npx mallaui@latest add Button

Manual

Copy and paste the following code into your project. Make sure to install the necessary dependencies first and update path to match your project setup.

Button.tsx

import React, {FC, ReactNode} from 'react';
import {ActivityIndicator, TouchableOpacity, StyleSheet, View} from 'react-native';
import {AppTheme} from '../../styles/theme';
import {useStyles} from '../../styles/useStyles';
import {Text} from './Text';

const defaultStyles = (theme: AppTheme) => ({
  base: StyleSheet.create({
    buttonWrapper: {
      alignItems: 'center',
      justifyContent: 'center',
      flexDirection: 'row'
    },
    disabled: {
      opacity: 0.5
    },
    leftSlot: {
      backgroundColor: 'transparent',
      marginRight: theme.paddings.iconPadding
    },
    rightSlot: {
      backgroundColor: 'transparent',
      marginLeft: theme.paddings.iconPadding
    }
  }),

  sizes: StyleSheet.create({
    sm: {
      paddingVertical: 10,
      paddingHorizontal: 12
    },
    md: {
      paddingVertical: 12,
      paddingHorizontal: 16
    },
    lg: {
      paddingVertical: 12,
      paddingHorizontal: 20
    },
    xl: {
      paddingVertical: 14,
      paddingHorizontal: 24
    }
  }),

  shapes: StyleSheet.create({
    square: {
      borderRadius: 10
    },
    circle: {
      borderRadius: 100
    }
  }),

  variants: {
    button: StyleSheet.create({
      default: {
        backgroundColor: theme.colors.app.primary
      },
      secondary: {
        backgroundColor: theme.colors.app.secondary
      },
      outline: {
        borderWidth: 2,
        backgroundColor: theme.colors.app.background,
        borderColor: theme.colors.app.input
      },
      ghost: {
        //
      },
      destructive: {
        backgroundColor: theme.colors.app.destructive
      }
    }),
    text: StyleSheet.create({
      default: {
        color: theme.colors.app.primaryForeground
      },
      secondary: {
        color: theme.colors.app.secondaryForeground
      },
      outline: {
        color: theme.colors.app.foreground
      },
      ghost: {
        color: theme.colors.app.foreground,
        textDecorationLine: 'underline'
      },
      destructive: {
        color: theme.colors.app.destructiveForeground
      }
    })
  }
});

interface IButtonProps {
  /**
   * The title of the button.
   */
  title?: string;

  /**
   * The size of the button.
   * @default 'md'
   */
  size?: keyof ReturnType<typeof defaultStyles>['sizes'];

  /**
   * The corner of the button.
   * @default 'square'
   */
  shape?: keyof ReturnType<typeof defaultStyles>['shapes'];

  /**
   * The variant of the button.
   * @default 'default'
   */
  variant?: keyof ReturnType<typeof defaultStyles>['variants']['button'];

  /**
   * The left slot of the button.
   */
  leftSlot?: ReactNode;

  /**
   * The right slot of the button.
   */
  rightSlot?: ReactNode;

  /**
   * Whether the button is loading.
   * @default false
   */
  isLoading?: boolean;

  /**
   * The action to perform when the user presses the button.
   */
  onPress?: () => void;

  /**
   * Whether the button is disabled.
   * @default false
   */
  isDisabled?: boolean;

  /**
   * The style of the button.
   */
  style?: any;

  /**
   * The style of the title.
   */
  textStyle?: any;
}

/**
 * Basic button component.
 */
const Button: FC<IButtonProps> = ({
  title,
  style,
  isLoading = false,
  textStyle,
  onPress = () => null,
  isDisabled,
  size = 'md',
  variant = 'default',
  shape = 'square',
  leftSlot,
  rightSlot
}) => {
  const styles = useStyles(defaultStyles);

  const handleButtonPress = () => {
    onPress();
  };

  return (
    <TouchableOpacity
      style={[
        styles.base.buttonWrapper,
        styles.sizes[size],
        styles.variants.button[variant],
        styles.shapes[shape],
        isDisabled && styles.base.disabled,
        style
      ]}
      onPress={handleButtonPress}
      disabled={isDisabled || isLoading}
    >
      {leftSlot && !isLoading ? (
        <View style={[styles.base.leftSlot]}>{leftSlot}</View>
      ) : null}
      {isLoading ? (
        <ActivityIndicator
          size='small'
          style={[styles.base.leftSlot]}
          color={styles.variants.text[variant].color}
        />
      ) : null}
      <Text
        size={size}
        fontWeight='medium'
        style={[styles.variants.text[variant], textStyle]}
        numberOfLines={1}
      >
        {title}
      </Text>
      {rightSlot && !isLoading ? (
        <View style={[styles.base.rightSlot]}>{rightSlot}</View>
      ) : null}
    </TouchableOpacity>
  );
};

Button.displayName = 'Button';

export {Button};

Usage

import { Button } from './components/ui/Button'
<Button title="Button" />

Properties

  • Name
    title
    Type
    string
    Description

    Title

  • Name
    size
    Type
    'sm' | 'md' | 'lg' | 'xl'
    Description

    Button size

  • Name
    variant
    Type
    'default' | 'secondary' | 'outline' | 'ghost' | 'destructive'
    Description

    Button variant

  • Name
    shape
    Type
    'square' | 'circle'
    Description

    Button shape

  • Name
    leftSlot
    Type
    ReactNode
    Description

    Icon to display on the left side of the button

  • Name
    rightSlot
    Type
    ReactNode
    Description

    Icon to display on the right side of the button

  • Name
    isLoading
    Type
    boolean
    Description

    Boolean indicating whether the button is in loading state

  • Name
    isDisabled
    Type
    boolean
    Description

    Boolean indicating whether the button is disabled


Size

Expo component example
Size xl
Size lg
Size md
Size sm

Variant

Expo component example
Default
Secondary
Outline
Destructive
Ghost

Shape

Expo component example
Square
Circle

State

Expo component example
Disabled
Loading
Loading destructive

Icon

Expo component example
Left slot
Right slot

Was this page helpful?