diff --git a/resources/views/docs/mobile/4/digging-deeper/accessibility.md b/resources/views/docs/mobile/4/digging-deeper/accessibility.md
index 1c4e698fc..3c13e78a4 100644
--- a/resources/views/docs/mobile/4/digging-deeper/accessibility.md
+++ b/resources/views/docs/mobile/4/digging-deeper/accessibility.md
@@ -87,11 +87,15 @@ The tappable trailing icon button on a [list item](../edge-components/list) take
headline="Backups"
trailingIconButton="info"
trailing-a11y-label="Backup details"
- @trailing-press="showBackupInfo"
+ on-trailing-press="showBackupInfo"
/>
```
@endverbatim
+`on-trailing-press` needs the `nativephp/mobile-ui` release that includes
+[NativePHP/mobile-ui#108](https://github.com/NativePHP/mobile-ui/pull/108). On 0.6.0, use the fluent
+`->onTrailingPress()` instead. See [List › Events](../edge-components/list#events).
+
List rows group their content (headline, supporting text, leading and trailing decorations) into a single
screen-reader focus stop; interactive trailing controls remain individually focusable.
diff --git a/resources/views/docs/mobile/4/digging-deeper/data-binding.md b/resources/views/docs/mobile/4/digging-deeper/data-binding.md
index cf168e82f..64c237a3a 100644
--- a/resources/views/docs/mobile/4/digging-deeper/data-binding.md
+++ b/resources/views/docs/mobile/4/digging-deeper/data-binding.md
@@ -11,7 +11,7 @@ PHP side; change the property in PHP and the control reflects it on the next ren
@verbatim
```blade static
-
+
```
@endverbatim
@@ -29,7 +29,7 @@ render sees the current value.
Any input-style EDGE component binds with `native:model`:
-- [``](../edge-components/text-input) — string
+- [``, `` and ``](../edge-components/text-input) — string
- [``](../edge-components/toggle) / [``](../edge-components/checkbox) — boolean
- [``](../edge-components/slider) — float
- [``](../edge-components/radio-group) / [``](../edge-components/select) — string
@@ -51,13 +51,18 @@ useful for text inputs where syncing on every character is wasteful:
| `native:model.lazy` | Alias for `.blur`. |
| `native:model.debounce.300ms` | After the user stops changing it for the given delay. |
+For text the user types freely, prefer a short debounce such as `native:model.debounce.150ms`. A live binding sends
+every keystroke to PHP, and when someone types quickly an earlier keystroke's value can come back after later ones and
+overwrite them, so characters appear to vanish. See
+[Text Input › Choosing a sync mode](../edge-components/text-input#choosing-a-sync-mode).
+
@verbatim
```blade static
{{-- Sync only when the user leaves the field --}}
-
+
{{-- Sync 500ms after typing stops --}}
-
+
```
@endverbatim
@@ -88,7 +93,7 @@ something other than a public property — set the value and change handler dire
@verbatim
```blade static
-
+
```
@endverbatim
diff --git a/resources/views/docs/mobile/4/digging-deeper/lifecycle-hooks.md b/resources/views/docs/mobile/4/digging-deeper/lifecycle-hooks.md
index 82415a31c..48663f6ee 100644
--- a/resources/views/docs/mobile/4/digging-deeper/lifecycle-hooks.md
+++ b/resources/views/docs/mobile/4/digging-deeper/lifecycle-hooks.md
@@ -104,7 +104,7 @@ value.
@verbatim
```blade static
-
+
```
@endverbatim
diff --git a/resources/views/docs/mobile/4/digging-deeper/theming.md b/resources/views/docs/mobile/4/digging-deeper/theming.md
index 7a8418770..60d1d770f 100644
--- a/resources/views/docs/mobile/4/digging-deeper/theming.md
+++ b/resources/views/docs/mobile/4/digging-deeper/theming.md
@@ -9,7 +9,7 @@ Every SuperNative app has one visual identity, defined in a single theme. Instea
element, you name **semantic tokens** — `primary`, `surface`, `on-surface` — and reference them everywhere. Change
a token once and it updates across every screen, in both light and dark mode.
-The theme is provided by the `nativephp/native-ui` plugin (which ships the components), but it governs the whole
+The theme is provided by the `nativephp/mobile-ui` plugin (which ships the components), but it governs the whole
app, so it's the visual contract for everything you build.
## Publishing the config
@@ -138,7 +138,7 @@ theme('primary', '#0F766E'); // fall back to a value when the token is unset
```
Pass a fallback when a setter needs a non-null string — `theme()` returns your default when the key is missing
-(or `native-ui` isn't installed).
+(or `nativephp/mobile-ui` isn't installed).
### Reacting to changes
diff --git a/resources/views/docs/mobile/4/edge-components/icon.md b/resources/views/docs/mobile/4/edge-components/icon.md
index 0e45e309b..b257d74b5 100644
--- a/resources/views/docs/mobile/4/edge-components/icon.md
+++ b/resources/views/docs/mobile/4/edge-components/icon.md
@@ -127,7 +127,7 @@ If you'd rather skip the `@@use` import, fully-qualified cases work anywhere:
+## Installing the components
+
+Every element in this section comes from the `nativephp/mobile-ui` plugin. Core `nativephp/mobile` defines the
+rendering pipeline and a few PHP element classes, but the SwiftUI and Compose renderers for all of these elements,
+including `` and ``, ship in the plugin. Install and register it:
+
+```shell
+composer require nativephp/mobile-ui
+php artisan vendor:publish --tag=nativephp-plugins-provider
+php artisan native:plugin:register nativephp/mobile-ui
+```
+
+If the plugin isn't registered in `app/Providers/NativeServiceProvider.php`, plugin elements such as `button`,
+`list_item` or `outlined_text_input` throw `Unknown native element type` when the screen renders, and the core-backed
+ones (`text`, `column`, `row` and friends) render nothing on the device. The PHP classes live in the
+`Native\Mobile\UI\Elements` namespace. See [Installation](../getting-started/installation#install-the-ui-components).
+
+## Attribute names
+
+Most attributes are written in kebab-case (`leading-icon`, `on-refresh`, `max-length`). A few elements, notably
+[``](list#list-item), take camelCase attributes (`leadingIcon`, `trailingText`,
+`leadingCheckbox`). Spell attributes exactly as each component's page lists them: an unrecognised spelling is
+silently ignored rather than raising an error.
+
+Boolean attributes follow PHP truthiness. A bare attribute (`disabled`) or a bound value (`:disabled="$busy"`) works
+as you'd expect, but a literal string such as `disabled="false"` is a non-empty string and counts as `true`. Bind
+booleans with `:` whenever the value can be false.
+
## The `native:` prefix is optional
`` and `` compile to exactly the same thing — the prefix is optional. We use it throughout
diff --git a/resources/views/docs/mobile/4/edge-components/list.md b/resources/views/docs/mobile/4/edge-components/list.md
index 56b9bccc4..b849dd106 100644
--- a/resources/views/docs/mobile/4/edge-components/list.md
+++ b/resources/views/docs/mobile/4/edge-components/list.md
@@ -46,6 +46,22 @@ Accepts any EDGE elements as children. `` is the canonical chi
A pre-styled Material3 row with a headline, optional supporting + overline text, and configurable leading + trailing
content slots.
+
+
@verbatim
```blade
done"`. Not in `nativephp/mobile-ui` 0.6.0; it needs the
+ release that includes [NativePHP/mobile-ui#109](https://github.com/NativePHP/mobile-ui/pull/109)
### Leading slot (mutually exclusive)
@@ -72,7 +91,7 @@ content slots.
- `leadingMonogram` - 1-2 character monogram (combine with `leadingMonogramColor`)
- `leadingMonogramColor` - Hex color for monogram background
- `leadingImage` - URL of a square image with a small radius
-- `leadingCheckbox` - Boolean value for a leading checkbox. Interactive when `on-leading-change` is set —
+- `leadingCheckbox` - Boolean value for a leading checkbox (bind it: `:leadingCheckbox="$done"`). Interactive when `on-leading-change` is set —
tapping the box fires your handler with the new value (the row's own `@press` still handles taps elsewhere
on the row); without a handler it renders as a static state glyph
- `leadingRadio` - Boolean value for a leading radio button. Interactive when `on-leading-change` is set;
@@ -86,10 +105,11 @@ content slots.
- `trailingCheckbox` - Boolean value for a trailing checkbox. Interactive when `on-trailing-change` is set;
static glyph otherwise
- `trailingSwitch` - Boolean value for a trailing switch [Android]
-- `trailingIconButton` - Icon name for a tappable trailing button
+- `trailingIconButton` - Icon name for a tappable trailing button. Handle taps with `on-trailing-press` (see
+ [Events](#events))
- `trailing-a11y-label` - Accessibility label for the trailing icon button (recommended whenever
`trailingIconButton` is set). See [Accessibility](../digging-deeper/accessibility)
-- `trailing-menu` - Attach a tap-to-open dropdown to the row's trailing edge. When set without an explicit trailing
+- `trailing-menu` - Attach a tap-to-open dropdown to the row's trailing edge (`trailingMenu` also works). When set without an explicit trailing
slot, an `ellipsis` icon button is auto-created as the anchor. See [Menus](menus)
Independent of the mutually-exclusive slot above, a row can also show a stack of small status icons:
@@ -109,9 +129,11 @@ All color props accept the full [color grammar](../digging-deeper/theming#color-
- `leadingIconColor`, `trailingIconColor`, `trailingTextColor` - Colors for the slot content
- `leadingIconBgColor` - Background color of the leading icon's circle
-### State
+### State and accessibility
- `disabled` - Disable the row (optional, boolean, default: `false`)
+- `a11y-label` / `a11y-hint` - Screen-reader label and hint for the whole row. See
+ [Accessibility](../digging-deeper/accessibility)
- `tonalElevation` - Tonal elevation in dp [Android]
- `shadowElevation` - Shadow elevation in dp [Android]
@@ -124,8 +146,26 @@ All color props accept the full [color grammar](../digging-deeper/theming#color-
- `on-leading-change` / `on-trailing-change` - Component method called when the leading/trailing checkbox or
radio is toggled, receiving the new value. Without a handler the control renders as a static state glyph.
-`onTrailingPress()` fires on both platforms when the trailing icon button is tapped. The trailing switch is
-interactive on [Android] only.
+- `on-trailing-press` - Component method called when the trailing icon button is tapped, on both platforms. This
+ attribute needs the `nativephp/mobile-ui` release that includes
+ [NativePHP/mobile-ui#108](https://github.com/NativePHP/mobile-ui/pull/108). In 0.6.0 it is silently ignored and
+ only the fluent `->onTrailingPress()` on a `ListItem` element works. `@trailing-press` never works: unknown `@name`
+ attributes are treated as child-component events and dropped from plain elements
+
+The trailing switch is interactive on [Android] only.
+
+Handlers receive their arguments in this order: the arguments you wrote in the expression, then the value the control
+sends. So `on-leading-change="toggleTask(@{{ $task->id }})"` calls `toggleTask($id, $checked)`:
+
+```php
+public function toggleTask(int $id, bool $checked): void
+{
+ Task::whereKey($id)->update(['done' => $checked]);
+}
+```
+
+`on-swipe-delete` and `@press` send no value, so `on-swipe-delete="deleteTask(@{{ $task->id }})"` calls
+`deleteTask($id)`. To drive these from a test, see [Testing a list](#testing-a-list).
### Swipe actions
@@ -224,7 +264,7 @@ The checkbox, swipe, and row press are three independent targets on one row: tap
check('toggleTask(1)') // tap the leading checkbox: calls toggleTask(1, true)
+ ->press('deleteTask(1)') // swipe-to-delete fires a press at its callback
+ ->press('openTask(2)'); // tap the row
+});
+```
+
## Element
```php
diff --git a/resources/views/docs/mobile/4/edge-components/text-input.md b/resources/views/docs/mobile/4/edge-components/text-input.md
index 59cb2130f..eab069aa8 100644
--- a/resources/views/docs/mobile/4/edge-components/text-input.md
+++ b/resources/views/docs/mobile/4/edge-components/text-input.md
@@ -184,6 +184,32 @@ automatically, so the `@{{ $name }}` echo updates as you type.
- `blur` — only fires on focus loss / submit
- `debounce` — fires after `debounce-ms` of inactivity (300ms when unset), or immediately on blur / submit
+### Choosing a sync mode
+
+Plain `native:model` is `live`: every keystroke is a round trip to PHP and a re-render. That's fine for short fields
+and for screens that react to each character, but it has a cost when someone types quickly. With several keystrokes
+in flight, the value PHP sends back for an earlier keystroke can land after the user has typed more, and in
+`nativephp/mobile-ui` 0.6.0 that older value overwrites the field. The visible symptom is characters vanishing (and
+sometimes coming back) while typing.
+
+For free-typed text, debounce the binding so only one sync goes out once the user pauses:
+
+@verbatim
+```blade static
+
+```
+@endverbatim
+
+A short window like 150ms still feels live to the user. Reach for:
+
+- `native:model.debounce.150ms` for text the user types freely: titles, notes, chat messages, new-item fields
+- `native:model.debounce.300ms` (or longer) for search and filter boxes that trigger a query
+- `native:model.blur` for form fields you only read when the form is submitted
+- plain `native:model` only when you need every character, such as a character counter, and the field is short
+
+Debounced and blurred fields flush any pending change on submit and on focus loss, before `@submit` fires. The
+`@submit` handler also receives the field's text as its last argument, so `@submit="add"` calls `add($text)`.
+
## Caret and selection reporting
`@selectionChange` reports caret position and text selection back to your component — for the cases where `@change`
diff --git a/resources/views/docs/mobile/4/getting-started/commands.md b/resources/views/docs/mobile/4/getting-started/commands.md
index 3e1b6d77b..975e49bd5 100644
--- a/resources/views/docs/mobile/4/getting-started/commands.md
+++ b/resources/views/docs/mobile/4/getting-started/commands.md
@@ -48,6 +48,11 @@ with `php artisan native:plugin:register`.
+The debug builds `native:run` produces are left on disk: the iOS simulator app at
+`nativephp/ios/build/Build/Products/Debug-iphonesimulator/NativePHP-simulator.app` and the Android APK at
+`nativephp/android/app/build/outputs/apk/debug/app-debug.apk`. See
+[Finding the built app](development#finding-the-built-app).
+
### native:watch
Watch for file changes and sync to a running mobile app.
@@ -403,7 +408,7 @@ php artisan native:plugin:install-agent
### native-ui:generate-icons
Generate the `App\Icons\Ios`, `App\Icons\Android`, and `App\Icons\AndroidOutlined` enums so you can reference icons as
-typed, autocompletable enum cases. Ships with the [native-ui](https://github.com/nativephp/native-ui) plugin.
+typed, autocompletable enum cases. Ships with the [`nativephp/mobile-ui`](https://github.com/NativePHP/mobile-ui) plugin.
```shell
php artisan native-ui:generate-icons
diff --git a/resources/views/docs/mobile/4/getting-started/development.md b/resources/views/docs/mobile/4/getting-started/development.md
index 3e8542536..16ab8a0b3 100644
--- a/resources/views/docs/mobile/4/getting-started/development.md
+++ b/resources/views/docs/mobile/4/getting-started/development.md
@@ -109,6 +109,33 @@ It's better than scratching your head for an hour trying to figure out why your
+## Finding the built app
+
+`native:run` builds a normal debug app and then installs it. The build output stays on disk afterwards, so you can
+hand it to a teammate, install it on another simulator or emulator, or upload it to a device farm.
+
+| Platform | Command | Output |
+|----------|---------|--------|
+| iOS simulator | `php artisan native:run ios {simulator-udid}` | `nativephp/ios/build/Build/Products/Debug-iphonesimulator/NativePHP-simulator.app` |
+| Android debug | `php artisan native:run android --build=debug` | `nativephp/android/app/build/outputs/apk/debug/app-debug.apk` |
+
+A few things to know:
+
+- The simulator `.app` is always named `NativePHP-simulator.app`, whatever your app is called. NativePHP sets the
+ bundle name inside it from your `APP_NAME`. It only runs on simulators, not on physical devices.
+- Install the `.app` on any booted simulator with `xcrun simctl install booted path/to/NativePHP-simulator.app`, and
+ the `.apk` on any emulator or device with `adb install -r path/to/app-debug.apk`.
+- `--build=profileable` on Android writes `apk/profileable/app-profileable.apk` instead.
+- The `nativephp` directory is rebuilt by `native:install --force`, so copy anything you want to keep somewhere else.
+- Keep `NATIVEPHP_APP_VERSION=DEBUG` in `.env` for these builds. A `DEBUG` build re-extracts your Laravel app every
+ time it launches. With a fixed version such as `1.0.0`, an app that is already installed only re-extracts when the
+ version or build number changes, so installing a fresh build over an old one can keep showing the old screens.
+- These are development builds. For signed release builds (`.ipa`, release `.apk` or `.aab`), use
+ [`native:package`](commands#nativepackage) or [Bifrost](../publishing/bifrost).
+
+To find a simulator's UDID, run `xcrun simctl list devices available`. For Android device serials, run
+`adb devices`.
+
## Working with Xcode or Android Studio
On occasion, it is useful to compile your app from inside the target platform's dedicated development tools, Android
diff --git a/resources/views/docs/mobile/4/getting-started/installation.md b/resources/views/docs/mobile/4/getting-started/installation.md
index ae602ec28..097a81c6b 100644
--- a/resources/views/docs/mobile/4/getting-started/installation.md
+++ b/resources/views/docs/mobile/4/getting-started/installation.md
@@ -3,6 +3,24 @@ title: Installation
order: 100
---
+## Start from the starter kit
+
+The quickest way to a working v4 app is the starter kit, which comes with NativePHP and its UI components already
+installed and registered:
+
+```shell
+laravel new my-app --using=nativephp/mobile-starter --no-node
+cd my-app
+```
+
+`--no-node` skips the `npm install && npm run build` the installer runs by default, which a SuperNative app doesn't
+need. `laravel new` also installs [Laravel Boost](https://laravel.com/ai/boost), which sets up AI agent guidelines for
+the project; pass `--no-boost` to skip it.
+
+Then skip ahead to [Run the NativePHP installer](#run-the-nativephp-installer).
+
+To add NativePHP to an existing Laravel app instead, follow the next two sections.
+
## Install the Composer package
NativePHP contains all the libraries, classes, commands, and interfaces that your application will need to work with
@@ -12,6 +30,40 @@ iOS and Android. And it's a single command away:
composer require nativephp/mobile
```
+## Install the UI components
+
+The native UI elements (``, ``, ``, the text inputs and the rest of the
+[EDGE components](../edge-components/introduction)) ship in a separate plugin, `nativephp/mobile-ui`. Install it
+alongside the core package:
+
+```shell
+composer require nativephp/mobile-ui
+```
+
+Like every [plugin](../plugins/using-plugins), it has to be registered before its native code is compiled into your
+app. Publish the `NativeServiceProvider` and register the plugin:
+
+```shell
+php artisan vendor:publish --tag=nativephp-plugins-provider
+php artisan native:plugin:register nativephp/mobile-ui
+```
+
+This adds `\Native\Mobile\UI\NativeUIServiceProvider::class` to the `plugins()` array in
+`app/Providers/NativeServiceProvider.php`. Check it's there with `php artisan native:plugin:list`.
+
+
+
### We love Laravel
NativePHP for Mobile is built to work with Laravel. We recommend that you install it into a
diff --git a/resources/views/docs/mobile/4/getting-started/quick-start.md b/resources/views/docs/mobile/4/getting-started/quick-start.md
index cb6f8ddca..81a8bd84a 100644
--- a/resources/views/docs/mobile/4/getting-started/quick-start.md
+++ b/resources/views/docs/mobile/4/getting-started/quick-start.md
@@ -13,7 +13,7 @@ Don't waste hours downloading, installing, and configuring Xcode and Android Stu
### New Laravel app
-If you are creating new Laravel app, you can build using our starter kit:
+The recommended way to start is our starter kit:
```bash
laravel new my-app --using=nativephp/mobile-starter --no-node
@@ -23,16 +23,36 @@ cd my-app
php artisan native:jump
```
+`--no-node` skips the `npm install && npm run build` the installer runs by default, which a SuperNative app doesn't
+need. `laravel new` also installs [Laravel Boost](https://laravel.com/ai/boost), which sets up AI agent guidelines for
+the project; pass `--no-boost` to skip it.
+
+The starter kit already installs and registers `nativephp/mobile-ui`.
+
+
+
### Existing Laravel app
If you already have a Laravel app:
```bash
-composer require nativephp/mobile
+composer require nativephp/mobile nativephp/mobile-ui
+
+php artisan vendor:publish --tag=nativephp-plugins-provider
+php artisan native:plugin:register nativephp/mobile-ui
php artisan native:jump
```
+`nativephp/mobile-ui` provides the native UI elements (text, buttons, lists, inputs and so on). It must be registered
+in `app/Providers/NativeServiceProvider.php` or your screens will render blank. See
+[Installation](installation#install-the-ui-components).
+
Scan the QR code with Jump and you're off!
## Install & run
@@ -41,8 +61,12 @@ If you've already got your [environment set up](environment-setup) to build mobi
Studio, you can build and run your app locally:
```bash
-# Install NativePHP for Mobile into a new Laravel app
-composer require nativephp/mobile
+# Install NativePHP for Mobile and its UI components into a new Laravel app
+composer require nativephp/mobile nativephp/mobile-ui
+
+# Register the UI plugin so its native code is compiled in
+php artisan vendor:publish --tag=nativephp-plugins-provider
+php artisan native:plugin:register nativephp/mobile-ui
# Ready your app to go native
php artisan native:install
diff --git a/resources/views/docs/mobile/4/testing/interactions.md b/resources/views/docs/mobile/4/testing/interactions.md
index 179ec49f5..c20423c6a 100644
--- a/resources/views/docs/mobile/4/testing/interactions.md
+++ b/resources/views/docs/mobile/4/testing/interactions.md
@@ -35,7 +35,7 @@ element a `ref` and target it by name. A `ref` works in Blade on any element:
Tap to vibrate
-
+
```
@endverbatim
@@ -83,7 +83,7 @@ Each control fires the same event its native counterpart emits:
- `changeTab($target, $index)` — switch a tab row to an index.
- `dismissSheet($target)` — dismiss a bottom sheet.
-Fields bound with `wire:model` sync their property as you'd expect:
+Fields bound with `native:model` sync their property as you'd expect:
```php
it('fills and submits the toast form', function () {
@@ -95,6 +95,28 @@ it('fills and submits the toast form', function () {
});
```
+### List rows
+
+A [list item](../edge-components/list#list-item)'s checkbox, radio and swipe-to-delete callbacks are best targeted by
+the expression you bound, since each row in a loop has its own:
+
+@verbatim
+```blade static
+
+```
+@endverbatim
+
+```php
+Native::test(Tasks::class)
+ ->check('toggleTask(1)') // calls toggleTask(1, true)
+ ->press('deleteTask(1)'); // swipe-to-delete arrives as a press
+```
+
## Setting properties and calling methods
Two lower-level tools reach the component directly.
diff --git a/resources/views/docs/mobile/4/testing/introduction.md b/resources/views/docs/mobile/4/testing/introduction.md
index 510da4d68..de72a8743 100644
--- a/resources/views/docs/mobile/4/testing/introduction.md
+++ b/resources/views/docs/mobile/4/testing/introduction.md
@@ -17,6 +17,24 @@ component's state.
Rendering fidelity — how SwiftUI or Compose actually paints those elements on screen — is out of scope by design. The
suite asserts on *what your component published*, exactly the layer you control from PHP.
+## Setup
+
+The testing helpers ship with `nativephp/mobile`, in the `Native\Mobile\Testing` namespace. There's nothing extra to
+install beyond your test runner. New Laravel apps ship with PHPUnit; to use Pest as these examples do:
+
+```shell
+composer require pestphp/pest --dev --with-all-dependencies
+./vendor/bin/pest --init
+```
+
+Tests boot your real application, so the plugins registered in `app/Providers/NativeServiceProvider.php` are what
+the test renders against. If `nativephp/mobile-ui` isn't [registered](../getting-started/installation#install-the-ui-components),
+a screen using `` or `` fails in the test with `Unknown native element type`, the
+same as it would in the app.
+
+Put component tests in `tests/Feature` (which `pest --init` binds to your app's `TestCase`) and run them with
+`php artisan test` or `./vendor/bin/pest`.
+
## The `Native` entry point
Every test starts from the `Native` facade. It has three entry points:
diff --git a/resources/views/docs/mobile/4/the-basics/layouts.md b/resources/views/docs/mobile/4/the-basics/layouts.md
index b3bb2a650..517dd4271 100644
--- a/resources/views/docs/mobile/4/the-basics/layouts.md
+++ b/resources/views/docs/mobile/4/the-basics/layouts.md
@@ -61,7 +61,7 @@ includes two reference layouts you can copy as a starting point:
- `App\NativeComponents\Layouts\TabsLayout` - Title bar plus a 3-tab bottom nav.
@verbatim
-If you use the `nativephp/native-ui` plugin, its `native-ui-layouts` publish tag scaffolds a starter ``
+If you use the `nativephp/mobile-ui` plugin, its `native-ui-layouts` publish tag scaffolds a starter ``
Blade component that wraps a screen's content with safe-area handling and optional scrolling — copy it to
`feed.blade.php`, `detail.blade.php`, and so on for multiple page archetypes.
@endverbatim
@@ -227,7 +227,7 @@ honors every tier everywhere.
## Drawer navigation
-For a slide-out side drawer, mix the native-ui `HasLayoutDrawer` trait into your layout and return a `Drawer` from
+For a slide-out side drawer, mix the mobile-ui `HasLayoutDrawer` trait into your layout and return a `Drawer` from
`drawer()`. The content is any Blade view, so you build the drawer's UI with normal EDGE components:
```php
@@ -342,7 +342,7 @@ the content too far.
## Floating overlay
For a pill or banner that **floats over** every screen — a "servers nearby" chip, a now-playing capsule, a
-sync-status badge — mix the native-ui `HasFloatingOverlay` trait into your layout and return a `FloatingOverlay`
+sync-status badge — mix the mobile-ui `HasFloatingOverlay` trait into your layout and return a `FloatingOverlay`
from `floatingOverlay()`. Unlike `bottomBar()`, it does **not** inset the content: it hovers on a top layer above
the content and the tab bar, so nothing is pushed up. Return `null` and nothing floats.
diff --git a/resources/views/docs/mobile/4/the-basics/native-ui.md b/resources/views/docs/mobile/4/the-basics/native-ui.md
index 3106959a5..4018dca62 100644
--- a/resources/views/docs/mobile/4/the-basics/native-ui.md
+++ b/resources/views/docs/mobile/4/the-basics/native-ui.md
@@ -38,6 +38,14 @@ runtime without recompiling your app.
Browse the full catalogue in the [EDGE Components](../edge-components/introduction) section.
+
+
## Structuring your app
Once you're comfortable with the component syntax, two concepts organize your screens into an app: