iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Button / Pressable

React Native button-like components: Button, Pressable, TouchableOpacity, and the platform-aware patterns.

React Native — buttons

EXAMPLE
import { Button, Pressable, TouchableOpacity, View, Text, StyleSheet, Platform } from 'react-native';

// ===== 1. Built-in <Button> (limited styling) =====
<Button title="Submit" onPress={onSubmit} color="#2563eb" />
// Pros: native button on each platform
// Cons: no custom styling; rarely the right choice for design-led apps

// ===== 2. Pressable (recommended, RN 0.63+) =====
<Pressable
  onPress={onPress}
  onLongPress={onLongPress}
  style={({ pressed }) => [
    styles.btn,
    pressed && styles.btnPressed,
  ]}
  android_ripple={{ color: 'rgba(255,255,255,0.2)' }}
  hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
  accessibilityRole="button"
  accessibilityLabel="Submit form"
>
  <Text style={styles.btnText}>Submit</Text>
</Pressable>

// ===== 3. TouchableOpacity (legacy but still common) =====
<TouchableOpacity onPress={onPress} activeOpacity={0.7} style={styles.btn}>
  <Text style={styles.btnText}>Submit</Text>
</TouchableOpacity>

// ===== Styling (StyleSheet) =====
const styles = StyleSheet.create({
  btn: {
    backgroundColor: '#2563eb',
    paddingVertical: 12,
    paddingHorizontal: 16,
    borderRadius: 8,
    alignItems: 'center',
  },
  btnPressed: {
    backgroundColor: '#1d4ed8',
  },
  btnText: {
    color: 'white',
    fontWeight: '600',
    fontSize: 16,
  },
});

// ===== A reusable button component =====
function PrimaryButton({ title, onPress, disabled }) {
  return (
    <Pressable
      onPress={onPress}
      disabled={disabled}
      style={({ pressed }) => [
        styles.btn,
        disabled && { opacity: 0.5 },
        pressed && styles.btnPressed,
      ]}
      android_ripple={!disabled ? { color: 'rgba(255,255,255,0.2)' } : undefined}
      accessibilityRole="button"
      accessibilityState={{ disabled: !!disabled }}
    >
      <Text style={styles.btnText}>{title}</Text>
    </Pressable>
  );
}

// ===== Loading state =====
import { ActivityIndicator } from 'react-native';

function SubmitButton({ onPress, loading }) {
  return (
    <Pressable onPress={onPress} disabled={loading} style={styles.btn}>
      {loading ? <ActivityIndicator color="white" /> : <Text style={styles.btnText}>Submit</Text>}
    </Pressable>
  );
}

// ===== Icon buttons =====
import { Feather } from '@expo/vector-icons';

<Pressable onPress={onClose} hitSlop={12} style={({ pressed }) => [{ opacity: pressed ? 0.6 : 1 }]}>
  <Feather name="x" size={20} color="#0f172a" />
</Pressable>

// ===== Platform-aware patterns =====
const buttonStyle = Platform.select({
  ios: { borderRadius: 8 },
  android: { borderRadius: 4, elevation: 2 },
});

// ===== Accessibility =====
// - accessibilityRole="button"
// - accessibilityLabel for icon-only buttons
// - accessibilityState={{ disabled, busy }}
// - hitSlop on small tap targets to meet 44x44 minimum

// ===== Patterns to internalise =====
// - Pressable over TouchableOpacity in new code
// - hitSlop for small icon buttons (44x44 minimum tap target)
// - Loading + disabled state encoded both visually and via accessibilityState
// - PrimaryButton / SecondaryButton component pair for the whole app

// ===== Pitfalls =====
// - <Button> is too restrictive; use Pressable for custom UI
// - Inline styles inside hot lists -> new object every render
// - Forgetting hitSlop on tiny icons -> bad UX
// - Disabled visuals without accessibilityState={{ disabled: true }} -> screen reader gap

Why it matters

Pressable is the modern button primitive. Wrap it in a PrimaryButton component with consistent styles, loading + disabled states, accessibility roles, and android_ripple. Use the built-in Button only for prototypes; build your own for any real app.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import { Pressable, Text } from 'react-native';
<Pressable
    onPress={() => alert('hi')}
    style={({ pressed }) => ({ opacity: pressed ? 0.5 : 1 })}
>
    <Text>Tap me</Text>
</Pressable>
Try it Yourself »

Discussion

Loading…