Repository navigation
ReanimatedSwipeable: action panes are visible at rest when the row content is not fully opaque (follow-up to #4271) #4617
Description
Environment
- react-native-gesture-handler 3.3.0 (main 8665cd1 behaves the same)
- React Native 0.88.0, Expo SDK 58, New Architecture
- iOS 27, Android 17 emulator
Description
Since #4271 the left and right action containers (absoluteFill, absolutely positioned behind the row) are no longer hidden when showLeftProgress / showRightProgress is 0; only pointerEvents is toggled (src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx:432, :465). Visibility now depends entirely on the row child covering them.
If the row child is translucent (for example a 35 % opaque track or a glass-style background), both the left and right action contents show through the row while it is closed. In 2.32 the containers had opacity: show*Progress.value === 0 ? 0 : 1, so this did not happen.
Reproduction
ReanimatedSwipeablewith bothrenderLeftActionsandrenderRightActions(e.g. a coloured "Approve" and "Dismiss" view).- Row child with a semi-transparent background (
rgba(...), alpha about 0.35). - At rest, with no gesture, both action contents are drawn behind/through the row.
Root cause
The opacity toggle was removed in #4271 because it flips on exact progress === 0, which hid the actions mid-way through a fast close (#3897). Nothing replaced it for the not-fully-opaque case.
Proposed fix
Hide each container unless the row is actually displaced towards it, keyed on appliedTranslation rather than on the progress value (the left actions are revealed by a positive translation, showLeftProgress = interpolate(appliedTranslation, [-1, 0, leftWidth], [0, 0, 1])):
--- a/packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx
+++ b/packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx
@@ leftActionAnimation
pointerEvents: showLeftProgress.value === 0 ? 'none' : 'auto',
+ opacity: appliedTranslation.value > 0 ? 1 : 0,
@@ rightActionAnimation
pointerEvents: showRightProgress.value === 0 ? 'none' : 'auto',
+ opacity: appliedTranslation.value < 0 ? 1 : 0,Why not the 2.32 expression (opacity: show*Progress.value === 0 ? 0 : 1): that is what #4271 removed, because the progress can reach 0 (showLeftProgress.value = 0 in the close path) while the row is still sliding home, so the actions vanished mid-way through a fast close (#3897). The translation only reaches 0 when the row is actually back at rest, so a closing row keeps its pane visible until it is covered. It also keeps the opposite pane hidden during a swipe, which matters for the same translucent-row case (while swiping right, the right pane would otherwise show through the row).
We carry this as a local patch against 3.3.0; our swipe tests (which drive the real component) pass with it. We have not re-run the exact #3897 fast-close scenario on a device. Happy to open a PR if this direction suits you.
Disclosure: drafted with AI assistance (Claude) from a patch we carry locally; code references were checked against the published package sources. Happy to clarify or open a PR.
Activity
github-actions commentedon Oct 19, 2026
Hey @fregster! 👋
Some of the required information in this issue is missing, incomplete or invalid. Could you take another look at the template and make sure each of these is filled in with something we can act on?
package.jsonor lockfilepackage.jsonor lockfileOnce the issue is updated we will take another look. Thanks!
github-actions commentedon Oct 19, 2026
Hey @fregster! 👋
The issue doesn't seem to contain a minimal reproduction.
Could you provide a snack, a gist or a link to a GitHub repository that reproduces the problem?
chocky335 commentedon Oct 19, 2026
The fix is in #4618, together with #4616. Each action pane is hidden unless the row translation moves toward it. The panes stay hidden at rest, and the #3897 fast close keeps working.
m-bert commentedon Oct 20, 2026
Hi @fregster! Thank you for reporting this issue!
Thank you @chocky335 for the PR. I don't think the opacity toggle is the right approach, though. The actions still show through the translucent row while it moves, and popping into view on the first pixel of movement looks odd.
Handling this does not require changes in the library.
renderLeftActions/renderRightActionsreceive the row translation as a shared value, so the app can decide how its actions appear. Below you can find two examples of how to tackle this:SlidingPanekeeps the action attached to the row edge, so it slides in with the row and is never drawn under it.FadingPanefades the action in with the reveal. It is hidden at rest, but still shows through the row while opening.Let me know what you think about it @fregster @chocky335.
Example of translucent Swipeable components:
chocky335 commentedon Oct 20, 2026
Thanks, that makes sense. The translation shared value gives the app what it needs, and your
SlidingPaneexample also avoids the pop-in that my opacity toggle had. I removed that part from #4618. If it helps, your two examples would fit theReanimatedSwipeabledocs page.m-bert commentedon Oct 21, 2026
@chocky335 I've slightly changed the example in the #4625, do you think it's better now? Also, I don't think
FadingPaneis necessary as translucent Swipeables are not that common. But if you think otherwise then let me know 😅chocky335 commentedon Oct 21, 2026
Yes, this is better, and I agree that
FadingPaneis not needed. Thanks for picking it up.m-bert commentedon Oct 21, 2026
Thanks for confirmation! In that case I'm closing this issue.