Skip to content

(cherry-pick) fix: Support optional arguments in boxShadow string (#7386) #7394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

patrycjakalinska
Copy link
Contributor

@patrycjakalinska patrycjakalinska commented Apr 15, 2025

Cherry pick of #7386
This PR updates the parseBoxShadowString function to handle boxShadow strings with missing optional arguments (blurRadius, spreadDistance, color).

It now gracefully handles input like:

  • 10px 10px white (defaults blurRadius and spreadDistance to 0px)

  • 10px 10px 5px white (defaults spreadDistance to 0px)

  • 10px 10px (defaults remaining values, uses black as color)

The default happen on Native side where RN process it and defaults the missing values.

I've also added unit test with stripped string that make sure styles behave correctly.

I've also moved the string type check into the processBoxShadow.js file, since we want to support boxShadow values that are arrays of objects where individual properties can be strings with units. (The possibility to support this was already implemented but typeof newValue.boxShadow === 'string' prevented it from existing)

      boxShadow: [
       {
        // before that's how value had been provided
         offsetX: 10
         // now they can be provided also as strings with units
         offsetY: '4px',
         blurRadius,
         color,
       },
     ],

Test plan

Example Code
import React from 'react';
import { Pressable, Text, View } from 'react-native';
import Animated, {
  interpolate,
  interpolateColor,
  useAnimatedProps,
  useAnimatedStyle,
  useSharedValue,
} from 'react-native-reanimated';
import { DefaultStyle } from 'react-native-reanimated/lib/typescript/hook/commonTypes';

const AnimatedPressable = Animated.createAnimatedComponent(Pressable);

export default function EmptyExample() {
  const pressed = useSharedValue(0);

  const animatedBoxShadow = useAnimatedStyle(() => {
    const blurRadius = interpolate(pressed.value, [0, 1], [10, 0]);
    const color = interpolateColor(
      pressed.value,
      [0, 1],
      ['rgba(255, 0, 0, 1)', 'rgba(0, 0, 255, 1)']
    );

    return {
      boxShadow: `0px 4px ${blurRadius}px ${color}`,
    };
  });

  const handlePress = () => {
    pressed.value = pressed.value === 0 ? 1 : 0;
  };

  return (
    <View
      style={{
        padding: 24,
      }}>
      <AnimatedPressable
        testID={'pressable'}
        style={[
          animatedBoxShadow,
          {
            backgroundColor: 'red',
            padding: 16,
            boxShadow: '0px 4px 10px rgba(255, 0, 0, 1)',
          },
        ]}
        onPress={handlePress}>
        <Text>Button</Text>
      </AnimatedPressable>
    </View>
  );
}

Summary

Test plan

<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

This PR updates the `parseBoxShadowString` function to handle
`boxShadow` strings with missing optional arguments (`blurRadius`,
`spreadDistance`, `color`).

It now gracefully handles input like:

- `10px 10px white` (defaults `blurRadius` and `spreadDistance` to
`0px`)

- `10px 10px 5px white` (defaults `spreadDistance` to `0px`)

- `10px 10px` (defaults remaining values, uses black as color)

The default happen on Native side where RN process it and defaults the
missing values.

I've also added unit test with stripped string that make sure styles
behave correctly.

I've also moved the string type check into the `processBoxShadow.js`
file, since we want to support `boxShadow` values that are arrays of
objects where individual properties can be strings with units. (The
possibility to support this was already implemented but `typeof
newValue.boxShadow === 'string'` prevented it from existing)
 
 ```
       boxShadow: [
        {
         // before that's how value had been provided
          offsetX: 10
          // now they can be provided also as strings with units
          offsetY: '4px',
          blurRadius,
          color,
        },
      ],
 ```
 
 
 Possible TO-DO:
- [ ] Add additional warning for wrong color format (not sure if it's
needed as it doesn't break the app)

## Test plan

<details>
<summary>Example Code</summary>

```tsx
import React from 'react';
import { Pressable, Text, View } from 'react-native';
import Animated, {
  interpolate,
  interpolateColor,
  useAnimatedProps,
  useAnimatedStyle,
  useSharedValue,
} from 'react-native-reanimated';
import { DefaultStyle } from 'react-native-reanimated/lib/typescript/hook/commonTypes';

const AnimatedPressable = Animated.createAnimatedComponent(Pressable);

export default function EmptyExample() {
  const pressed = useSharedValue(0);

  const animatedBoxShadow = useAnimatedStyle(() => {
    const blurRadius = interpolate(pressed.value, [0, 1], [10, 0]);
    const color = interpolateColor(
      pressed.value,
      [0, 1],
      ['rgba(255, 0, 0, 1)', 'rgba(0, 0, 255, 1)']
    );

    return {
      boxShadow: `0px 4px ${blurRadius}px ${color}`,
    };
  });

  const handlePress = () => {
    pressed.value = pressed.value === 0 ? 1 : 0;
  };

  return (
    <View
      style={{
        padding: 24,
      }}>
      <AnimatedPressable
        testID={'pressable'}
        style={[
          animatedBoxShadow,
          {
            backgroundColor: 'red',
            padding: 16,
            boxShadow: '0px 4px 10px rgba(255, 0, 0, 1)',
          },
        ]}
        onPress={handlePress}>
        <Text>Button</Text>
      </AnimatedPressable>
    </View>
  );
}


```

</details>
@patrycjakalinska patrycjakalinska marked this pull request as ready for review April 15, 2025 13:22
Copy link
Member

@MatiPl01 MatiPl01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@MatiPl01 MatiPl01 merged commit 38356c2 into 3.17-stable Apr 15, 2025
32 of 40 checks passed
@MatiPl01 MatiPl01 deleted the @patrycjakalinska/backport-boxShadow-optional-arguments branch April 15, 2025 13:54
@MatiPl01 MatiPl01 mentioned this pull request Apr 16, 2025
MatiPl01 added a commit that referenced this pull request Apr 16, 2025
## Summary

Included fixes:
- #7376
- #7395
- #7394
- #7400


## Current state

|| Fabric (iOS) | Fabric (Android) | Paper (iOS) | Paper (Android) | Web
| MacOS | TVOS (iOS) | TVOS (android) |
|-|-|-|-|-|-|-|-|-|
| Builds           | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 
| Runs             | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants