SIGN IN SIGN UP

Forward `borderless` and `foreground` from `android_ripple` (#4442)

## Description

Follow-up to #4411. `StatefulPressable` and the legacy `Pressable` only
forwarded `color` and `radius` from `android_ripple` to the button, so
`borderless` and `foreground` silently did nothing on those engines -
the ripple stayed bounded and drew under the children.
`PressableWithTouchable` already passed all four fields, which made the
behavior depend on whether a relation prop
(`simultaneousWith`/`requireToFail`/`block`) was present.

Both engines now pass the whole config through. The button props for the
two flags already existed, only the Pressable side dropped them.

## Test plan

<details>
<summary>Tested on the following code:</summary>

```tsx
import React from 'react';
import {
  Pressable as RNPressable,
  ScrollView,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import { LegacyPressable, Pressable } from 'react-native-gesture-handler';
import type { PressableProps } from 'react-native-gesture-handler';

// Android-only check for `android_ripple.borderless` / `.foreground`, which the
// StatefulPressable and legacy engines used to drop (only color + radius were
// forwarded to the button).
//
// borderless: the ripple is a circle that spills outside the box.
// foreground:  the ripple draws over the opaque child instead of under it.
//
// Every column must look the same. Nothing to see on iOS - no native ripple there.

const RIPPLE_COLOR = '#1565c0';

const VARIANTS = [
  {
    label: 'baseline\n{ color }',
    ripple: { color: RIPPLE_COLOR },
    covered: false,
  },
  {
    label: 'borderless\n{ borderless: true }',
    ripple: { color: RIPPLE_COLOR, borderless: true },
    covered: false,
  },
  {
    // Control for the row below: a background ripple hides under the child.
    label: 'covered, control\n{ color }\nno ripple expected',
    ripple: { color: RIPPLE_COLOR },
    covered: true,
  },
  {
    label: 'foreground\n{ foreground: true }\nripple over the child',
    ripple: { color: RIPPLE_COLOR, foreground: true },
    covered: true,
  },
  {
    label: 'both + radius\n{ borderless, foreground, radius: 70 }',
    ripple: {
      color: RIPPLE_COLOR,
      borderless: true,
      foreground: true,
      radius: 70,
    },
    covered: true,
  },
] as const;

// A relation prop is what routes the public `Pressable` to the Stateful engine.
function StatefulPressable(props: PressableProps) {
  return <Pressable {...props} simultaneousWith={[]} />;
}

const ENGINES = [
  { label: 'v3\nTouchable', Component: Pressable },
  { label: 'v3\nStateful', Component: StatefulPressable },
  { label: 'legacy\nRNGH', Component: LegacyPressable },
  { label: 'RN\ncontrol', Component: RNPressable },
] as const;

export default function EmptyExample() {
  return (
    <ScrollView contentContainerStyle={styles.container}>
      <View style={styles.row}>
        <View style={styles.variantLabel} />
        {ENGINES.map((engine) => (
          <Text key={engine.label} style={styles.engineLabel}>
            {engine.label}
          </Text>
        ))}
      </View>

      {VARIANTS.map((variant) => (
        <View key={variant.label} style={styles.row}>
          <Text style={[styles.variantLabel, styles.variantText]}>
            {variant.label}
          </Text>
          {ENGINES.map(({ label, Component }) => (
            <View key={label} style={styles.cell}>
              <Component android_ripple={variant.ripple} style={styles.button}>
                {variant.covered ? <View style={styles.cover} /> : null}
              </Component>
            </View>
          ))}
        </View>
      ))}
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 12,
    paddingTop: 40,
    gap: 20,
  },
  row: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  variantLabel: {
    width: 100,
  },
  variantText: {
    fontSize: 11,
    fontFamily: 'monospace',
    color: '#37474f',
  },
  engineLabel: {
    flex: 1,
    fontSize: 11,
    textAlign: 'center',
    color: '#607d8b',
  },
  cell: {
    flex: 1,
    alignItems: 'center',
  },
  button: {
    width: 54,
    height: 54,
    borderRadius: 6,
    backgroundColor: '#eceff1',
  },
  cover: {
    flex: 1,
    backgroundColor: '#cfd8dc',
  },
});
```

</details>
M
Michał Bert committed
b2bbb4974d66f6a95c2447f5dceacf91d621604f
Parent: 00acc10
Committed by GitHub <noreply@github.com> on 8/19/2026, 10:52:03 AM