Button.tsx

import { styles } from './Button.style';

import { type ForwardedRef, forwardRef, useCallback, useState } from 'react';
import {
  type GestureResponderEvent,
  type PressableProps,
  Pressable,
  View,
} from 'react-native';

import Text from '../text/Text';

type Props = {
  children: string;
  size: 36 | 40 | 44 | 48;
  disabled?: boolean;
  wide?: boolean;
} & Omit<PressableProps, 'ref'>;

const Button = (
  { children, size, disabled = false, wide = false, ...props }: Props,
  ref: ForwardedRef<View>
) => {
  const [pressed, setPressed] = useState(false);

  const handlePressIn = useCallback(
    (event: GestureResponderEvent) => {
      setPressed(true);
      props.onPressIn?.(event);
    },
    [props]
  );

  const handlePressOut = useCallback(
    (event: GestureResponderEvent) => {
      setPressed(false);
      props.onPressOut?.(event);
    },
    [props]
  );

  return (
    <View style={styles.container}>
      <Pressable
        {...props}
        ref={ref}
        disabled={disabled}
        style={[wide && styles.wide]}
        onPressIn={handlePressIn}
        onPressOut={handlePressOut}
      >
        <View
          style={[
            styles.button,
            styles[`button${size}`],
            disabled && styles.disabled,
            wide && styles.wide,
            !disabled && pressed && styles.pressed,
          ]}
        >
          <Text
            style={[
              styles.buttonText,
              styles[`buttonText${size}`],
              disabled && styles.disabledText,
            ]}
          >
            {children}
          </Text>
        </View>
      </Pressable>
    </View>
  );
};

export default forwardRef(Button);

Button.style.ts

import { StyleSheet } from 'react-native';

import theme from '../../theme';

export const styles = StyleSheet.create({
  container: {
    flexWrap: 'wrap',
    justifyContent: 'center',
    flexDirection: 'row',
  },
  button: {
    backgroundColor: theme.color_primary_60,
    borderRadius: 10,
    flexDirection: 'row',
    justifyContent: 'center',
  },
  buttonText: {
    color: theme.color_white,
  },
  button36: {
    paddingVertical: 8,
    paddingHorizontal: 16,
  },
  buttonText36: {
    fontSize: 14,
    lineHeight: 20,
  },
  button40: {
    paddingVertical: 10,
    paddingHorizontal: 16,
  },
  buttonText40: {
    fontSize: 14,
    lineHeight: 20,
  },
  button44: {
    paddingVertical: 11,
    paddingHorizontal: 16,
  },
  buttonText44: {
    fontSize: 15,
    lineHeight: 22,
  },
  button48: {
    paddingVertical: 14,
    paddingHorizontal: 16,
  },
  buttonText48: {
    fontSize: 14,
    lineHeight: 20,
  },
  disabled: {
    backgroundColor: theme.color_icon_gray_10,
  },
  disabledText: {
    color: theme.color_icon_gray_40,
  },
  wide: {
    width: '100%',
  },
  pressed: {
    backgroundColor: theme.color_primary_80,
  },
});