Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ a non-theme-styled container (e.g. a light spinner over a dark image overlay).
```blade
<native:column fill center>
<native:activity-indicator size="lg" />
<native:text class="text-base text-slate-400 mt-4">Loading...</native:text>
<native:text class="text-base text-theme-on-surface-variant mt-4">Loading...</native:text>
</native:column>
```
@endverbatim
Expand All @@ -51,7 +51,7 @@ a non-theme-styled container (e.g. a light spinner over a dark image overlay).
```blade
<native:row :gap="8" :align-items="1">
<native:activity-indicator size="sm" />
<native:text class="text-sm text-slate-500">Refreshing</native:text>
<native:text class="text-sm text-theme-on-surface-variant">Refreshing</native:text>
</native:row>
```
@endverbatim
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Per Model 3, the container color resolves from `theme.surface`. For a custom sur
<native:bottom-sheet :visible="$showSheet" @dismiss="$showSheet = false">
<native:column class="w-full p-4 gap-3">
<native:text class="text-xl font-bold">Sheet Title</native:text>
<native:text class="text-base text-slate-500">Sheet content goes here.</native:text>
<native:text class="text-base text-theme-on-surface-variant">Sheet content goes here.</native:text>
<native:button label="Close" @press="$showSheet = false" />
</native:column>
</native:bottom-sheet>
Expand Down
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/edge-components/carousel.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ stack with `item-spacing` between items.
@foreach($posts as $post)
<native:column :height="200" bg="#F1F5F9" :border-radius="16" :padding="16">
<native:text class="text-lg font-bold">{{ $post->title }}</native:text>
<native:text class="text-sm text-slate-500">{{ $post->excerpt }}</native:text>
<native:text class="text-sm text-theme-on-surface-variant">{{ $post->excerpt }}</native:text>
</native:column>
@endforeach
</native:carousel>
Expand Down
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/edge-components/divider.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ the platform separator color (`UIColor.separator` on iOS, Material `outlineVaria
`<native:divider />` is a self-closing element. It does not accept children.

The line is **always 1pt high**. For thicker rules, drop in a styled column instead:
`<native:column class="h-px bg-zinc-200" />` for 1px, `<native:column class="h-1 bg-zinc-200" />` for 4dp, etc.
`<native:column class="h-px bg-theme-outline" />` for 1px, `<native:column class="h-1 bg-theme-outline" />` for 4dp, etc.

</aside>

Expand Down
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/edge-components/icon.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ and platform-specific usage, see the [Icons](icons) reference page.
```blade
<native:column center :padding="32">
<native:icon name="email" :size="64" color="#94A3B8" />
<native:text class="text-lg text-slate-400">No messages</native:text>
<native:text class="text-lg text-theme-on-surface-variant">No messages</native:text>
</native:column>
```
@endverbatim
Expand Down
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/edge-components/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ The renderer collapses fit modes to two effective behaviors: `fit` and `fill`. M
<native:image src="https://example.com/cover.jpg" class="w-full" :height="180" :fit="2" />
<native:column class="p-4 gap-2">
<native:text class="text-lg font-bold">Article Title</native:text>
<native:text class="text-base text-slate-500">A brief description of the article.</native:text>
<native:text class="text-base text-theme-on-surface-variant">A brief description of the article.</native:text>
</native:column>
</native:column>
```
Expand Down
1 change: 1 addition & 0 deletions resources/views/docs/mobile/4/edge-components/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ The parser recognizes the classes listed below.
| Text size | `text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, `text-3xl`, `text-4xl`, `text-5xl`, `text-6xl`, arbitrary `text-[N]` |
| Font weight | `font-thin`, `font-extralight`, `font-light`, `font-normal`, `font-medium`, `font-semibold`, `font-bold`, `font-extrabold`, `font-black` |
| Text align | `text-left`, `text-center`, `text-right` |
| Text selection | `select-text`, `select-none` (container-scoped; descendants inherit) |
| Safe area | `safe-area` (top + bottom), `safe-area-top`, `safe-area-bottom` |
| Liquid Glass | `glass`, `glass:prominent`, `glass:interactive`, `glass:clear` (compose: `glass:clear:interactive`) |

Expand Down
6 changes: 3 additions & 3 deletions resources/views/docs/mobile/4/edge-components/pressable.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ provides a clear tap target that wraps multiple children.
```blade
<native:pressable @press="selectItem({{ $item->id }})" class="w-full p-4 rounded-xl" bg="#FFFFFF">
<native:text class="text-lg font-semibold">{{ $item->name }}</native:text>
<native:text class="text-sm text-slate-400">{{ $item->description }}</native:text>
<native:text class="text-sm text-theme-on-surface-variant">{{ $item->description }}</native:text>
</native:pressable>
```
@endverbatim
Expand Down Expand Up @@ -50,7 +50,7 @@ Accepts any EDGE elements as children. Children are arranged vertically (like a
<native:icon name="folder" :size="24" color="#3B82F6" />
<native:column :flex-grow="1" :gap="2">
<native:text class="text-base font-medium">{{ $item->name }}</native:text>
<native:text class="text-sm text-slate-400">{{ $item->subtitle }}</native:text>
<native:text class="text-sm text-theme-on-surface-variant">{{ $item->subtitle }}</native:text>
</native:column>
<native:icon name="forward" :size="16" color="#94A3B8" />
</native:row>
Expand All @@ -74,7 +74,7 @@ Accepts any EDGE elements as children. Children are arranged vertically (like a
:elevation="2"
>
<native:text class="text-lg font-bold">{{ $post->title }}</native:text>
<native:text class="text-base text-slate-500">{{ $post->excerpt }}</native:text>
<native:text class="text-base text-theme-on-surface-variant">{{ $post->excerpt }}</native:text>
</native:pressable>
```
@endverbatim
Expand Down
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/edge-components/row.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Everything else from the shared list applies the same as on any element (`w-*`,
@verbatim
```blade
<native:row class="w-full justify-between items-center">
<native:text class="text-base text-slate-500">Status</native:text>
<native:text class="text-base text-theme-on-surface-variant">Status</native:text>
<native:row class="gap-1 items-center">
<native:icon name="check" color="#22C55E" :size="16" />
<native:text class="text-base font-semibold text-green-500">Active</native:text>
Expand Down
4 changes: 2 additions & 2 deletions resources/views/docs/mobile/4/edge-components/scroll-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ scrollable content.
@foreach($posts as $post)
<native:column class="w-full p-4 gap-2" :border-width="1" border-color="#F1F5F9">
<native:text class="text-lg font-semibold">{{ $post->title }}</native:text>
<native:text class="text-base text-slate-500">{{ $post->excerpt }}</native:text>
<native:text class="text-base text-theme-on-surface-variant">{{ $post->excerpt }}</native:text>
</native:column>
@endforeach
</native:column>
Expand Down Expand Up @@ -88,7 +88,7 @@ scrollable content.
<native:scroll-view class="w-full h-full" bg="#FFFFFF">
<native:column class="w-full gap-4 safe-area p-4">
<native:text class="text-3xl font-bold">Welcome</native:text>
<native:text class="text-base text-slate-500">
<native:text class="text-base text-theme-on-surface-variant">
Scroll down to see more content.
</native:text>
{{-- Long content here --}}
Expand Down
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/edge-components/spacer.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ See the full shared list at [Layout & Styling](layout#supported-tailwind-classes
```blade
<native:column class="w-full h-full p-4">
<native:text class="text-2xl font-bold">Welcome</native:text>
<native:text class="text-base text-slate-500">Get started with your app.</native:text>
<native:text class="text-base text-theme-on-surface-variant">Get started with your app.</native:text>
<native:spacer />
<native:button label="Continue" @press="next" />
</native:column>
Expand Down
8 changes: 8 additions & 0 deletions resources/views/docs/mobile/4/edge-components/text-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ Both variants are self-closing. They do not accept children.

</aside>

<aside>

To keep an input visible while the keyboard is up — a chat composer, a search bar — place it in a
[`<native:bottom-bar>`](../super-native/layouts#keyboard-aware-bottom-content), which pins above the keyboard
automatically. Avoid manually padding or shifting the screen yourself.

</aside>

## Two-way Binding

Use the `native:model` directive for automatic two-way binding with a component property. The directive expands to
Expand Down
47 changes: 45 additions & 2 deletions resources/views/docs/mobile/4/edge-components/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,50 @@ All [shared layout and style attributes](layout) are supported, plus:

<aside>

`<native:text>` is **not** self-closing. Text content goes between the tags as slot content. HTML tags inside the
slot are stripped — only plain text is rendered.
`<native:text>` is **not** self-closing — content goes between the tags. Nested `<native:text>` elements are
supported as [inline runs](#inline-runs); any other HTML tags in the slot are stripped.

</aside>

## Inline runs

Nest `<native:text>` elements inside a `<native:text>` to style spans within a single paragraph. The nested runs
and the surrounding text compose into **one** attributed string that wraps together as a unit — each run carries
its own classes (weight, color, size):

@verbatim
```blade
<native:text class="text-base text-theme-on-surface">
Use <native:text class="font-bold">bold</native:text> and
<native:text class="text-theme-primary font-semibold">color</native:text> inline.
</native:text>
```
@endverbatim

Runs render in document order, so interleaved text and nested `<native:text>` stay in sequence. A `<native:text>`
with no nested runs behaves exactly like a plain string.

## Text selection

Text isn't selectable by default. Add `select-text` to make a subtree long-press-selectable (the native Copy
menu). It's container-scoped and inherited, so it covers every descendant — put it on a wrapping element to make a
whole region selectable. Use `select-none` to opt a nested subtree back out:

@verbatim
```blade
<native:column class="select-text">
<native:text class="text-lg font-bold">Selectable heading</native:text>
<native:text class="text-base">This body copy can be selected and copied.</native:text>

<native:text class="select-none text-xs text-theme-on-surface-variant">Not selectable</native:text>
</native:column>
```
@endverbatim

<aside>

`select-text` / `select-none` work on **any** element, not just text — they scope selection for the whole
subtree. The programmatic equivalent is `->selectable()` / `->selectable(false)`.

</aside>

Expand Down Expand Up @@ -135,3 +177,4 @@ Text::make('Hello')
- `color(string $hex)` - Text color
- `textAlign(int $align)` - `0`=start, `1`=center, `2`=end
- `maxLines(int $lines)` - Truncate after N lines
- `selectable(bool $on = true)` - Make the subtree selectable (mirrors `select-text` / `select-none`)
5 changes: 5 additions & 0 deletions resources/views/docs/mobile/4/getting-started/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ For changes prior to v4, see the [v3 documentation](/docs/mobile/3/getting-start
- **[Native navigation stack](../super-native/navigation)** — register screens with `Route::native()`, then push, pop, and replace them with native transitions
- **[Component testing suite](../testing/introduction)** — mount a `NativeComponent`, drive interactions, and assert on state and output entirely in-process, with no device or simulator

### Breaking Changes

- **Device, Dialog, File and System are now core built-ins** — the `nativephp/mobile-device`, `nativephp/mobile-dialog`, `nativephp/mobile-file`, and `nativephp/mobile-system` plugins have moved into `nativephp/mobile`. **Remove the standalone plugins before upgrading** (see the [Upgrade Guide](upgrade-guide)). The facades and events are unchanged, so no application code changes are needed.
- **The Vite dev server is now opt-in** — `native:run` / `native:watch` no longer start Vite automatically. Pass `--vite` to enable JS/CSS HMR. The `--no-vite` flag still works but is now redundant. See [Hot Reloading](development#hot-reloading).

### For Plugin Developers

- **No breaking changes** to the plugin architecture — add the `^4.0` constraint to your plugin's `nativephp/mobile` dependency and you're done
10 changes: 10 additions & 0 deletions resources/views/docs/mobile/4/getting-started/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ php artisan native:run {os?} {udid?}
| `udid` | Specific device/simulator UDID |
| `--build=debug` | Build type: `debug`, `release`, or `bundle` |
| `--watch` | Enable hot reloading during development |
| `--vite` | Start the Vite dev server for JS/CSS HMR (opt-in; off by default) |
| `--start-url=` | Initial URL/path to load (e.g., `/dashboard`) |
| `--no-tty` | Disable TTY mode for non-interactive environments |

Expand All @@ -60,6 +61,15 @@ php artisan native:watch {platform?} {target?}
|--------|-----------------------------------------|
| `platform` | Target platform: `ios/i` or `android/a` |
| `target` | The device/simulator UDID to watch |
| `--vite` | Start the Vite dev server for JS/CSS HMR (opt-in; off by default) |

<aside>

As of **v4**, the Vite dev server is **opt-in** — pass `--vite` to `native:run`/`native:watch` to start it. It
was previously started automatically; the old `--no-vite` flag still exists but is now redundant. See the
[Upgrade Guide](upgrade-guide).

</aside>

### native:jump

Expand Down
21 changes: 18 additions & 3 deletions resources/views/docs/mobile/4/getting-started/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,27 @@ application to the target device and _then_ start the watcher, all in one go.
This will start a long-lived process that watches your application's source files for changes, pushing them into the
emulator after any updates and reloading the current screen.

If you're using Vite, we'll also use your Node CLI tool of choice (`npm`, `bun`, `pnpm`, or `yarn`) to run Vite's HMR
server.
If you're using Vite for your UI (React/Vue/Tailwind, etc.), pass the `--vite` flag and we'll also start Vite's HMR
server using your Node CLI tool of choice (`npm`, `bun`, `pnpm`, or `yarn`):

```shell
php artisan native:watch --vite

# or build, deploy, and start watching in one go:
php artisan native:run --watch --vite
```

<aside>

As of **v4**, the Vite dev server is **opt-in** — it only starts when you pass `--vite`. In earlier versions it
started automatically and you disabled it with `--no-vite` (that flag still exists but is now redundant).

</aside>

### Enabling HMR

To make HMR work, you'll need to add the `hot` file helper to your `laravel` plugin's config in your `vite.config.js`:
To make HMR work, add the `hot` file helper to your `laravel` plugin's config in your `vite.config.js`, then run
the watcher with `--vite` (above):

```js
import { nativephpMobile, nativephpHotFile } from './vendor/nativephp/mobile/resources/js/vite-plugin.js'; // [tl! focus]
Expand Down
84 changes: 84 additions & 0 deletions resources/views/docs/mobile/4/getting-started/upgrade-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,90 @@ title: Upgrade Guide
order: 3
---

## Upgrading To 4.0 From 3.x

v4's headline is [SuperNative](../super-native/introduction) — fully native UI. Most of the release is additive,
but there is **one breaking change to your dependencies**: a handful of APIs that used to be separate plugins are
now core built-ins.

### Why SuperNative

For its first three major versions, NativePHP for Mobile was built around a fast, opinionated web view. It worked
well — but it tied your app's UI to a stack of moving parts we didn't own, and every upstream release was a chance
for something to break. Inertia 3 dropped its axios dependency and broke Inertia apps. Livewire 4 began emitting
filenames containing an emoji (🔥) that our bundled PHP binaries initially couldn't read. We spent real energy
chasing a target that kept moving, on layers we couldn't control.

SuperNative changes that equation. Instead of rendering your UI in a browser and hoping the layers above stay
compatible, it renders real SwiftUI and Jetpack Compose views driven directly by your PHP — a stack we own end to
end, from your Laravel app all the way down to the native view tree. That means our effort goes into making *that*
fast, stable, and capable, rather than reacting to churn elsewhere. The web view's advantages have narrowed as
SuperNative's rendering has matured, and for new work SuperNative is where the platform — and our focus — is
headed.

The web view isn't going away: [it's still available as a component](../edge-components/web-view) for the cases
that genuinely need HTML. But it's now opt-in, not the foundation.

### Device, Dialog, File and System are now built in

`Device`, `Dialog`, `File`, and `System` now ship inside `nativephp/mobile` — their native bridge functions are
registered by core. `nativephp/mobile` v4 declares a Composer **conflict** with the four standalone plugins, so
`composer update` will refuse to resolve until you **remove them**.

Uninstall each one you have (this also unregisters it from your `NativeServiceProvider`):

```shell
php artisan native:plugin:uninstall nativephp/mobile-device
php artisan native:plugin:uninstall nativephp/mobile-dialog
php artisan native:plugin:uninstall nativephp/mobile-file
php artisan native:plugin:uninstall nativephp/mobile-system
```

Or remove them directly with Composer if they were never registered in your `NativeServiceProvider`:

```shell
composer remove nativephp/mobile-device nativephp/mobile-dialog nativephp/mobile-file nativephp/mobile-system
```

**No application code changes are required.** The `Native\Mobile\Facades\{Device, Dialog, File, System}` facades
and their events (`ButtonPressed`, etc.) are unchanged. Their docs now live in the SuperNative section:
[Device](../super-native/device), [Dialog](../super-native/dialog), [File](../super-native/file), and
[System](../super-native/system).

### The Vite dev server is now opt-in

`native:run` and `native:watch` no longer start the Vite dev server automatically. If you rely on Vite HMR during
development (React/Vue/Tailwind, etc.), add the `--vite` flag:

```shell
php artisan native:watch --vite
php artisan native:run --watch --vite
```

The old `--no-vite` flag still exists but is now redundant — Vite is off unless you ask for it. If you have
`--no-vite` in your scripts, you can drop it.

### Update your dependency

```json
"require": {
"nativephp/mobile": "~3.1.0" // [tl! remove]
"nativephp/mobile": "~4.0.0" // [tl! add]
}
```

```sh
composer update
php artisan native:install --force
```

<aside>

The `--force` flag rebuilds the native project files with the v4 versions.

</aside>


## Upgrading To 3.1 From 3.0

v3.1 is a drop-in upgrade with no breaking changes. The headline feature is a **persistent PHP runtime** that
Expand Down
4 changes: 0 additions & 4 deletions resources/views/docs/mobile/4/plugins/core/device.md

This file was deleted.

4 changes: 0 additions & 4 deletions resources/views/docs/mobile/4/plugins/core/dialog.md

This file was deleted.

4 changes: 0 additions & 4 deletions resources/views/docs/mobile/4/plugins/core/file.md

This file was deleted.

4 changes: 0 additions & 4 deletions resources/views/docs/mobile/4/plugins/core/system.md

This file was deleted.

Loading
Loading