Skip to content

Instantly share code, notes, and snippets.

@ottodevs
Created August 1, 2025 10:07
Show Gist options
  • Save ottodevs/34d93849d90207c993335e57e8b0acd2 to your computer and use it in GitHub Desktop.
Save ottodevs/34d93849d90207c993335e57e8b0acd2 to your computer and use it in GitHub Desktop.

Revisions

  1. ottodevs created this gist Aug 1, 2025.
    248 changes: 248 additions & 0 deletions expo-router-web-patches-guide.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,248 @@
    # πŸ› οΈ Fix shadow* and pointerEvents Warnings in Expo Router/Web

    > **Common Issue**: When using Expo Router with React Native Web, you encounter warnings about `shadow*` properties and `pointerEvents` props that aren't compatible with web environments.
    ## πŸ“‹ Problem Analysis

    This issue affects most Expo Router templates and React Navigation setups when targeting web platforms. The warnings occur because:

    1. **Shadow Properties**: React Native's `shadowColor`, `shadowOffset`, `shadowOpacity`, `shadowRadius` don't work on web - need `boxShadow*` equivalents
    2. **pointerEvents Props**: Web compatibility requires `pointerEvents` to be in `style` objects, not as direct props

    ## 🎯 Affected Packages & Versions

    | Package | Version | Files Affected |
    |---------|---------|----------------|
    | `expo-router` | `~5.1.4` | `build/views/Sitemap.js` |
    | `@react-navigation/elements` | `^2.6.1` | `lib/module/Screen.js`, `lib/module/Header/Header.js` |
    | `react-native-screens` | `~4.11.1` | `lib/commonjs/components/ScreenStackHeaderConfig.js` |

    ## πŸ”§ Solution Overview

    We'll use **Bun's native patch system** to fix these issues:

    1. Replace `shadow*` properties with `boxShadow*` equivalents
    2. Move `pointerEvents` props to `style` objects
    3. Apply patches automatically on install

    ## πŸ“¦ Step-by-Step Implementation

    ### 1. Install Dependencies (if needed)

    ```bash
    # No additional dependencies needed - Bun has native patching support
    ```

    ### 2. Apply Patches

    #### A. Fix Expo Router Shadow Properties

    ```bash
    bun patch expo-router
    ```

    **Edit**: `node_modules/expo-router/build/views/Sitemap.js`

    **Find** (around line 139):
    ```javascript
    shadowColor: '#000',
    shadowOffset: {
    width: 0,
    height: 3,
    },
    shadowOpacity: 0.33,
    shadowRadius: 3,
    ```

    **Replace with**:
    ```javascript
    boxShadowColor: '#000',
    boxShadowOffset: {
    width: 0,
    height: 3,
    },
    boxShadowOpacity: 0.33,
    boxShadowRadius: 3,
    ```

    **Commit**:
    ```bash
    bun patch --commit node_modules/expo-router
    ```

    #### B. Fix React Navigation pointerEvents

    ```bash
    bun patch @react-navigation/elements
    ```

    **Edit**: `node_modules/@react-navigation/elements/lib/module/Screen.js`

    **Find**:
    ```javascript
    children: /*#__PURE__*/_jsx(View, {
    pointerEvents: "box-none",
    onLayout: e => {
    // ...
    },
    style: [styles.header, headerTransparent ? styles.absolute : null],
    ```
    **Replace with**:
    ```javascript
    children: /*#__PURE__*/_jsx(View, {
    onLayout: e => {
    // ...
    },
    style: [{ pointerEvents: "box-none" }, styles.header, headerTransparent ? styles.absolute : null],
    ```
    **Edit**: `node_modules/@react-navigation/elements/lib/module/Header/Header.js`
    Apply similar fixes to **7 instances** of `pointerEvents` props, moving them all to style objects.
    **Commit**:
    ```bash
    bun patch --commit node_modules/@react-navigation/elements
    ```
    #### C. Fix React Native Screens
    ```bash
    bun patch react-native-screens
    ```
    **Edit**: `node_modules/react-native-screens/lib/commonjs/components/ScreenStackHeaderConfig.js`
    **Find**:
    ```javascript
    style: styles.headerConfig,
    pointerEvents: "box-none"
    ```
    **Replace with**:
    ```javascript
    style: [{ pointerEvents: "box-none" }, styles.headerConfig]
    ```
    **Commit**:
    ```bash
    bun patch --commit node_modules/react-native-screens
    ```
    ### 3. Verify Setup
    Your `package.json` should now include:
    ```json
    {
    "patchedDependencies": {
    "[email protected]": "patches/[email protected]",
    "@react-navigation/[email protected]": "patches/@react-navigation%[email protected]",
    "[email protected]": "patches/[email protected]"
    }
    }
    ```
    ### 4. Test Installation
    ```bash
    rm -rf node_modules && bun install
    ```
    ## πŸ“ Generated Patch Files
    The following patch files will be created in your `patches/` directory:
    ### `expo-router@5.1.4.patch`
    ```diff
    diff --git a/build/views/Sitemap.js b/build/views/Sitemap.js
    index a61428d..f6f2327 100644
    --- a/build/views/Sitemap.js
    +++ b/build/views/Sitemap.js
    @@ -136,13 +136,13 @@ const styles = react_native_1.StyleSheet.create({
    paddingVertical: 16,
    borderBottomWidth: 1,
    borderColor: '#313538',
    - shadowColor: '#000',
    - shadowOffset: {
    + boxShadowColor: '#000',
    + boxShadowOffset: {
    width: 0,
    height: 3,
    },
    - shadowOpacity: 0.33,
    - shadowRadius: 3,
    + boxShadowOpacity: 0.33,
    + boxShadowRadius: 3,
    elevation: 8,
    },
    headerContent: {
    ```
    ### `@react-navigation%2Felements@2.6.1.patch`
    Contains fixes for:
    - `Screen.js`: 1 pointerEvents fix
    - `Header/Header.js`: 7 pointerEvents fixes (including conditional logic)
    ### `react-native-screens@4.11.1.patch`
    ```diff
    diff --git a/lib/commonjs/components/ScreenStackHeaderConfig.js b/lib/commonjs/components/ScreenStackHeaderConfig.js
    index abc123..def456 100644
    --- a/lib/commonjs/components/ScreenStackHeaderConfig.js
    +++ b/lib/commonjs/components/ScreenStackHeaderConfig.js
    @@ -17,8 +17,7 @@ const ScreenStackHeaderConfig = exports.ScreenStackHeaderConfig = /*#__PURE__*/
    ref: ref,
    topInsetEnabled: _edgeToEdge.EDGE_TO_EDGE ? true : props.topInsetEnabled,
    - style: styles.headerConfig,
    - pointerEvents: "box-none"
    + style: [{ pointerEvents: "box-none" }, styles.headerConfig]
    })));
    ```
    ## βœ… Verification Commands
    After applying patches, verify fixes:
    ```bash
    # Check that no direct pointerEvents props remain (should return empty)
    grep -R 'pointerEvents: "' node_modules/@react-navigation/elements node_modules/react-native-screens | grep -v 'style.*pointerEvents'

    # Check that boxShadow* properties are applied
    grep -A5 -B5 'boxShadowColor' node_modules/expo-router/build/views/Sitemap.js
    ```
    ## πŸš€ Benefits
    - βœ… **Eliminates warnings** in web builds
    - βœ… **Automatic application** on every install
    - βœ… **Team consistency** via committed patches
    - βœ… **Minimal overhead** - only affects problematic files
    - βœ… **Future-proof** - patches persist across installs
    ## πŸ—οΈ Project Setup Requirements
    - **Bun** as package manager
    - **Expo Router** `~5.1.4`
    - **React Navigation** Elements `^2.6.1`
    - **React Native Screens** `~4.11.1`
    ## πŸ“ Notes
    - Patches are applied automatically during `bun install`
    - Commit the `patches/` directory to version control
    - If package versions change, patches may need updating
    - No additional dependencies required - uses Bun's native patching
    ## πŸ”— Related Issues
    This solution addresses common warnings in:
    - Expo Router web builds
    - React Navigation web compatibility
    - Next.js + React Native Web setups
    - Any template using these packages for web targets
    ---
    **✨ Created by**: Fixing common Expo Router/Web compatibility issues
    **πŸ”§ Tested with**: Bun 1.2.19, Expo SDK 53, React Native 0.80+