Skip to content

Commit c8daf9a

Browse files
committed
Migrate the Turbo Native helpers to Hotwire Native
The previous helpers are still working, but were deprecated and should be removed on the next major release
1 parent 42d2269 commit c8daf9a

31 files changed

+475
-304
lines changed

config/turbo-laravel.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
|
5959
*/
6060
'features' => [
61-
Features::turboNativeRoutes(),
61+
Features::hotwireNativeRoutes(),
6262
],
6363

6464
/*

docs/csrf.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ Since Turbo.js intercepts form submissions and converts those to fetch requests
2020

2121
With that being said, you may still want to use the `@csrf` Blade directive if you want to support users with JavaScript disabled, since the forms will still work if they contain the CSRF token.
2222

23-
[Continue to Turbo Native...](/docs/{{version}}/turbo-native)
23+
[Continue to Hotwire Native...](/docs/{{version}}/hotwire-native)

docs/helpers.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,11 @@ if (request()->wasFromTurboFrame(dom_id($post, 'create_comment'))) {
241241
}
242242
```
243243

244-
### The `request()->wasFromTurboNative()` macro
244+
### The `request()->wasFromHotwireNative()` macro
245245

246-
The `request()->wasFromTurboNative()` macro added to the request class will check if the request came from a Turbo Native client and returns `true` or `false` accordingly.
246+
The `request()->wasFromHotwireNative()` macro added to the request class will check if the request came from a Hotwire Native client and returns `true` or `false` accordingly.
247247

248-
Turbo Native clients are encouraged to override the `User-Agent` header in the WebViews to mention the words `Turbo Native` on them. This is what this macro uses to detect if it came from a Turbo Native client.
248+
Hotwire Native clients are encouraged to override the `User-Agent` header in the WebViews to mention the words `Hotwire Native` on them. This is what this macro uses to detect if it came from a Hotwire Native client.
249249

250250
### The `response()->turboStream()` macro
251251

docs/hotwire-native.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Hotwire Native
2+
3+
[TOC]
4+
5+
## Introduction
6+
7+
Hotwire also has a [mobile side](https://native.hotwired.dev/) and Turbo Laravel provides some helpers to help integrating with that.
8+
9+
Turbo visits made by a Hotwire Native client should send a custom `User-Agent` header. Using that header, we can detect in the backend that a request is coming from a Hotwire Native client instead of a regular web browser.
10+
11+
This is useful if you want to customize the behavior a little bit different based on that information. For instance,
12+
you may want to include some elements for mobile users, like a mobile-only CSS file include, for instance. To do that, you may use the `@hotwirenative` Blade directive in your Blade views:
13+
14+
```blade
15+
@hotwirenative
16+
<link rel="stylesheet" href="mobile.css">
17+
@endhotwirenative
18+
```
19+
20+
Alternatively, you may want to include some elements only if the client requesting it is _NOT_ a Hotwire Native client using the `@unlesshotwirenative` Blade helpers:
21+
22+
```blade
23+
@unlesshotwirenative
24+
<h1>Hello, Non-Hotwire Native Users!</h1>
25+
@endunlesshotwirenative
26+
```
27+
28+
You may also check if the request was made from a Hotwire Native visit using the request macro:
29+
30+
```php
31+
if (request()->wasFromHotwireNative()) {
32+
// ...
33+
}
34+
```
35+
36+
Or the Turbo Facade directly, like so:
37+
38+
```php
39+
use HotwiredLaravel\TurboLaravel\Facades\Turbo;
40+
41+
if (Turbo::isHotwireNativeVisit()) {
42+
// ...
43+
}
44+
```
45+
46+
## Interacting With Hotwire Native Navigation
47+
48+
Hotwire Native will hook into Turbo's visits so it displays them on mobile mimicking the mobile way of stacking screens instead of just replace elements on the same screen. This helps the native feel of our hybrid app.
49+
50+
However, sometimes we may need to customize the behavior of form request handler to avoid a weird screen jumping effect happening on the mobile client. Instead of regular redirects, we can send some signals by redirecting to specific routes that are detected by the Hotwire Native client.
51+
52+
For instance, if a form submission request came from a Hotwire Native client, the form was probably rendered on a native modal, which is not part of the screen stack, so we can just tell Turbo to `refresh` the current screen it has on stack instead. There are 3 signals we can send to the Hotwire Native client:
53+
54+
| Signal | Route| Description|
55+
|---|---|---|
56+
| `recede` | `/recede_historical_location` | Go back to previous screen |
57+
| `resume` | `/resume_historical_location` | Stay on the current screen as is |
58+
| `refresh`| `/refresh_historical_location` | Stay on the current screen but refresh |
59+
60+
Sending these signals is a matter of detecting if the request came from a Hotwire Native client and, if so, redirect the user to these signal URLs instead. The Hotwire Native client should detect the redirect was from one of these special routes and trigger the desired behavior.
61+
62+
You may use the `InteractsWithHotwireNativeNavigation` trait on your controllers to achieve this behavior and fallback to a regular redirect if the request wasn't from a Hotwire Native client:
63+
64+
```php
65+
use HotwiredLaravel\TurboLaravel\Http\Controllers\Concerns\InteractsWithHotwireNativeNavigation;
66+
67+
class TraysController extends Controller
68+
{
69+
use InteractsWithHotwireNativeNavigation;
70+
71+
public function store()
72+
{
73+
// Tray creation...
74+
75+
return $this->recedeOrRedirectTo(route('trays.show', $tray));
76+
}
77+
}
78+
```
79+
80+
In this example, when the request to create trays comes from a Hotwire Native client, we're going to redirect to the `/recede_historical_location` URL instead of the `trays.show` route. However, if the request was made from your web app, we're going to redirect the client to the `trays.show` route.
81+
82+
There are a couple of redirect helpers available:
83+
84+
```php
85+
$this->recedeOrRedirectTo(string $url);
86+
$this->resumeOrRedirectTo(string $url);
87+
$this->refreshOrRedirectTo(string $url);
88+
$this->recedeOrRedirectBack(string $fallbackUrl, array $options = []);
89+
$this->resumeOrRedirectBack(string $fallbackUrl, array $options = []);
90+
$this->refreshOrRedirectBack(string $fallbackUrl, array $options = []);
91+
```
92+
93+
It's common to flash messages using the `->with()` method of the Redirect response in Laravel. However, since a Hotwire Native request will never actually redirect somewhere where the flash message will be rendered, the behavior of the `->with()` method was slightly modified too.
94+
95+
If you're setting flash messages like this after a form submission:
96+
97+
```php
98+
use HotwiredLaravel\TurboLaravel\Http\Controllers\Concerns\InteractsWithHotwireNativeNavigation;
99+
100+
class TraysController extends Controller
101+
{
102+
use InteractsWithHotwireNativeNavigation;
103+
104+
public function store()
105+
{
106+
// Tray creation...
107+
108+
return $this->recedeOrRedirectTo(route('trays.show', $tray))
109+
->with('status', __('Tray created.'));
110+
}
111+
}
112+
```
113+
114+
If a request was sent from a Hotwire Native client, the flashed messages will be added to the query string instead of flashed into the session like they'd normally be. In this example, it would redirect like this:
115+
116+
```
117+
/recede_historical_location?status=Tray%20created.
118+
```
119+
120+
In the Hotwire Native client, you should be able to intercept these redirects, retrieve the flash messages from the query string and create native toasts, if you'd like to.
121+
122+
If the request wasn't from a Hotwire Native client, the message would be flashed into the session as normal, and the client would receive a redirect to the `trays.show` route in this case.
123+
124+
If you don't want these routes enabled, feel free to disable them by commenting out the feature on your `config/turbo-laravel.php` file (make sure the Turbo Laravel configs are published):
125+
126+
```php
127+
return [
128+
'features' => [
129+
// Features::hotwireNativeRoutes(),
130+
],
131+
];
132+
```
133+
134+
[Continue to Testing...](/docs/{{version}}/testing)

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
* [Broadcasting](/docs/{{version}}/broadcasting)
1212
* [Validation Response Redirects](/docs/{{version}}/validation-response-redirects)
1313
* [CSRF Protection](/docs/{{version}}/csrf)
14-
* [Turbo Native](/docs/{{version}}/turbo-native)
14+
* [Hotwire Native](/docs/{{version}}/hotwire-native)
1515
* [Testing](/docs/{{version}}/testing)
1616
* [Known Issues](/docs/{{version}}/known-issues)

docs/installation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Turbo Laravel can be installed via [Composer](https://getcomposer.org/):
44

55
```bash
6-
composer require hotwired-laravel/turbo-laravel:^2.0.0
6+
composer require hotwired-laravel/turbo-laravel
77
```
88

99
After installing the package, you may run the `turbo:install` Artisan command. This command will add the Turbo.js dependency to your `package.json` file (when you're using Vite and NPM) or to your `routes/importmap.php` file (when it detects that you're using [Importmap Laravel](https://github.com/tonysm/importmap-laravel)). It also publishes some files to your `resources/js` folder, which imports Turbo for you:
@@ -12,6 +12,6 @@ After installing the package, you may run the `turbo:install` Artisan command. T
1212
php artisan turbo:install
1313
```
1414

15-
Note: Turbo used to work with Livewire, but somewhere around Livewire V3 the bridges stopped working. There's an open issue to investigate Livewire V3 compatibility. If you're into Livewire and would love to use Turbo in a Livewire app (maybe you want to augment your Livewire&Turbo app with Turbo Native or something like that), you're welcome to check out the issue and try to bring the compatibility back. If you wanted an application scaffolding like Laravel Breeze or Laravel Jetstream, checkout Turbo Breeze, our fork of Breeze that sets up a fresh Laravel app using Stimulus, Importmaps, TailwindCSS (via the CLI), and Turbo.
15+
Note: Turbo used to work with Livewire, but somewhere around Livewire V3 the bridges stopped working. There's an open issue to investigate Livewire V3 compatibility. If you're into Livewire and would love to use Turbo in a Livewire app (maybe you want to augment your Livewire & Turbo app with Hotwire Native or something like that), you're welcome to check out the issue and try to bring the compatibility back. If you wanted an application scaffolding like Laravel Breeze or Laravel Jetstream, checkout Turbo Breeze, our fork of Breeze that sets up a fresh Laravel app using Stimulus, Importmaps, TailwindCSS (via the CLI), and Turbo.
1616

1717
[Continue to Overview...](/docs/{{version}}/overview)

docs/testing.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
Testing a Hotwired app is like testing a regular Laravel app. However, Turbo Laravel comes with a set of helpers that may be used to ease testing some aspects that are specific to Turbo:
88

9-
1. **Turbo HTTP Request Helpers**. When you may want to mimic a Turbo visit, or a Turbo Native visit, or a request coming from a Turbo Frame.
9+
1. **Turbo HTTP Request Helpers**. When you may want to mimic a Turbo visit, or a Hotwire Native visit, or a request coming from a Turbo Frame.
1010
1. **Turbo Streams on HTTP Responses.** When you may want to test the Turbo Streams returned from HTTP requests.
1111
1. **Turbo Stream Broadcasts.** When you're either using the broadcast methods on your models using the `Broadcasts` trait, or when you're using [Handmade Turbo Stream Broadcasts](https://turbo-laravel.com/docs/2.x/broadcasting#content-handmade-broadcasts).
1212

@@ -69,9 +69,9 @@ class CreateCommentsTest extends TestCase
6969
}
7070
```
7171

72-
### Acting as Turbo Native
72+
### Acting as Hotwire Native
7373

74-
Additionally, when you're building a Turbo Native mobile app, you may want to issue a request pretending to be sent from a Turbo Native client. That's done by setting the `User-Agent` header to something that mentions the word `Turbo Native`. The `InteractsWithTurbo` trait also has a `$this->turboNative()` method you may use that automatically sets the header correctly:
74+
Additionally, when you're building a Hotwire Native mobile app, you may want to issue a request pretending to be sent from a Hotwire Native client. That's done by setting the `User-Agent` header to something that mentions the word `Hotwire Native`. The `InteractsWithTurbo` trait also has a `$this->hotwireNative()` method you may use that automatically sets the header correctly:
7575

7676
```php
7777
use HotwiredLaravel\TurboLaravel\Testing\InteractsWithTurbo;
@@ -87,7 +87,7 @@ class CreateCommentsTest extends TestCase
8787

8888
$this->assertCount(0, $post->comments);
8989

90-
$this->turboNative()->post(route('posts.comments.store', $post), [
90+
$this->hotwireNative()->post(route('posts.comments.store', $post), [
9191
'content' => 'Hello World',
9292
])->assertOk();
9393

@@ -97,17 +97,17 @@ class CreateCommentsTest extends TestCase
9797
}
9898
```
9999

100-
When using this method, calls to `request()->wasFromTurboNative()` will return `true`. Additionally, the `@turbonative` and `@unlessturbonative` Blade directives will render as expected.
100+
When using this method, calls to `request()->wasFromHotwireNative()` will return `true`. Additionally, the `@hotwirenative` and `@unlesshotwirenative` Blade directives will render as expected.
101101

102-
Additionally, a few macros were added to the `TestResponse` class to make it easier to assert based on the `recede`, `resume`, and `refresh` redirects using the specific assert methods:
102+
A few other macros were added to the `TestResponse` class to make it easier to assert based on the `recede`, `resume`, and `refresh` redirects using the specific assert methods:
103103

104104
| Method | Descrition |
105105
|---|---|
106106
| `assertRedirectRecede(array $with = [])` | Asserts that a redirect was returned to the `/recede_historical_location` route. |
107107
| `assertRedirectResume(array $with = [])` | Asserts that a redirect was returned to the `/resume_historical_location` route. |
108108
| `assertRedirectRefresh(array $with = [])` | Asserts that a redirect was returned to the `/refresh_historical_location` route. |
109109

110-
The `$with` param will ensure that not only the route is correct, but also any flashed message will be included in the query string:
110+
The `$with` argument will ensure that not only the route is correct, but also any flashed message will be included in the query string:
111111

112112
```php
113113
use HotwiredLaravel\TurboLaravel\Testing\InteractsWithTurbo;
@@ -123,7 +123,7 @@ class CreateCommentsTest extends TestCase
123123

124124
$this->assertCount(0, $post->comments);
125125

126-
$this->turboNative()->post(route('posts.comments.store', $post), [
126+
$this->hotwireNative()->post(route('posts.comments.store', $post), [
127127
'content' => 'Hello World',
128128
])->assertRedirectRecede(['status' => __('Comment created.')]);
129129

docs/turbo-native.md

Lines changed: 0 additions & 134 deletions
This file was deleted.

0 commit comments

Comments
 (0)