From e96041f0969e8d5ad40f177b8f570bc9d4016559 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Tue, 3 Nov 2026 22:15:40 +0000 Subject: [PATCH] Document the gesture area's trigger-x, trigger-y and @trigger A Swipe to reply section on the gesture area page, the props and the event, how a trigger shares touches, a link from Gestures & Animation, and the gesture helpers on the test harness, trigger() among them. Co-Authored-By: Claude Opus 5.5 --- .../docs/mobile/4/digging-deeper/gestures.md | 4 +- .../mobile/4/edge-components/gesture-area.md | 78 ++++++++++++++++++- .../docs/mobile/4/testing/interactions.md | 22 ++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/resources/views/docs/mobile/4/digging-deeper/gestures.md b/resources/views/docs/mobile/4/digging-deeper/gestures.md index 847b521b..27db8e24 100644 --- a/resources/views/docs/mobile/4/digging-deeper/gestures.md +++ b/resources/views/docs/mobile/4/digging-deeper/gestures.md @@ -36,7 +36,9 @@ As the user drags, `$drag` updates on the UI thread and the bound props follow i and shrinks together, with no PHP involved during the gesture. To have a drag settle on set points when the finger lifts, like a row that slides aside to show its actions, give the -gesture area [snap points](../edge-components/gesture-area#swipe-to-reveal). +gesture area [snap points](../edge-components/gesture-area#swipe-to-reveal). To have it do something when you let +it go far enough, like a message that slides sideways to reply, give it a +[trigger](../edge-components/gesture-area#swipe-to-reply). ### Formulas diff --git a/resources/views/docs/mobile/4/edge-components/gesture-area.md b/resources/views/docs/mobile/4/edge-components/gesture-area.md index e8aa3b03..cde5e0ef 100644 --- a/resources/views/docs/mobile/4/edge-components/gesture-area.md +++ b/resources/views/docs/mobile/4/edge-components/gesture-area.md @@ -42,6 +42,9 @@ screen in your app and drag the card. - `snap-x` / `snap-y` - The points a bound pan settles on when the finger lifts (optional), as an array of numbers or a comma-separated string. Give at least two. See [Swipe to reveal](#swipe-to-reveal). +- `trigger-x` / `trigger-y` - How far a bound pan has to go for letting go to call + `@trigger` (optional, float). The sign is the direction, so `-64` is 64 points to the left. It takes the place of + snap points on that axis. See [Swipe to reply](#swipe-to-reply). - `swipe-fingers` - How many fingers a `@swipe` needs (optional, integer, default `1`). + +## Swipe to reply + + + +With `trigger-x` (or `trigger-y`), a bound pan does something when you let it go far enough, the way a message in a +chat app slides sideways to reply: + +- The content follows the finger the trigger's way as far as the trigger point. Past it, it moves a third as far as + the finger does. It doesn't move the other way at all. +- Each time the pull goes past the point, the phone plays a light haptic. Coming back under it plays nothing. +- When the finger lifts, the content springs back to rest. If it was past the point, `@trigger` is called. + +Here a message slides left, and a Reply icon beside it grows, turns upright and fades in as it goes. Both read the +same shared value, so the icon is in place when the haptic plays: + +@verbatim +```blade static +@php + $shown = $pull->interpolate([-64, 0], [1, 0]); + $turn = $pull->interpolate([-64, 0], [0, 90]); +@endphp + + + + + {{ $message->body }} + + + + + + + +``` +@endverbatim + +PHP has nothing to do while the finger moves or when it lifts, because the message always springs back by itself. +`reply()` only runs when the pull went far enough: + +```php +use Native\Mobile\Edge\SharedValue; + +public ?SharedValue $pull = null; + +public ?int $replyingTo = null; + +public function mount(): void +{ + $this->pull = SharedValue::make(); +} + +public function reply(int $id): void +{ + $this->replyingTo = $id; +} +``` + +The pull only starts when the finger heads the trigger's way. Here that's left, so a drag up or down still scrolls +the thread, and on iOS 26 a drag to the right still goes back. + + diff --git a/resources/views/docs/mobile/4/testing/interactions.md b/resources/views/docs/mobile/4/testing/interactions.md index 6eab8d36..fdaa8ff9 100644 --- a/resources/views/docs/mobile/4/testing/interactions.md +++ b/resources/views/docs/mobile/4/testing/interactions.md @@ -126,6 +126,28 @@ Native::test(Tasks::class) ->press('deleteTask(1)'); // swipe-to-delete arrives as a press ``` +### Gestures + +A [gesture area](../edge-components/gesture-area)'s callbacks fire with what the device would send when the gesture +ends: + +- `dragEnd($target, $x, $y = 0.0)` — finish a drag at a translation, for `@dragEnd`. +- `pinch($target, $scale)` — finish a pinch at a scale, for `@pinchEnd`. +- `swipe($target, $direction = 'left')` — swipe `left`, `right`, `up` or `down`, for `@swipe`. +- `trigger($target)` — let a pull go past its trigger point, for `@trigger`. + +@verbatim +```blade static + +``` +@endverbatim + +```php +Native::test(Thread::class) + ->trigger('swipe-5') + ->assertSet('replyingTo', 5); +``` + ## Setting properties and calling methods Two lower-level tools reach the component directly.