[Android] Add hover callbacks to Touchable - #4396
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughChangesButton hover support now tracks Android pointer samples, dispatches Button hover events
Sequence Diagram(s)sequenceDiagram
participant Pointer
participant ButtonViewGroup
participant NativeEvent
participant Touchable
Pointer->>ButtonViewGroup: Sends hover MotionEvent
ButtonViewGroup->>NativeEvent: Creates ButtonEvent with HoverSample
NativeEvent->>Touchable: Invokes onButtonHoverIn or onButtonHoverOut
Touchable->>Touchable: Calls onHoverIn or onHoverOut with nativeEvent
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt`:
- Around line 881-886: Guard the hover-state update in the
hoverActiveAtPressStart path so press events only update isHovered,
lastHoverSample, and dispatchHoverEventIfNeeded when the event’s tool type
matches lastHoverSample.pointerType. Ignore mismatched pointer types, preserving
the active stylus or mouse hover session.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 020237d9-5a9d-4017-8f02-a4c16e47ada3
📒 Files selected for processing (10)
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.ktpackages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/Extensions.ktpackages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.ktpackages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/events/RNGestureHandlerButtonEvent.ktpackages/react-native-gesture-handler/src/__tests__/api_v3.test.tsxpackages/react-native-gesture-handler/src/components/GestureHandlerButton.tsxpackages/react-native-gesture-handler/src/specs/RNGestureHandlerButtonNativeComponent.tspackages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.tspackages/react-native-gesture-handler/src/v3/components/Touchable/Touchable.tsxpackages/react-native-gesture-handler/src/v3/components/Touchable/TouchableProps.ts
There was a problem hiding this comment.
Pull request overview
Adds JS-visible hover callbacks to the v3 Touchable by introducing new native direct events (onButtonHoverIn/onButtonHoverOut) and wiring them through to Touchable props (onHoverIn/onHoverOut), primarily via Android-native hover tracking.
Changes:
- Expose
TouchableonHoverIn/onHoverOutprops and forward them toGestureHandlerButtonasonButtonHoverIn/onButtonHoverOut. - Add Android-side hover event dispatch with a snapshotted hover sample payload and lifecycle handling (including enabled/disabled transitions).
- Extend codegen spec + event plumbing and add a Jest test asserting correct payload unwrapping/forwarding.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/v3/components/Touchable/TouchableProps.ts | Adds public onHoverIn/onHoverOut props and updates omitted native interaction prop set. |
| packages/react-native-gesture-handler/src/v3/components/Touchable/Touchable.tsx | Forwards hover callbacks to GestureHandlerButton via memoized internal handlers. |
| packages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.ts | Omits hover direct events from deprecated button raw props surface. |
| packages/react-native-gesture-handler/src/specs/RNGestureHandlerButtonNativeComponent.ts | Adds new direct event handlers to the native component spec. |
| packages/react-native-gesture-handler/src/components/GestureHandlerButton.tsx | Extends ButtonProps interface with onButtonHoverIn/onButtonHoverOut. |
| packages/react-native-gesture-handler/src/tests/api_v3.test.tsx | Adds test verifying Touchable hover callbacks receive unwrapped native payload. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt | Implements Android hover state tracking and dispatches hover in/out direct events. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/Extensions.kt | Adds Context?.findActivity() helper used for window offset capture. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/events/RNGestureHandlerButtonEvent.kt | Adds hover event name mapping and an event factory for hover samples. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt | Reuses the new findActivity() helper for window offset resolution. |
Suppressed comments (1)
packages/react-native-gesture-handler/src/v3/components/Touchable/TouchableProps.ts:121
onHoverOutis now part of the publicTouchableAPI, but hover direct events are only dispatched on Android (iOS/web currently won’t invoke this callback). Please clarify the platform support in the JSDoc to prevent consumers from assuming it works everywhere.
/**
* Called when a non-touch pointer stops hovering over the component.
*/
onHoverOut?: ((event: ButtonEvent) => void) | undefined;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
0f1e612 to
6d22aa9
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
6d22aa9 to
6d06663
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt`:
- Around line 1081-1082: Preserve the serialized pointer-type integer contract
by assigning matching explicit values for KEY and OTHER in GestureHandler.kt,
RNGestureHandlerPointerType.h, and src/v3/types/EventTypes.ts; ensure KEY
remains 3 and OTHER remains 4 across all three definitions so legacy and
replayed events decode consistently.
- Around line 1081-1082: Update the pointer type constants so POINTER_TYPE_OTHER
retains its existing numeric value of 3, and assign POINTER_TYPE_KEY a distinct
value instead. Preserve compatibility for native paths interpreting the
established POINTER_TYPE_OTHER value.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c40833e5-4b18-44e7-a4cc-3c34a950e426
📒 Files selected for processing (3)
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.ktpackages/react-native-gesture-handler/apple/RNGestureHandlerPointerType.hpackages/react-native-gesture-handler/src/v3/types/EventTypes.ts
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt`:
- Around line 1081-1082: Preserve the serialized pointer-type integer contract
by assigning matching explicit values for KEY and OTHER in GestureHandler.kt,
RNGestureHandlerPointerType.h, and src/v3/types/EventTypes.ts; ensure KEY
remains 3 and OTHER remains 4 across all three definitions so legacy and
replayed events decode consistently.
- Around line 1081-1082: Update the pointer type constants so POINTER_TYPE_OTHER
retains its existing numeric value of 3, and assign POINTER_TYPE_KEY a distinct
value instead. Preserve compatibility for native paths interpreting the
established POINTER_TYPE_OTHER value.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: c40833e5-4b18-44e7-a4cc-3c34a950e426
📒 Files selected for processing (3)
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.ktpackages/react-native-gesture-handler/apple/RNGestureHandlerPointerType.hpackages/react-native-gesture-handler/src/v3/types/EventTypes.ts
🛑 Comments failed to post (1)
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt (1)
1081-1082: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail rg -n -C 3 \ 'POINTER_TYPE_(KEY|OTHER)|RNGestureHandler(Key|OtherPointer)|PointerType\.(KEY|OTHER)|pointerType\s*(===|!==|==|!=)' \ packages/react-native-gesture-handlerRepository: software-mansion/react-native-gesture-handler
Length of output: 15138
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "Android pointer type constants and mappings:" sed -n '880,1083p' packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt echo echo "Apple pointer type header:" cat -n packages/react-native-gesture-handler/apple/RNGestureHandlerPointerType.h echo echo "EventTypes pointer type definition:" sed -n '1,35p' packages/react-native-gesture-handler/src/v3/types/EventTypes.ts echo echo "Read-only semantic check of enum value ordering/mappings:" python3 - <<'PY' from pathlib import Path import re android = Path('packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt').read_text() apple = Path(' packages/react-native-gesture-handler/apple/RNGestureHandlerPointerType.h').read_text() if Path(' packages/react-native-gesture-handler/apple/RNGestureHandlerPointerType.h').exists() else Path('packages/react-native-gesture-handler/apple/RNGestureHandlerPointerType.h').read_text() event = Path('packages/react-native-gesture-handler/src/v3/types/EventTypes.ts').read_text() def ints(s): return list(map(str.strip, s.splitlines())) android_consts = re.findall(r'const val POINTER_TYPE_(KEY|OTHER|TOUCH|STYLUS|MOUSE)\s*=\s*(\d+)', android) apple_consts = re.findall(r'RNGestureHandler(KEY|OtherPointer|Touch|Stylus|Mouse)\s*,?\s*$', apple, re.M) event_type = re.search(r'enum\s+PointerType\s*{(?P<body>.*?)\n}', event, re.S) print("android_consts", android_consts) print("apple_consts", apple_consts) if event_type: body = event_type.group('body').strip() print("event_types", re.findall(r'([A-Z_]+)\s*(?:=\s*(\d+))?(?:,|$)?', body, re.M)) else: print("event_types missing enum") print("\nAndroid OTHER equals 3?", any(name == 'OTHER' and value == '3' for name, value in android_consts)) print("Apple OtherPointer equals 3?", any(name == 'OtherPointer' for name in apple_consts) and apple_consts.index('OtherPointer') == 3) print("Apple Key equals 4?", any(name == 'KEY' for name in apple_consts) and apple_consts.index('KEY') == 3) PYRepository: software-mansion/react-native-gesture-handler
Length of output: 10129
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "PointerType files:" fd -a 'PointerType\.(ts|tsx|js|jsx|mm|m|h)$' packages/react-native-gesture-handler echo echo "PointerType.ts full:" cat -n packages/react-native-gesture-handler/src/PointerType.ts 2>/dev/null || true echo echo "Android PointerType-related text:" rg -n -C 3 'POINTER_TYPE_(TOUCH|STYLUS|MOUSE|KEY|OTHER)|setPointerType|pointerType|ReadableType\.INT|putInt|pointerTypeOf' packages/react-native-gesture-handler/android/src/main/java echo echo "Apple Raw pointer type related text:" rg -n -C 3 'RNGestureHandlerPointerType|RNGestureHandler(Key|OtherPointer)|pointerType|rht_pointer_type|`@dtoa`|putInt|setPointer' packages/react-native-gesture-handler/appleRepository: software-mansion/react-native-gesture-handler
Length of output: 50401
Preserve the existing pointer-type integer contract
These pointer types are serialized as integers across the shared enum, Apple native enum, and Android constants. With
KEYat 3 andOTHERat 4,OldPointer/replayedOTHERevents read as 3 map toKEY, andKEYevents read by older consumers map asOTHER. Keep explicit compatibility values between the Android constants, Apple enum, and sharedPointerType.📍 Affects 3 files
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt#L1081-L1082(this comment)packages/react-native-gesture-handler/apple/RNGestureHandlerPointerType.h#L7-L7packages/react-native-gesture-handler/src/v3/types/EventTypes.ts#L19-L19🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt` around lines 1081 - 1082, Preserve the serialized pointer-type integer contract by assigning matching explicit values for KEY and OTHER in GestureHandler.kt, RNGestureHandlerPointerType.h, and src/v3/types/EventTypes.ts; ensure KEY remains 3 and OTHER remains 4 across all three definitions so legacy and replayed events decode consistently.Source: Coding guidelines
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "Files matching GestureHandler.kt:" fd -a 'GestureHandler\.kt$' . || true echo echo "Relevant const values and nearby events:" file="packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt" if [ -f "$file" ]; then nl -ba "$file" sed -n '1050,1125p' else echo "GestureHandler.kt not found at expected path" fi echo echo "Search for POINTER_TYPE constants/usages:" rg -n "POINTER_TYPE_(KEY|OTHER|TOUCH|PEN)|POINTER_TYPE_KEY|POINTER_TYPE_OTHER" packages/react-native-gesture-handler -S || true echo echo "Deduce git diff context for these constants if available:" git diff -- packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt | sed -n '1,220p' || trueRepository: software-mansion/react-native-gesture-handler
Length of output: 1664
🏁 Script executed:
#!/bin/bash set -euo pipefail file="packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt" echo "File size and target lines:" wc -l "$file" python3 - <<'PY' "$file" import sys path=sys.argv[1] for i,l in enumerate(open(path), 1): if 1060 <= i <= 1110: print(f"{i:5d}\t{l.rstrip()}") PY echo echo "Relevant const values and usages:" python3 - <<'PY' "$file" import re path=sys.argv[1] for i,l in enumerate(open(path), 1): if re.search(r'POINTER_TYPE_(KEY|OTHER|TOUCH|PEN|TOUCH)', l) or 'KEY' in l or 'OTHER' in l: print(f"{i:5d}\t{l.rstrip()}") PY echo echo "Search outside target file: POINTER_TYPE constants/usages:" rg -n "POINTER_TYPE_(KEY|OTHER|TOUCH|PEN)|POINTER_TYPE_KEY|POINTER_TYPE_OTHER" packages/react-native-gesture-handler -S || true echo echo "Git diff around target file if available:" git diff -- packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt | sed -n '1,260p' || trueRepository: software-mansion/react-native-gesture-handler
Length of output: 2867
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "Relevant POINTER_TYPE usages:" python3 - <<'PY' for p in ["packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt"]: with open(p, encoding="utf-8") as f: for i, line in enumerate(f, 1): if "POINTER_TYPE_" in line: print(f"{p}:{i}: {line.rstrip()}") PY echo echo "Search all repository POINTER_TYPE references:" rg -n "POINTER_TYPE_(KEY|OTHER|TOUCH|STYLUS|MOUSE|PEN)|POINTER_TYPE_KEY|POINTER_TYPE_OTHER" packages/react-native-gesture-handler -S || true echo echo "Search TypeScript/native mapping references for pointer type names/numbers:" rg -n 'pointerType|pointer.*type|POINTER_TYPE|TYPE_OTHER|TYPE_KEY|OTHER|KEY' packages/react-native-gesture-handler -S \ -g '!android/build' -g '!ios' -g '!apple' -g '!build' -g '!dist' -g '!node_modules' || trueRepository: software-mansion/react-native-gesture-handler
Length of output: 45286
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "PointerType.ts:" cat -n packages/react-native-gesture-handler/src/PointerType.ts echo echo "TypeScript NativeComponent/spec pointerType code around PointerType.ts:" python3 - <<'PY' import re, pathlib for p in [ "packages/react-native-gesture-handler/src/specs/RNGestureHandlerButtonNativeComponent.ts", "packages/react-native-gesture-handler/src/specs/RNGestureHandlerDetectorNativeComponent.ts", "packages/react-native-gesture-handler/src/v3/types/EventTypes.ts", "packages/react-native-gesture-handler/src/handlers/gestureHandlerCommon.ts", ]: path=pathlib.Path(p) if not path.exists(): print(f"{p} missing") continue lines=path.read_text().splitlines() for i,l in enumerate(lines,1): if "pointerType" in l or "PointerType" in l: print(f"{p}:{i}: {l}") echo echo "Apple/native pointerType definitions and native mappings:" rg -n "POINTER_TYPE_(KEY|OTHER|TOUCH|STYLUS|MOUSE|PEN)|pointerType:|PointerType::|PointerProperties|TOOL_TYPE" packages/react-native-gesture-handler/apple packages/react-native-gesture-handler/android -S || trueRepository: software-mansion/react-native-gesture-handler
Length of output: 614
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "TypeScript PointerType enum:" cat -n packages/react-native-gesture-handler/src/PointerType.ts echo echo "Pointer type references in native/spec/type files:" python3 <<'PY' import pathlib patterns = ["native", "specs", "EventTypes", "PointerType", "pointerType"] files = [ pathlib.Path("packages/react-native-gesture-handler/src/PointerType.ts"), pathlib.Path("packages/react-native-gesture-handler/src/specs/RNGestureHandlerButtonNativeComponent.ts"), pathlib.Path("packages/react-native-gesture-handler/src/specs/RNGestureHandlerDetectorNativeComponent.ts"), pathlib.Path("packages/react-native-gesture-handler/src/v3/types/EventTypes.ts"), pathlib.Path("packages/react-native-gesture-handler/src/handlers/gestureHandlerCommon.ts"), ] for path in files: print(f"\n--- {path} ---") if not path.exists(): print("missing") continue for i, line in enumerate(path.read_text().splitlines(), 1): if any(s in line for s in patterns): print(f"{i}: {line}") print("\nApple native pointer type references:") rg -n "POINTER_TYPE_(KEY|OTHER|TOUCH|STYLUS|MOUSE|PEN)|pointerType:|PointerType::|PointerProperties|TOOL_TYPE|TOOL_TYPE_KEY|KEY" packages/react-native-gesture-handler/apple packages/react-native-gesture-handler/android -S || trueRepository: software-mansion/react-native-gesture-handler
Length of output: 772
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "Apple native pointer type references:" rg -n "POINTER_TYPE_(KEY|OTHER|TOUCH|STYLUS|MOUSE|PEN)|pointerType:|PointerType::|PointerProperties|TOOL_TYPE|TOOL_TYPE_KEY|KEY|OTHER" packages/react-native-gesture-handler/apple packages/react-native-gesture-handler/android -S || trueRepository: software-mansion/react-native-gesture-handler
Length of output: 35424
Preserve the existing numeric value for
POINTER_TYPE_OTHER.
POINTER_TYPE_OTHERmoved from3to4, whilePOINTER_TYPE_KEYnow uses3; makePOINTER_TYPE_OTHERretain3so older native paths interpreting numeric pointer types do not map new key events asOTHER.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt` around lines 1081 - 1082, Update the pointer type constants so POINTER_TYPE_OTHER retains its existing numeric value of 3, and assign POINTER_TYPE_KEY a distinct value instead. Preserve compatibility for native paths interpreting the established POINTER_TYPE_OTHER value.
6d06663 to
0627f6e
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/Extensions.kt`:
- Around line 35-43: Update the tool-type mapping in MotionEvent.getPointerType
so MotionEvent.TOOL_TYPE_ERASER shares the stylus branch and returns
GestureHandler.POINTER_TYPE_STYLUS, including inverted-stylus hover events;
leave other mappings unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 107a82c6-de60-49f5-8a80-ac7a7fe175a8
📒 Files selected for processing (4)
packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.ktpackages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/Extensions.ktpackages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.ktpackages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/react-native-gesture-handler/src/v3/components/GestureButtonsProps.ts
- packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt
0627f6e to
9f98e34
Compare
## Description
`Touchable` gains `onHoverIn`/`onHoverOut`, reported for a mouse,
trackpad cursor or hovering stylus. The button already tracked hover to
drive its animation — this exposes it to JS as the new
`onButtonHoverIn`/`onButtonHoverOut` direct events, omitted from
`RawButtonProps` since the deprecated buttons never report hover.
- Reporting follows `isHovered && isEnabled`, the same expression that
drives the hover visual, so disabling a hovered button reports a
hover-out and re-enabling it with the pointer still inside reports a
hover-in.
- No hover events arrive while the button is held, so the transitions
are derived from the touch stream during a press — gated so a press can
only maintain a hover that was already open, never open one. The pointer
type carries over from the previous sample, since those events belong to
the pressing pointer.
- The payload is snapshotted when the pointer is seen, because the
events outlive the `MotionEvent` behind them.
## Test plan
`yarn test` covers the prop forwarding; hover itself needs a device or
emulator with a mouse, trackpad or stylus.
<details>
<summary>Example code</summary>
```tsx
import React, { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import {
GestureHandlerRootView,
Touchable,
} from 'react-native-gesture-handler';
export default function Example() {
const [log, setLog] = useState<string[]>([]);
const callbacks = (source: string) => ({
onHoverIn: () => setLog((l) => [`${source} onHoverIn`, ...l]),
onHoverOut: () => setLog((l) => [`${source} onHoverOut`, ...l]),
onPressIn: () => setLog((l) => [`${source} onPressIn`, ...l]),
onPressOut: () => setLog((l) => [`${source} onPressOut`, ...l]),
});
return (
<GestureHandlerRootView style={styles.container}>
<View style={styles.row}>
<Touchable style={styles.box} {...callbacks('Touchable')}>
<Text style={styles.text}>Touchable</Text>
</Touchable>
<Pressable style={styles.box} {...callbacks('Pressable')}>
<Text style={styles.text}>Pressable</Text>
</Pressable>
</View>
{log.slice(0, 12).map((entry, i) => (
<Text key={i}>{entry}</Text>
))}
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 24 },
row: { flexDirection: 'row', gap: 24, marginBottom: 24 },
box: {
width: 120,
height: 120,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#6941C6',
},
text: { color: 'white' },
});
```
</details>
9f98e34 to
7c6aa7b
Compare
Description
TouchablegainsonHoverIn/onHoverOut, reported for a mouse,trackpad cursor or hovering stylus. The button already tracked hover to
drive its animation — this exposes it to JS as the new
onButtonHoverIn/onButtonHoverOutdirect events, omitted fromRawButtonPropssince the deprecated buttons never report hover.isHovered && isEnabled, the same expression thatdrives the hover visual, so disabling a hovered button reports a
hover-out and re-enabling it with the pointer still inside reports a
hover-in.
are derived from the touch stream during a press — gated so a press can
only maintain a hover that was already open, never open one. The pointer
type carries over from the previous sample, since those events belong to
the pressing pointer.
events outlive the
MotionEventbehind them.Test plan
yarn testcovers the prop forwarding; hover itself needs a device oremulator with a mouse, trackpad or stylus.
Example code