diff --git a/resources/views/docs/mobile/4/digging-deeper/accessibility.md b/resources/views/docs/mobile/4/digging-deeper/accessibility.md index 101fca66..1c4e698f 100644 --- a/resources/views/docs/mobile/4/digging-deeper/accessibility.md +++ b/resources/views/docs/mobile/4/digging-deeper/accessibility.md @@ -20,7 +20,7 @@ Every element accepts two attributes: - `a11y-hint` - Supplementary usage guidance, announced after the label (e.g. "Double-tap to open settings"). @verbatim -```blade +```blade static ``` @@ -48,7 +48,7 @@ isn't descriptive enough on its own. mystery to screen reader users. @verbatim -```blade +```blade static {{-- Bad: VoiceOver has nothing meaningful to announce --}} @@ -63,7 +63,7 @@ Standalone `` elements are **decorative by default** — they are unless you give them an `a11y-label`. If an icon conveys meaning on its own (or is tappable), label it: @verbatim -```blade +```blade static ``` @endverbatim @@ -72,7 +72,7 @@ Images take an `alt` attribute, mirroring the web. With `alt`, the image is anno is treated as decorative and skipped: @verbatim -```blade +```blade static ``` @endverbatim @@ -82,7 +82,7 @@ is treated as decorative and skipped: The tappable trailing icon button on a [list item](../edge-components/list) takes its own label via `trailing-a11y-label`: @verbatim -```blade +```blade static ``` @endverbatim @@ -52,7 +52,7 @@ useful for text inputs where syncing on every character is wasteful: | `native:model.debounce.300ms` | After the user stops changing it for the given delay. | @verbatim -```blade +```blade static {{-- Sync only when the user leaves the field --}} @@ -87,7 +87,7 @@ properties, derive the rest with computed methods, and let the UI re-render itse something other than a public property — set the value and change handler directly: @verbatim -```blade +```blade static ``` @endverbatim diff --git a/resources/views/docs/mobile/4/digging-deeper/gestures.md b/resources/views/docs/mobile/4/digging-deeper/gestures.md index 1e559dce..6bf8fc3c 100644 --- a/resources/views/docs/mobile/4/digging-deeper/gestures.md +++ b/resources/views/docs/mobile/4/digging-deeper/gestures.md @@ -17,7 +17,7 @@ If you've used Reanimated in React Native, this is the same idea. Create one in PHP with `SharedValue::make($initial)`, bind it to a gesture, and read it from any animatable prop: @verbatim -```blade +```blade static @php $drag = \Native\Mobile\Edge\SharedValue::make(); @endphp @@ -68,7 +68,7 @@ change in `animate-duration` (milliseconds) and the element eases from its old v render. The animatable props are `translate-x`, `translate-y`, `scale`, `rotate`, and `opacity`: @verbatim -```blade +```blade static {{-- A panel slides up from below when $shown flips to true --}} @@ -113,7 +113,7 @@ back on release: - `press-translate-y` — nudge down while pressed (e.g. `3`) @verbatim -```blade +```blade static Press me 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 b5c2807b..981cdfa3 100644 --- a/resources/views/docs/mobile/4/digging-deeper/lifecycle-hooks.md +++ b/resources/views/docs/mobile/4/digging-deeper/lifecycle-hooks.md @@ -103,7 +103,7 @@ Livewire's updated hooks. The hook name is `updated` + the studly-cased property value. @verbatim -```blade +```blade static ``` @endverbatim diff --git a/resources/views/docs/mobile/4/digging-deeper/reactivity.md b/resources/views/docs/mobile/4/digging-deeper/reactivity.md index a1e1a690..fa5faa09 100644 --- a/resources/views/docs/mobile/4/digging-deeper/reactivity.md +++ b/resources/views/docs/mobile/4/digging-deeper/reactivity.md @@ -32,7 +32,7 @@ class CartScreen extends NativeComponent Access it as `$this->total` (no parentheses) in PHP, or `@{{ $this->total }}` in the view: @verbatim -```blade +```blade static Total: {{ $this->total }} ``` @endverbatim @@ -82,7 +82,7 @@ You can also drive a re-render from the view with `native:poll` — useful for a without wiring a method: @verbatim -```blade +```blade static {{ now()->format('g:i:s A') }} ``` @endverbatim diff --git a/resources/views/docs/mobile/4/digging-deeper/theming.md b/resources/views/docs/mobile/4/digging-deeper/theming.md index 5d16cd83..88450495 100644 --- a/resources/views/docs/mobile/4/digging-deeper/theming.md +++ b/resources/views/docs/mobile/4/digging-deeper/theming.md @@ -77,7 +77,7 @@ preserves the alpha byte. Reference any token from Blade with the `theme-{token}` class suffix, on background, text, and border utilities: @verbatim -```blade +```blade static Balance Updated just now diff --git a/resources/views/docs/mobile/4/edge-components/activity-indicator.md b/resources/views/docs/mobile/4/edge-components/activity-indicator.md index 3b418fd4..da264840 100644 --- a/resources/views/docs/mobile/4/edge-components/activity-indicator.md +++ b/resources/views/docs/mobile/4/edge-components/activity-indicator.md @@ -39,18 +39,21 @@ a non-theme-styled container (e.g. a light spinner over a dark image overlay). @verbatim ```blade - + Loading... ``` @endverbatim +On a real loading screen, use `` at the page root instead — the fixed `h-[200]` here just +gives the example a bounded area to center in. + ### Inline loading @verbatim ```blade - + Refreshing diff --git a/resources/views/docs/mobile/4/edge-components/badge.md b/resources/views/docs/mobile/4/edge-components/badge.md index 993b5e62..37c569f4 100644 --- a/resources/views/docs/mobile/4/edge-components/badge.md +++ b/resources/views/docs/mobile/4/edge-components/badge.md @@ -8,8 +8,8 @@ order: 110 A small count or text marker, typically used as an overlay on nav items, list rows, or buttons. Renders as a capsule pill. -Colors come from the theme via the semantic `variant` prop by default. To override them per instance, apply `bg-*` -classes for the fill and `rounded-*` classes to adjust the capsule radius. +Colors come from the theme via the semantic `variant` prop — `destructive` (the default), `primary`, or `accent`. +Prefer `variant` for badge colors: it keeps the label legible on both platforms and in both light and dark themes. @verbatim ```blade @@ -41,7 +41,7 @@ icon, see the `badge` and `news` props on [``](bottom-na @verbatim ```blade - + @@ -58,19 +58,40 @@ icon, see the `badge` and `news` props on [``](bottom-na ### Anchored to an icon -Use a [``](stack) to layer the badge over its target: +Use a [``](stack) to layer the badge over its target. Size the stack a little larger than the +icon so the badge has a corner to sit in, and position it with positive `top-*` / `right-*` insets — the +renderer anchors an absolute child to whichever edges you set (negative insets are not supported): @verbatim ```blade - + ``` @endverbatim +### Custom background (iOS only) + +On iOS you can override the capsule fill with a `bg-*` class and the radius with a `rounded-*` class: + +@verbatim +```blade static + +``` +@endverbatim + + + ## Element ```php diff --git a/resources/views/docs/mobile/4/edge-components/bottom-nav.md b/resources/views/docs/mobile/4/edge-components/bottom-nav.md index fdf258bd..9836bf46 100644 --- a/resources/views/docs/mobile/4/edge-components/bottom-nav.md +++ b/resources/views/docs/mobile/4/edge-components/bottom-nav.md @@ -20,8 +20,10 @@ order: 120 A bottom navigation bar with up to 5 items. Used for your app's primary navigation. +One bar demonstrates the whole item API — an `active` tab, a `news` dot, and a `badge`: + @verbatim -```blade +```blade static + ` can contain up to 5 `` elements. ### Props - `id` - Unique identifier (required) -- `icon` - A named [icon](icons) (required) +- `icon` - A named [icon](icon#icon-name-reference) (required) - `label` - Accessibility label (required) - `url` - A URL to navigate to in the web view (required) - `active` - Highlight this item as active (optional, default: `false`) @@ -84,7 +95,7 @@ Any `url` that doesn't match a registered native route will exit to the web view -### `badge` example +Here's `badge` on a tab item:
@@ -95,23 +106,23 @@ Any `url` that doesn't match a registered native route will exit to the web view ## Builder API When a `` is supplied by a [layout](../the-basics/layouts), you build it fluently with the `TabBar` -and `Tab` builders rather than writing it in Blade. +and `Tab` builders rather than writing it in Blade. This is the same bar as the [Overview](#overview) example: ```php use Native\Mobile\Edge\Layouts\Builders\Tab; use Native\Mobile\Edge\Layouts\Builders\TabBar; TabBar::make() - ->dark() - ->activeColor('#0891b2') ->labelVisibility('labeled') - ->backgroundColor('#0F172A') - ->textColor('#94A3B8') - ->add(Tab::link('Chats', '/syncup', icon: 'chat_bubble')->badge('2')) - ->add(Tab::link('Friends', '/syncup/friends', icon: 'person.3.fill')->news()) - ->add(Tab::link('Profile', '/syncup/profile', icon: 'person')->active()); + ->activeColor('#0891b2') + ->add(Tab::link('Home', '/home', icon: 'home')->active()) + ->add(Tab::link('Friends', '/friends', icon: 'person.3.fill')->news()) + ->add(Tab::link('Profile', '/profile', icon: 'person')->badge('3')); ``` +To force a dark bar regardless of the system theme, chain `->dark()` — or take full control with +`->backgroundColor('#0F172A')->textColor('#94A3B8')`, which wins over `dark()`'s default. + ### `TabBar` methods - `make()` - Create a new builder @@ -126,7 +137,7 @@ TabBar::make() - `link(string $label, string $url, ?string $icon = null)` - Build a tab. The id defaults to the label slugified - `id(string $id)` - Override the auto-generated id -- `icon(string $icon)` - A named [icon](icons) +- `icon(string $icon)` - A named [icon](icon#icon-name-reference) - `badge(string $badge, ?string $color = null)` - Show a numeric/text badge - `news(bool $news = true)` - Show a red dot indicator - `active(bool $active = true)` - Mark this tab as active diff --git a/resources/views/docs/mobile/4/edge-components/bottom-sheet.md b/resources/views/docs/mobile/4/edge-components/bottom-sheet.md index 0ff6faa3..a8b875b6 100644 --- a/resources/views/docs/mobile/4/edge-components/bottom-sheet.md +++ b/resources/views/docs/mobile/4/edge-components/bottom-sheet.md @@ -9,7 +9,7 @@ A modal panel that slides up from the bottom of the screen. Use it for contextua that overlay the main content. Renders as SwiftUI's `.sheet` with `presentationDetents` on iOS and a Material3 `ModalBottomSheet` on Android. -Per Model 3, the container color resolves from `theme.surface`. For a custom surface wrap content in a +Per Material 3, the container color resolves from `theme.surface`. For a custom surface wrap content in a ``. @verbatim @@ -64,21 +64,21 @@ Accepts any EDGE elements as children. The children are rendered inside the shee - + Edit - + Share - + Delete @@ -107,7 +107,7 @@ Accepts any EDGE elements as children. The children are rendered inside the shee Add Item - + diff --git a/resources/views/docs/mobile/4/edge-components/button-group.md b/resources/views/docs/mobile/4/edge-components/button-group.md index dbe8253c..f71a5d32 100644 --- a/resources/views/docs/mobile/4/edge-components/button-group.md +++ b/resources/views/docs/mobile/4/edge-components/button-group.md @@ -13,10 +13,16 @@ Use this for short, mutually-exclusive choices that fit on one row. For more opt @verbatim ```blade +@php $period = 0; @endphp + + +Showing {{ ['Daily', 'Weekly', 'Monthly'][$period] }} stats ``` @endverbatim +`period` is a public int property on your component — the `@php` line stands in for `public int $period = 0;`. Tapping a segment syncs the new index back automatically, so anything echoing `$period` re-renders. + ## Props - `options` - Array of option labels (required, array of strings) @@ -32,11 +38,16 @@ Use this for short, mutually-exclusive choices that fit on one row. For more opt ## Two-way Binding -`native:model` binds the selected index to an integer property on your component: +`native:model` binds the selected index to an integer property on your component — declare it as +`public int $planTier = 1;` and the group keeps it in sync: @verbatim ```blade +@php $planTier = 1; @endphp + + +Selected plan: {{ $tiers[$planTier] }} ``` @endverbatim @@ -44,24 +55,38 @@ Use this for short, mutually-exclusive choices that fit on one row. For more opt ### Period picker +`reportRange` is a public int property on your component (`public int $reportRange = 2;`): + @verbatim ```blade +@php $reportRange = 2; @endphp + + +Report range: {{ ['Day', 'Week', 'Month', 'Year'][$reportRange] }} ``` @endverbatim ### With manual change handler +Instead of `native:model`, pass the current index with `:value` and handle changes yourself. +`$difficulty` is a public int property on your component, and `setDifficulty(int $index)` is the +method that receives the new index — assign it to `$difficulty` there: + @verbatim ```blade +@php $difficulty = 1; @endphp + + +Difficulty: {{ ['Easy', 'Medium', 'Hard'][$difficulty] }} ``` @endverbatim diff --git a/resources/views/docs/mobile/4/edge-components/button.md b/resources/views/docs/mobile/4/edge-components/button.md index 1bf0478a..ffc1c318 100644 --- a/resources/views/docs/mobile/4/edge-components/button.md +++ b/resources/views/docs/mobile/4/edge-components/button.md @@ -17,6 +17,8 @@ control drop to a [``](pressable) wrapping your own content. ``` @endverbatim +`@press` names a public method on your component — tapping this button calls `handleStart()`. + ## Props The label can be passed as the `label` attribute or as slot content between the tags. If both are set, `label` wins. @@ -28,8 +30,8 @@ Slot content is treated as plain text — nested tags are stripped and whitespac token solid; for a softer tonal fill, set opacity on the token itself (e.g. `'secondary' => 'fuchsia-500/70'` in `config/native-ui.php`) — see [Theming](../digging-deeper/theming) - `size` - `sm`, `md` (default), `lg` -- `icon` - A leading [icon](icons) name (optional) -- `icon-trailing` - A trailing [icon](icons) name (optional) +- `icon` - A leading [icon](icon#icon-name-reference) name (optional) +- `icon-trailing` - A trailing [icon](icon#icon-name-reference) name (optional) - `font` - Custom font for the label from `resources/fonts/`, by filename without extension (optional, string) — see [Text › Custom fonts](text#custom-fonts) - `line-height` - Label line height as a multiplier of the font size (optional, float) - `line-height-px` - Label line height as an absolute value in pixels (optional, float) @@ -73,7 +75,7 @@ attributes are intentionally dropped before reaching the renderer. @verbatim ```blade - + diff --git a/resources/views/docs/mobile/4/edge-components/canvas.md b/resources/views/docs/mobile/4/edge-components/canvas.md index 63c56d63..bae76506 100644 --- a/resources/views/docs/mobile/4/edge-components/canvas.md +++ b/resources/views/docs/mobile/4/edge-components/canvas.md @@ -10,13 +10,16 @@ children stack vertically by default. Use it as a semantic wrapper when grouping @verbatim ```blade - - + + ``` @endverbatim +Shapes take their fill from a `bg` attribute or any `bg-*` class (including `bg-theme-*` tokens), and corner +rounding from `rounded-*` classes. + ## Props All [shared layout and style attributes](layout) are supported. There are no canvas-specific props. @@ -29,6 +32,66 @@ Accepts any EDGE elements as children. Typically used with [shape primitives](sh For overlay-style layering of shapes use a [``](stack) instead — `` arranges children along the column main axis, which is rarely what you want for free-form drawing. +## Examples + +### Mini bar chart + +Shapes plus flex layout are enough for lightweight data graphics. A bottom-aligned row of rects with varying +heights makes a bar chart — vary the `opacity-*` class to get a tonal ramp from a single theme color: + +@verbatim +```blade + + + + + + + + +``` +@endverbatim + +In a real app you'd generate the rects with `@foreach` over a public array property on your component and +compute each `:height` from the data point. + +### Pulsing beacon + +Transform attributes (`:scale`, `:rotate`, `:translate-x`, `:translate-y`) combine with `animate-loop` and +`:animate-duration` to produce continuous, auto-reversing animations. Layer an animated circle behind a static +one in a stack to get a pulsing status beacon: + +@verbatim +```blade + + + + + + +``` +@endverbatim + +The loop oscillates the outer circle between its resting state and the declared `:scale` (and `opacity-*`), +reversing each cycle. `:animate-duration` is in milliseconds; add `animate-easing` to change the curve. + +### Concentric rings + +Layering same-center circles of decreasing size in a stack gives a bullseye — again using opacity steps of one +theme color so it works in both light and dark mode: + +@verbatim +```blade + + + + + + + +``` +@endverbatim + ## Element ```php diff --git a/resources/views/docs/mobile/4/edge-components/carousel.md b/resources/views/docs/mobile/4/edge-components/carousel.md index 21eb6e5d..16f6eb60 100644 --- a/resources/views/docs/mobile/4/edge-components/carousel.md +++ b/resources/views/docs/mobile/4/edge-components/carousel.md @@ -12,8 +12,8 @@ stack with `item-spacing` between items. ```blade @foreach($posts as $post) - - {{ $post->title }} + + {{ $post->title }} {{ $post->excerpt }} @endforeach @@ -66,14 +66,23 @@ wrapping a [``](row). @foreach($contacts as $contact) - - {{ $contact->name }} + + + {{ $contact->initials }} + + + + {{ $contact->name }} @endforeach ``` @endverbatim +Use `rounded-full` (a class) to make the avatar circular — the `border-radius` *attribute* is not +read on images. The initials layer underneath the image acts as a fallback: it shows while the +avatar is loading, or whenever `$contact->avatar` is empty. + ## Element ```php diff --git a/resources/views/docs/mobile/4/edge-components/checkbox.md b/resources/views/docs/mobile/4/edge-components/checkbox.md index e0a57516..12e8423e 100644 --- a/resources/views/docs/mobile/4/edge-components/checkbox.md +++ b/resources/views/docs/mobile/4/edge-components/checkbox.md @@ -9,14 +9,21 @@ A binary tick/untick control with an optional inline label. On iOS, renders as a (`checkmark.square.fill` / `square`) — SwiftUI has no native checkbox primitive. On Android, renders as a Material3 `Checkbox`. -Per Model 3, check/border/label colors come from the theme — no per-instance overrides. +Per Material 3, check/border/label colors come from the theme — no per-instance overrides. @verbatim ```blade +@php $agreed = false; @endphp + + +{{ $agreed ? 'Thanks for agreeing!' : 'Tap the box to agree' }} ``` @endverbatim +Here `agreed` is a public boolean property on your component — the `@php` line stands in for +`public bool $agreed = false;`. Toggling the box syncs the new state back automatically. + ## Props - `value` - Current checked state (optional, boolean, default: `false`) @@ -39,30 +46,48 @@ Margin classes position the checkbox; the check, border, and label colors come f ## Two-way Binding -Use `native:model` for automatic two-way binding with a boolean property on your component. The `live`, `blur`, -and `debounce` modifiers set `sync-mode` (and `debounce-ms`) for you, though for a discrete tap every toggle is a -single event. +Use `native:model` for automatic two-way binding with a public boolean property on your component. The `live`, +`blur`, and `debounce` modifiers set `sync-mode` (and `debounce-ms`) for you, though for a discrete tap every +toggle is a single event. @verbatim ```blade - +@php $subscribed = true; @endphp + + + +{{ $subscribed ? 'You are subscribed' : 'Not subscribed' }} ``` @endverbatim +`subscribed` is a public boolean property on your component (the `@php` line stands in for +`public bool $subscribed = true;`). Every toggle syncs the new value back, so the `{{ $subscribed }}` echo +updates as soon as you tap. + ## Examples ### Multiple options @verbatim ```blade +@php + $emailNotifications = true; + $smsNotifications = false; + $pushNotifications = true; +@endphp + + + Enabled: {{ ($emailNotifications ? 1 : 0) + ($smsNotifications ? 1 : 0) + ($pushNotifications ? 1 : 0) }} of 3 ``` @endverbatim +Each checkbox binds its own public boolean property; the summary line re-renders on every toggle. + ### Disabled @verbatim diff --git a/resources/views/docs/mobile/4/edge-components/chip.md b/resources/views/docs/mobile/4/edge-components/chip.md index 354e608e..d21c5b52 100644 --- a/resources/views/docs/mobile/4/edge-components/chip.md +++ b/resources/views/docs/mobile/4/edge-components/chip.md @@ -13,15 +13,20 @@ fully rounded and can be adjusted with `rounded-*` classes. @verbatim ```blade +@php $filterVerified = false; @endphp + ``` @endverbatim +`filterVerified` is a public boolean property on your component — the `@php` line stands in for +`public bool $filterVerified = false;`. + ## Props - `label` - Chip text (optional, string). Can also be passed as the first argument to `make()` - `selected` / `value` - Whether the chip is active (optional, boolean, default: `false`) -- `icon` - Leading [icon](icons) name (optional, string) +- `icon` - Leading [icon](icon#icon-name-reference) name (optional, string) - `disabled` - Disable the chip (optional, boolean, default: `false`) - `a11y-label` - Accessibility label (optional) - `a11y-hint` - Accessibility hint (optional) @@ -36,17 +41,28 @@ fully rounded and can be adjusted with `rounded-*` classes. @verbatim ```blade +@php $filterOnSale = false; @endphp + + + + {{ $filterOnSale ? 'Showing sale items only' : 'Showing everything' }} + ``` @endverbatim +Toggling the chip syncs the new boolean back to `filterOnSale` automatically, and anything that reads the +property — like the `{{ $filterOnSale ? ... }}` echo above — re-renders with the new value. + ## Examples ### Filter chip row @verbatim ```blade - +@php $filter = 'all'; @endphp + + @@ -54,10 +70,15 @@ fully rounded and can be adjusted with `rounded-*` classes. ``` @endverbatim +Here `$filter` is a public string property and `setFilter()` is a public method on your component that assigns it — +driving `selected` from one property keeps the row single-select. + ### With icon @verbatim ```blade +@php $onlyVerified = false; @endphp + ``` @endverbatim diff --git a/resources/views/docs/mobile/4/edge-components/column.md b/resources/views/docs/mobile/4/edge-components/column.md index 67ad083d..23773244 100644 --- a/resources/views/docs/mobile/4/edge-components/column.md +++ b/resources/views/docs/mobile/4/edge-components/column.md @@ -42,8 +42,23 @@ Everything else from the shared list applies the same as on any element (`w-*`, ### Full-screen layout with safe area +A column at the page root typically fills the screen and pushes actions to the bottom with a spacer: + @verbatim ```blade + + My App + + + +``` +@endverbatim + +The full-screen version below adds `safe-area` at the page root so content clears the notch and home +indicator — run it in your app to see it edge-to-edge: + +@verbatim +```blade static My App @@ -80,16 +95,21 @@ Everything else from the shared list applies the same as on any element (`w-*`, ### Space-between distribution +`justify-between` spreads children across the column's height, placing the leftover space between them: + @verbatim ```blade - - Top - Middle - Bottom + + Top + Middle + Bottom ``` @endverbatim +Distribution needs a bounded height to work with — on a real screen you would typically use `h-full` at the +page root; the fixed `h-[220]` here just gives the preview a bounded height to distribute. + ## Element ```php 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 7e29ddbf..63da331e 100644 --- a/resources/views/docs/mobile/4/edge-components/gesture-area.md +++ b/resources/views/docs/mobile/4/edge-components/gesture-area.md @@ -10,7 +10,7 @@ Captures a vertical pan/drag gesture over its content and writes the translation Children render normally — gesture detection wraps the whole content frame. @verbatim -```blade +```blade static @php $drag = \Native\Mobile\Edge\SharedValue::make(); @endphp @@ -21,6 +21,10 @@ Children render normally — gesture detection wraps the whole content frame. ``` @endverbatim +This example needs a real app to try out: the drag runs entirely on the UI thread against a live +`SharedValue` bound from your component, so there's no inline preview here — drop the snippet into a +screen in your app and drag the card. + ## Props - `pan-y` - A [`SharedValue`](../digging-deeper/gestures) that receives the vertical drag translation (required for diff --git a/resources/views/docs/mobile/4/edge-components/icon.md b/resources/views/docs/mobile/4/edge-components/icon.md index fef4c425..03fd6547 100644 --- a/resources/views/docs/mobile/4/edge-components/icon.md +++ b/resources/views/docs/mobile/4/edge-components/icon.md @@ -5,12 +5,14 @@ order: 230 ## Overview -Displays a platform-native icon. On iOS, icons render as SF Symbols. On Android, icons render as Material Icons. -A smart mapping system translates common icon names across platforms automatically. +Displays a platform-native icon. On iOS, icons render as [SF Symbols](https://developer.apple.com/sf-symbols/); +on Android, as [Material Icons](https://fonts.google.com/icons?icon.set=Material+Icons). You don't need to worry about +the differences — use one consistent icon name and EDGE's smart mapping system translates it to the right platform +symbol automatically. @verbatim ```blade - + ``` @endverbatim @@ -18,11 +20,11 @@ A smart mapping system translates common icon names across platforms automatical All [shared layout and style attributes](layout) are supported, plus: -- `name` - Icon name (required unless `ios`/`android` are given, string). See the [Icons](icons) reference -- `ios` / `android` - Per-platform overrides: an [SF Symbol](icons) name for iOS and a [Material Icon](icons) name +- `name` - Icon name (required unless `ios`/`android` are given, string). See the [Icon name reference](#icon-name-reference) +- `ios` / `android` - Per-platform overrides: an [SF Symbol](#ios-sf-symbols) name for iOS and a [Material Icon](#android-material-icons) name for Android, so one tag renders the right symbol on each platform. Use in place of `name` when the platforms need different icons (``). When bound with `:ios` / `:android`, - these also accept enum cases directly — `:ios="Ios::Gearshape"`, `:android="Android::Settings"` + these also accept enum cases directly — see [Typed icon enums](#typed-icon-enums) - `size` - Icon size in dp (optional, float, default: `24`) - `color` - Icon color as hex string (optional, default: platform default) - `dark-color` - Icon color when the device is in dark mode, as a hex string (optional). Overrides `color` in dark mode @@ -31,8 +33,8 @@ All [shared layout and style attributes](layout) are supported, plus: @@ -43,10 +45,10 @@ and platform-specific usage, see the [Icons](icons) reference page. @verbatim ```blade - - - - + + + + ``` @endverbatim @@ -67,13 +69,13 @@ and platform-specific usage, see the [Icons](icons) reference page. @verbatim ```blade - + No messages ``` @endverbatim -### Platform-specific icon +### Platform-specific icons Give each platform its own symbol with the `ios` / `android` attributes — resolution happens per platform, so one tag renders the right icon on each: @@ -84,18 +86,51 @@ tag renders the right icon on each: ``` @endverbatim -Or bind enum cases directly with `:ios` / `:android`: +### Typed icon enums + +Bind `:ios` / `:android` to pass enum cases instead of strings for typed, autocompletable symbol names. Import +the enums into your Blade view with `@@use` first — compiled views have no namespace, so a bare `Ios::Gearshape` +won't resolve: @verbatim ```blade +@use('App\Icons\Ios') +@use('App\Icons\Android') + ``` @endverbatim +The `AndroidOutlined` enum renders the outlined Material style instead of the filled one: + +@verbatim +```blade +@use('App\Icons\Ios') +@use('App\Icons\AndroidOutlined') + + +``` +@endverbatim + +You can also combine a shared `name` with a per-platform enum override: + +@verbatim +```blade +@use('App\Icons\Ios') + + +``` +@endverbatim + +If you'd rather skip the `@@use` import, fully-qualified cases work anywhere: +`:ios="\App\Icons\Ios::Gearshape"`. + +## How names resolve + +Every icon name — whether passed to `` or to the `icon` attribute of any other EDGE component — goes +through a four-tier resolution strategy: + +1. **Direct platform icons** - On iOS, if the name contains a `.` it's used as a direct SF Symbol path (e.g., `car.side.fill`). On Android, any Material Icon ligature name works directly (e.g., `shopping_cart`) +2. **Manual mapping** - Explicit mappings for common icons and aliases (e.g., `home`, `settings`, `user`) +3. **Smart fallback** - Normalizes unmapped icon names to a platform equivalent +4. **Default fallback** - Uses a circle icon if no match is found + +This approach means you can use intuitive icon names for common cases, leverage direct platform icons for advanced use +cases, and get consistent results across iOS and Android. + +### iOS (SF Symbols) + +On iOS, icons render as SF Symbols. Manual mappings convert common icon names to their SF Symbol equivalents. +For example: + +- `home` → `house.fill` +- `settings` → `gearshape.fill` +- `check` → `checkmark.circle.fill` + +Any name containing a `.` bypasses the mapping and is used as a direct SF Symbol path. Dotted paths are iOS-only, +so pair them with an `android` override: + +@verbatim +```blade + +``` +@endverbatim + +If a name isn't manually mapped and isn't a dotted path, the smart fallback lower-cases it and strips dashes and +underscores (`archive-box` → `archivebox`). It deliberately does **not** guess filled or circled variations — many +SF Symbols ship their plain glyph at the bare name, so when you want the filled variant, ask for it explicitly +(`archivebox.fill`, or the `Ios::ArchiveboxFill` enum case). + +### Android (Material Icons) + +On Android, icons render using a lightweight font-based approach that supports the entire Material Icons library. You +can use any Material Icon by its ligature name directly (e.g., `shopping_cart`, `qr_code_2`) — no mapping required. + +Manual mappings provide convenient aliases for common icon names. For example: + +- `home` → `home` +- `settings` → `settings` +- `check` → `check` +- `cart` → `shopping_cart` + +## Icons in other components + +Every EDGE component with an `icon` attribute resolves names through this same system — pass it the same names you +would give ``: + +@verbatim +```blade + +``` +@endverbatim + +The PHP Element builders take per-platform overrides everywhere too: any builder with an icon accepts +`icon(?string $name = null, IosSymbol|string|null $ios = null, AndroidSymbol|string|null $android = null)`, so you can +pass a shared name, `ios:` / `android:` named arguments, or both. + +For Blade components whose tag only takes a single `icon` string, pick the platform variant with the `System` facade: + +@verbatim +```blade + +``` +@endverbatim + +## Icon name reference + +All icons listed here are manually mapped and guaranteed to work consistently across iOS and Android. + +### Navigation + +| Icon | Description | +|------|-------------| +| `dashboard` | Grid-style dashboard view | +| `home` | House/home screen | +| `menu` | Three-line hamburger menu | +| `settings` | Gear/settings | +| `account`, `profile`, `user` | User account or profile | +| `person` | Single person | +| `people`, `connections`, `contacts` | Multiple people | +| `group`, `groups` | Group of people | + +### Business & Commerce + +| Icon | Description | +|------|-------------| +| `orders`, `receipt` | Receipt or order | +| `cart`, `shopping` | Shopping cart | +| `shop`, `store` | Store or storefront | +| `products`, `inventory` | Products or inventory | + +### Charts & Data + +| Icon | Description | +|------|-------------| +| `chart`, `barchart` | Bar chart | +| `analytics` | Analytics/analysis | +| `summary`, `report`, `assessment` | Summary or report | + +### Time & Scheduling + +| Icon | Description | +|------|-------------| +| `clock`, `schedule`, `time` | Clock or time | +| `calendar` | Calendar | +| `history` | History or recent | + +### Actions + +| Icon | Description | +|------|-------------| +| `add`, `plus` | Add or create new | +| `edit` | Edit or modify | +| `delete` | Delete or remove | +| `save` | Save | +| `search` | Search | +| `filter` | Filter | +| `refresh` | Refresh or reload | +| `share` | Share | +| `download` | Download | +| `upload` | Upload | + +### Communication + +| Icon | Description | +|------|-------------| +| `notifications` | Notifications or alerts | +| `message` | Message or SMS | +| `email`, `mail` | Email | +| `chat` | Chat or conversation | +| `phone` | Phone or call | + +### Navigation Arrows + +| Icon | Description | +|------|-------------| +| `back` | Back or previous | +| `forward` | Forward or next | +| `up` | Up arrow | +| `down` | Down arrow | + +### Status + +| Icon | Description | +|------|-------------| +| `check`, `done` | Check or complete | +| `close` | Close or dismiss | +| `warning` | Warning | +| `error` | Error | +| `info` | Information | + +### Authentication + +| Icon | Description | +|------|-------------| +| `login` | Login | +| `logout`, `exit` | Logout or exit | +| `lock` | Locked | +| `unlock` | Unlocked | + +### Content + +| Icon | Description | +|------|-------------| +| `favorite`, `heart` | Favorite or like | +| `star` | Star or rating | +| `bookmark` | Bookmark | +| `image`, `photo` | Image or photo | +| `image-plus` | Add photo | +| `video` | Video | +| `folder` | Folder | +| `folder-lock` | Locked folder | +| `file`, `description` | Document or file | +| `book-open` | Book | +| `newspaper`, `news`, `article` | News or article | + +### Device & Hardware + +| Icon | Description | +|------|-------------| +| `camera` | Camera | +| `qr`, `qrcode`, `qr-code` | QR code scanner | +| `device-phone-mobile`, `smartphone` | Mobile phone | +| `vibrate` | Vibration | +| `bell` | Bell or notification | +| `finger-print`, `fingerprint` | Fingerprint or biometric | +| `light-bulb`, `lightbulb`, `flashlight` | Light bulb or flashlight | +| `map`, `location` | Map or location | +| `globe-alt`, `globe`, `web` | Globe or web | +| `bolt`, `flash` | Lightning bolt or flash | + +### Audio & Volume + +| Icon | Description | +|------|-------------| +| `speaker`, `speaker-wave` | Speaker with sound | +| `volume-up` | Volume up | +| `volume-down` | Volume down | +| `volume-mute`, `mute` | Muted | +| `volume-off` | Volume off | +| `music`, `audio`, `music-note` | Music or audio | +| `microphone`, `mic` | Microphone | + +### Miscellaneous + +| Icon | Description | +|------|-------------| +| `help` | Help or question | +| `about`, `information-circle` | Information or about | +| `more` | More options | +| `list` | List view | +| `visibility` | Visible | +| `visibility_off` | Hidden | + +## Finding icons + +Browse the complete Material Icons library at [Google Fonts Icons](https://fonts.google.com/icons). Use the icon name +exactly as shown (with underscores, e.g., `shopping_cart`, `qr_code_2`). + +For the complete SF Symbols library, download the [SF Symbols app](https://developer.apple.com/sf-symbols/) for macOS. +This [community Figma file](https://www.figma.com/community/file/1549047589273604548) is another great starting point, +though not comprehensive. + + + +Icons carry meaning that users recognize across apps, so stay consistent: use the same icon name for the same action +throughout your app. And if you rely on auto-converted names, test that they appear correctly on both platforms. + ## Element ```php diff --git a/resources/views/docs/mobile/4/edge-components/icons.md b/resources/views/docs/mobile/4/edge-components/icons.md deleted file mode 100644 index 6b8fe876..00000000 --- a/resources/views/docs/mobile/4/edge-components/icons.md +++ /dev/null @@ -1,312 +0,0 @@ ---- -title: Icons -order: 240 ---- - -## Overview - -NativePHP EDGE components use a smart icon mapping system that automatically converts icon names to platform-specific -icons. On iOS, icons render as [SF Symbols](https://developer.apple.com/sf-symbols/), while Android uses -[Material Icons](https://fonts.google.com/icons?icon.set=Material+Icons). - -You don't need to worry about the differences! Just use a single, consistent icon name in your components, and the EDGE -handles the platform translation automatically. - -## How It Works - -The icon system uses a four-tier resolution strategy: - -1. **Direct Platform Icons** - On iOS, if the name contains a `.` it's used as a direct SF Symbol path (e.g., `car.side.fill`). On Android, any Material Icon ligature name works directly (e.g., `shopping_cart`). -2. **Manual Mapping** - Explicit mappings for common icons and aliases (e.g., `home`, `settings`, `user`) -3. **Smart Fallback** - Attempts to auto-convert unmapped icon names to platform equivalents -4. **Default Fallback** - Uses a circle icon if no match is found - -This approach means you can use intuitive icon names for common cases, leverage direct platform icons for advanced use -cases, and get consistent results across iOS and Android. - -## Platform Differences - -### iOS (SF Symbols) - -On iOS, icons render as SF Symbols. Manual mappings convert common icon names to their SF Symbol equivalents. -For example: - -- `home` → `house.fill` -- `settings` → `gearshape.fill` -- `check` → `checkmark.circle.fill` - -If an icon name isn't manually mapped, the system attempts to find a matching SF Symbol by trying variations like -`.fill`, `.circle.fill`, and `.square.fill`. - -### Android (Material Icons) - -On Android, icons render using a lightweight font-based approach that supports the entire Material Icons library. You -can use any Material Icon by its ligature name directly (e.g., `shopping_cart`, `qr_code_2`). - -Manual mappings provide convenient aliases for common icon names. For example: - -- `home` → `home` -- `settings` → `settings` -- `check` → `check` -- `cart` → `shopping_cart` - -## Direct Platform Icons - -For advanced use cases, you can use platform-specific icon names directly. - -### iOS SF Symbols - -On iOS, include a `.` in the icon name to use an SF Symbol path directly: - -@verbatim -```blade - - - -``` -@endverbatim - -### Android Material Icons - -On Android, use any Material Icon ligature name (with underscores): - -@verbatim -```blade - - - -``` -@endverbatim - -## Platform-Specific Icons - -When a single mapped name won't do, give each platform its own symbol. The [``](icon) component accepts -`ios` and `android` attributes that resolve per platform, so one tag renders the right icon on each: - -@verbatim -```blade - -``` -@endverbatim - -Bind with `:ios` / `:android` to pass enum cases directly for typed, autocompletable symbol names: - -@verbatim -```blade - -``` -@endverbatim - -The `App\Icons\Ios` and `App\Icons\Android` enums are generated into your app by the -[native-ui](https://github.com/nativephp/native-ui) plugin. Run this once to create them: - -```shell -php artisan native-ui:generate-icons -``` - -For components that take a single `icon` attribute, pick the platform variant with the `System` facade: - -@verbatim -```blade - -``` -@endverbatim - -See the [Icon](icon) reference for the full per-platform API. - -## Basic Usage - -Use the `icon` attribute in any EDGE component that supports icons, simply passing the name of the icon you wish to use: - -@verbatim -```blade - -``` -@endverbatim - -## Icon Reference - -All icons listed here are manually mapped and guaranteed to work consistently across iOS and Android. - -### Navigation - -| Icon | Description | -|------|-------------| -| `dashboard` | Grid-style dashboard view | -| `home` | House/home screen | -| `menu` | Three-line hamburger menu | -| `settings` | Gear/settings | -| `account`, `profile`, `user` | User account or profile | -| `person` | Single person | -| `people`, `connections`, `contacts` | Multiple people | -| `group`, `groups` | Group of people | - -### Business & Commerce - -| Icon | Description | -|------|-------------| -| `orders`, `receipt` | Receipt or order | -| `cart`, `shopping` | Shopping cart | -| `shop`, `store` | Store or storefront | -| `products`, `inventory` | Products or inventory | - -### Charts & Data - -| Icon | Description | -|------|-------------| -| `chart`, `barchart` | Bar chart | -| `analytics` | Analytics/analysis | -| `summary`, `report`, `assessment` | Summary or report | - -### Time & Scheduling - -| Icon | Description | -|------|-------------| -| `clock`, `schedule`, `time` | Clock or time | -| `calendar` | Calendar | -| `history` | History or recent | - -### Actions - -| Icon | Description | -|------|-------------| -| `add`, `plus` | Add or create new | -| `edit` | Edit or modify | -| `delete` | Delete or remove | -| `save` | Save | -| `search` | Search | -| `filter` | Filter | -| `refresh` | Refresh or reload | -| `share` | Share | -| `download` | Download | -| `upload` | Upload | - -### Communication - -| Icon | Description | -|------|-------------| -| `notifications` | Notifications or alerts | -| `message` | Message or SMS | -| `email`, `mail` | Email | -| `chat` | Chat or conversation | -| `phone` | Phone or call | - -### Navigation Arrows - -| Icon | Description | -|------|-------------| -| `back` | Back or previous | -| `forward` | Forward or next | -| `up` | Up arrow | -| `down` | Down arrow | - -### Status - -| Icon | Description | -|------|-------------| -| `check`, `done` | Check or complete | -| `close` | Close or dismiss | -| `warning` | Warning | -| `error` | Error | -| `info` | Information | - -### Authentication - -| Icon | Description | -|------|-------------| -| `login` | Login | -| `logout`, `exit` | Logout or exit | -| `lock` | Locked | -| `unlock` | Unlocked | - -### Content - -| Icon | Description | -|------|-------------| -| `favorite`, `heart` | Favorite or like | -| `star` | Star or rating | -| `bookmark` | Bookmark | -| `image`, `photo` | Image or photo | -| `image-plus` | Add photo | -| `video` | Video | -| `folder` | Folder | -| `folder-lock` | Locked folder | -| `file`, `description` | Document or file | -| `book-open` | Book | -| `newspaper`, `news`, `article` | News or article | - -### Device & Hardware - -| Icon | Description | -|------|-------------| -| `camera` | Camera | -| `qr`, `qrcode`, `qr-code` | QR code scanner | -| `device-phone-mobile`, `smartphone` | Mobile phone | -| `vibrate` | Vibration | -| `bell` | Bell or notification | -| `finger-print`, `fingerprint` | Fingerprint or biometric | -| `light-bulb`, `lightbulb`, `flashlight` | Light bulb or flashlight | -| `map`, `location` | Map or location | -| `globe-alt`, `globe`, `web` | Globe or web | -| `bolt`, `flash` | Lightning bolt or flash | - -### Audio & Volume - -| Icon | Description | -|------|-------------| -| `speaker`, `speaker-wave` | Speaker with sound | -| `volume-up` | Volume up | -| `volume-down` | Volume down | -| `volume-mute`, `mute` | Muted | -| `volume-off` | Volume off | -| `music`, `audio`, `music-note` | Music or audio | -| `microphone`, `mic` | Microphone | - -### Miscellaneous - -| Icon | Description | -|------|-------------| -| `help` | Help or question | -| `about`, `information-circle` | Information or about | -| `more` | More options | -| `list` | List view | -| `visibility` | Visible | -| `visibility_off` | Hidden | - -## Best Practices - -Icons have meaning and most users will associate the visual cues of icons and the underlying behavior or section of an -application across apps. So try to maintain consistent use of icons to help guide users through your app. - -- **Stay consistent** - Use the same icon name throughout your app for the same action -- **Test on both platforms** - If you use auto-converted icons, verify they appear correctly on iOS and Android - -## Finding Icons - -### Android Material Icons - -Browse the complete Material Icons library at [Google Fonts Icons](https://fonts.google.com/icons). Use the icon name -exactly as shown (with underscores, e.g., `shopping_cart`, `qr_code_2`). - -### iOS SF Symbols - -Browse SF Symbols using this [community Figma file](https://www.figma.com/community/file/1549047589273604548). While not -comprehensive, it's a great starting point for discovering available symbols. - -For the complete library, download the [SF Symbols app](https://developer.apple.com/sf-symbols/) for macOS. - - diff --git a/resources/views/docs/mobile/4/edge-components/image.md b/resources/views/docs/mobile/4/edge-components/image.md index 7f1484cc..86271d97 100644 --- a/resources/views/docs/mobile/4/edge-components/image.md +++ b/resources/views/docs/mobile/4/edge-components/image.md @@ -9,7 +9,13 @@ Displays an image from a URL. Loaded asynchronously by the native platform — ` @verbatim ```blade - + ``` @endverbatim @@ -40,7 +46,7 @@ The renderer collapses fit modes to two effective behaviors: `fit` and `fill`. M @verbatim ```blade - + ``` @endverbatim @@ -49,11 +55,11 @@ The renderer collapses fit modes to two effective behaviors: `fit` and `fill`. M @verbatim ```blade ``` @endverbatim @@ -61,24 +67,33 @@ The renderer collapses fit modes to two effective behaviors: `fit` and `fill`. M ### Tinted icon image @verbatim -```blade +```blade static ``` @endverbatim + + ### Image in a card @verbatim ```blade - - - - Article Title + + + + Article Title A brief description of the article. @@ -90,7 +105,7 @@ The renderer collapses fit modes to two effective behaviors: `fit` and `fill`. M ```php use Native\Mobile\Edge\Elements\Image; -Image::make('https://example.com/photo.jpg') +Image::make('https://picsum.photos/seed/nativephp/400/300') ->fit(2) ->tintColor('#7C3AED'); ``` diff --git a/resources/views/docs/mobile/4/edge-components/introduction.md b/resources/views/docs/mobile/4/edge-components/introduction.md index f1aadcbf..154c7722 100644 --- a/resources/views/docs/mobile/4/edge-components/introduction.md +++ b/resources/views/docs/mobile/4/edge-components/introduction.md @@ -82,7 +82,7 @@ interactive forms and navigation chrome. ## How It Works @verbatim -```blade +```blade static diff --git a/resources/views/docs/mobile/4/edge-components/layout.md b/resources/views/docs/mobile/4/edge-components/layout.md index 9c93019d..2c22151d 100644 --- a/resources/views/docs/mobile/4/edge-components/layout.md +++ b/resources/views/docs/mobile/4/edge-components/layout.md @@ -15,7 +15,7 @@ This page documents the shared attribute system that powers the layout engine ac Control element dimensions with width, height, and fill attributes. @verbatim -```blade +```blade static {{-- Fixed dimensions (in dp) --}} ... @@ -55,7 +55,7 @@ Padding and margin follow CSS shorthand conventions. Pass a single value for uni per-side control. @verbatim -```blade +```blade static {{-- Uniform padding --}} ... @@ -93,7 +93,7 @@ The layout engine uses a Flexbox-based system. Containers (column, row) arrange properties control how children grow, shrink, and align. @verbatim -```blade +```blade static {{-- Grow to fill remaining space --}} ... @@ -130,7 +130,7 @@ Alignment values are integers that map to standard flex alignment: | `4` | baseline | @verbatim -```blade +```blade static {{-- Center children on both axes --}} ... @@ -166,7 +166,7 @@ A child with `w-full` (or `h-full`) overrides its parent's `items-center` along Visual styling attributes that apply to any element. @verbatim -```blade +```blade static Tap, double tap, or long press me @@ -210,7 +210,7 @@ Respect the device's safe area insets (notch, home indicator, status bar) by add typically applied to your outermost column. @verbatim -```blade +```blade static {{-- Content will not overlap the notch or home indicator --}} @@ -229,7 +229,7 @@ chrome already handles safe-area insets for you. Hide elements without removing them from the tree. @verbatim -```blade +```blade static @@ -243,7 +243,7 @@ Hide elements without removing them from the tree. Override styles for dark mode using the `dark:` prefix with Tailwind classes, or pass a `dark` attribute array. @verbatim -```blade +```blade static {{-- Tailwind dark mode --}} @@ -261,7 +261,7 @@ EDGE includes a built-in Tailwind CSS parser that converts familiar utility clas the `class` attribute on any element. @verbatim -```blade +```blade static Styled with Tailwind diff --git a/resources/views/docs/mobile/4/edge-components/lazy-grid.md b/resources/views/docs/mobile/4/edge-components/lazy-grid.md index 560d61a4..9d923af4 100644 --- a/resources/views/docs/mobile/4/edge-components/lazy-grid.md +++ b/resources/views/docs/mobile/4/edge-components/lazy-grid.md @@ -15,9 +15,9 @@ of thumb is around 50 or more cells. @verbatim ```blade - - @foreach($icons as $icon) - + + @foreach (['star', 'heart', 'bell', 'bookmark', 'camera', 'paperplane', 'flag', 'gearshape'] as $icon) + @endforeach @@ -25,6 +25,8 @@ of thumb is around 50 or more cells. ``` @endverbatim +In a real app you would typically loop a collection property on your component (`$icons`) rather than a literal list. + ## Props - `columns` - Number of equal-width tracks the cells flow across. When `horizontal` is set, this becomes the number @@ -55,24 +57,26 @@ it be the screen's scroll container) to keep lazy composition. @verbatim ```blade - - @foreach($photos as $photo) + + @foreach (range(1, 9) as $i) - + @endforeach ``` @endverbatim +Swap `range(1, 9)` for your own `$photos` collection and bind `src` from each item (e.g. `$photo->url`). + ### Horizontal category shelves @verbatim -```blade +```blade static @foreach($products as $product) - + {{ $product->name }} @endforeach diff --git a/resources/views/docs/mobile/4/edge-components/list.md b/resources/views/docs/mobile/4/edge-components/list.md index 16e58934..1c3a59c2 100644 --- a/resources/views/docs/mobile/4/edge-components/list.md +++ b/resources/views/docs/mobile/4/edge-components/list.md @@ -72,18 +72,19 @@ 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. Toggling is interactive on [Android]; iOS renders a - static glyph -- `leadingRadio` - Boolean value for a leading radio button. Toggling is interactive on [Android]; iOS renders a - static glyph +- `leadingCheckbox` - Boolean value for a leading checkbox. 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; + static glyph otherwise ### Trailing slot (mutually exclusive) - `trailingIcon` - Icon name rendered as a trailing icon. Pair with `trailingIconIos` / `trailingIconAndroid` to override the [icon](icon) per platform - `trailingText` - Trailing text label -- `trailingCheckbox` - Boolean value for a trailing checkbox. Toggling is interactive on [Android]; iOS renders a - static glyph +- `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 - `trailing-a11y-label` - Accessibility label for the trailing icon button (recommended whenever @@ -120,9 +121,11 @@ All color props accept the full [color grammar](../digging-deeper/theming#color- - `on-swipe-delete` - Shortcut for a single destructive trailing swipe. For anything richer, use `trailing-actions` below. -Toggle changes and trailing icon-button taps are wired through the [Element](#element) callbacks rather than Blade -events. `onTrailingPress()` fires on both platforms when the trailing icon button is tapped. `onLeadingChange()` -and `onTrailingChange()` fire on [Android], where the checkbox / radio / switch controls are interactive. +- `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. ### Swipe actions @@ -135,18 +138,25 @@ definitions the user reveals by swiping the row. Each action is an array: - `tint` - Background color as a hex string - `role` - Set to `destructive` to render in the platform's delete style (trailing only) +Swipe actions only work on rows that are direct children of `` (or a ``) — +they are attached by the list renderer, so a standalone `` silently ignores them. + @verbatim ```blade - + + @foreach ($emails as $email) + + @endforeach + ``` @endverbatim @@ -204,6 +214,9 @@ ListSection::make('Fruits', ListItem::make('Apple'))->footer('1 item'); ### Swipe-to-delete with pull-to-refresh +The checkbox, swipe, and row press are three independent targets on one row: tapping the box fires +`on-leading-change`, swiping left fires `on-swipe-delete`, tapping anywhere else fires `@press`. + @verbatim ```blade @@ -212,6 +225,7 @@ ListSection::make('Fruits', ListItem::make('Apple'))->footer('1 item'); headline="{{ $task->title }}" supporting="{{ $task->due }}" leadingCheckbox="{{ $task->done }}" + on-leading-change="toggleTask({{ $task->id }})" trailingIcon="forward" on-swipe-delete="deleteTask({{ $task->id }})" @press="openTask({{ $task->id }})" @@ -221,13 +235,22 @@ ListSection::make('Fruits', ListItem::make('Apple'))->footer('1 item'); ``` @endverbatim +> [!NOTE] +> Pull-to-refresh needs to own the pull gesture, so it only fires when the list is the screen's scrolling +> container — inside another scroll view (like this docs page) the outer container wins the pull. Swipe and +> checkbox work inline; run the refresh on a dedicated screen. + ### Infinite scroll +`loadMore()` is a method on your component that fetches the next page and appends it to the collection the loop +renders — in a real app the loop is `@foreach ($posts as $post)` over your paginated results. The fixed `range()` +here just gives the demo enough rows to scroll before the end-reached trigger fires. + @verbatim ```blade - @foreach($posts as $post) - + @foreach (range(1, 15) as $i) + @endforeach ``` diff --git a/resources/views/docs/mobile/4/edge-components/menus.md b/resources/views/docs/mobile/4/edge-components/menus.md index f5f3bf5c..86df571f 100644 --- a/resources/views/docs/mobile/4/edge-components/menus.md +++ b/resources/views/docs/mobile/4/edge-components/menus.md @@ -10,9 +10,10 @@ standalone element — you build a list of actions and attach it with an attribu - `:menu` on a [button](button) or [pressable](pressable) — tapping opens the menu instead of firing `@press`. - `:trailing-menu` on a [list item](list) — opens from the row's trailing edge. +- `items()` on a nav-bar action — see [Menus in the nav bar](#menus-in-the-nav-bar) below. -All three share one item model: an array of `NavAction`, the same builder used for -[nav-bar menus](../the-basics/layouts#builder-reference). +All of them share one item model: an array of `NavAction`, the same builder used +[throughout layouts](../the-basics/layouts#builder-reference). ## Building the items @@ -64,6 +65,53 @@ Use `:trailing-menu` to open a menu from a row's trailing edge — a common patt ``` @endverbatim +## Menus in the nav bar + +The same `NavAction` builder powers pull-down menus on nav-bar (top bar) actions. Give an action sub-items +with `items()` and it renders as a menu that drops from the bar button instead of firing a plain press: + +```php +use Native\Mobile\Edge\Layouts\Builders\NavAction; +use Native\Mobile\Edge\Layouts\Builders\NavBarOptions; + +public function navigationOptions(): ?NavBarOptions +{ + return NavBarOptions::make() + ->action( + NavAction::make('share') + ->icon('share') + ->a11yLabel('Share') + ->press('share') + ) + ->action( + NavAction::make('more') + ->icon('ellipsis') + ->a11yLabel('More options') + ->items([ + NavAction::make('mute') + ->label('Mute') + ->icon(ios: 'bell.slash', android: 'notifications_off') + ->press('mute'), + NavAction::make('pin')->label('Pin')->icon('pin')->press('pin'), + NavAction::divider(), + NavAction::make('delete') + ->label('Delete') + ->icon('trash') + ->press('delete') + ->destructive(), + ]) + ); +} +``` + +Here `share` stays a plain press, while `more` opens a native pull-down (SwiftUI `Menu` / Compose `DropdownMenu`) +with dividers and destructive tinting, exactly like the inline menus above. This works in both stack and tab +layouts — you can also attach it directly in a layout definition via `NavBar::make()->action(...)` in your +layout's `navBar()`. + +> **Note** Menus are only supported on nav-bar actions. Bottom-nav / tab-bar items and the inline +> `` element render their actions as plain buttons — `items()` is ignored there. + ## Item reference The menu-relevant `NavAction` methods: @@ -73,6 +121,8 @@ The menu-relevant `NavAction` methods: - `label(string)` — the row text - `press(string $method)` — the component method to call when chosen - `url(string)` — navigate to a URL instead of calling a method +- `items(array $items)` — sub-items that turn a nav-bar action into a pull-down menu (nav-bar actions only) +- `a11yLabel(string)` — screen-reader label for icon-only actions - `destructive(bool = true)` — tint the item as destructive - `NavAction::divider()` — a separator row diff --git a/resources/views/docs/mobile/4/edge-components/modal.md b/resources/views/docs/mobile/4/edge-components/modal.md index af9cfefc..80d900b3 100644 --- a/resources/views/docs/mobile/4/edge-components/modal.md +++ b/resources/views/docs/mobile/4/edge-components/modal.md @@ -9,7 +9,7 @@ A full-screen modal overlay. Visibility is driven by the `visible` prop. Use a [ contextual actions; reach for `` when you want the entire screen covered (e.g. an onboarding flow, image preview, or detail view). -Per Model 3, backdrop and surface colors come from `theme.background`. The close icon uses `theme.onSurfaceVariant`. +Per Material 3, backdrop and surface colors come from `theme.background`. The close icon uses `theme.onSurfaceVariant`. @verbatim ```blade @@ -23,8 +23,8 @@ Per Model 3, backdrop and surface colors come from `theme.background`. The close - Details - {{ $description }} + Details + {{ $description }} @@ -90,7 +90,7 @@ Programmatically setting `visible` to `false` from PHP does not fire the callbac - Processing... + Processing... {{-- A real app closes this from PHP when the work finishes; the button stands in for that here since the modal can't be dismissed by the user. --}} diff --git a/resources/views/docs/mobile/4/edge-components/pressable.md b/resources/views/docs/mobile/4/edge-components/pressable.md index c7245432..5183bf03 100644 --- a/resources/views/docs/mobile/4/edge-components/pressable.md +++ b/resources/views/docs/mobile/4/edge-components/pressable.md @@ -13,13 +13,16 @@ provides a clear tap target that wraps multiple children. @verbatim ```blade - - {{ $item->name }} - {{ $item->description }} + + Account + Signed in as {{ $name }} — tap anywhere on the card ``` @endverbatim +`@press` names a method on your component — declare `public function openAccount(): void` and it runs when any +part of the card is tapped. + ## Props All [shared layout and style attributes](layout) are supported, plus: @@ -48,10 +51,10 @@ Accepts any EDGE elements as children. Children are arranged vertically (like a @press="selectItem({{ $item->id }})" class="w-full px-4 py-3" > - + - - {{ $item->name }} + + {{ $item->name }} {{ $item->subtitle }} @@ -64,30 +67,38 @@ Accepts any EDGE elements as children. Children are arranged vertically (like a ``` @endverbatim +Interpolate arguments straight into the handler — each row calls `selectItem()` on your component with its own id. + ### Card with tap and long press @verbatim ```blade - - {{ $post->title }} - {{ $post->excerpt }} - +@foreach ($posts as $post) + + {{ $post->title }} + {{ $post->excerpt }} + +@endforeach ``` @endverbatim +A tap calls `openDetail()`; holding the card calls `showOptions()` instead — one pressable can route each gesture to +a different component method. + ### Navigation with @navigate @verbatim ```blade - - {{ $item->name }} - +@foreach ($items as $item) + + {{ $item->name }} + +@endforeach ``` @endverbatim @@ -103,13 +114,14 @@ the animation stays smooth even while a handler is dispatching: @verbatim ```blade - {{ $post->title }} + Press and hold + The card scales down, dims, and nudges while pressed. ``` @endverbatim diff --git a/resources/views/docs/mobile/4/edge-components/progress-bar.md b/resources/views/docs/mobile/4/edge-components/progress-bar.md index 9186674d..7867373d 100644 --- a/resources/views/docs/mobile/4/edge-components/progress-bar.md +++ b/resources/views/docs/mobile/4/edge-components/progress-bar.md @@ -10,7 +10,7 @@ value (or with `indeterminate`), renders an animated wave. For a circular spinner use [``](activity-indicator) instead. -Per Model 3, the progress fill uses `theme.primary` and the track uses `theme.surfaceVariant`. The optional `color` +Per Material 3, the progress fill uses `theme.primary` and the track uses `theme.surfaceVariant`. The optional `color` prop is an escape hatch for non-theme containers. @verbatim @@ -40,16 +40,20 @@ prop is an escape hatch for non-theme containers. @verbatim ```blade +@php $progress = 0.65; @endphp + - - Uploading - {{ round($progress * 100) }}% + + Uploading + {{ round($progress * 100) }}% ``` @endverbatim +Here `$progress` stands in for a public property on your component — declare `public float $progress = 0.65;` and update it as the work advances; the bar and the percentage label track it automatically. + ### Indeterminate @verbatim @@ -66,6 +70,12 @@ prop is an escape hatch for non-theme containers. ``` @endverbatim + + ## Element ```php diff --git a/resources/views/docs/mobile/4/edge-components/radio-group.md b/resources/views/docs/mobile/4/edge-components/radio-group.md index 28c60984..989f8fcf 100644 --- a/resources/views/docs/mobile/4/edge-components/radio-group.md +++ b/resources/views/docs/mobile/4/edge-components/radio-group.md @@ -8,10 +8,12 @@ order: 310 A single-choice container holding `` children. The group owns the selection; each child declares its own `value` and label. -Per Model 3, all colors come from theme tokens. +Per Material 3, all colors come from theme tokens. @verbatim ```blade +@php $plan = 'pro'; @endphp + @@ -20,6 +22,9 @@ Per Model 3, all colors come from theme tokens. ``` @endverbatim +Here `plan` is a public string property on your component — the `@php` line stands in for +`public string $plan = 'pro';`. + ## Props (Group) - `value` - Currently selected `value` string (optional). Use `native:model` for two-way binding @@ -34,17 +39,25 @@ Per Model 3, all colors come from theme tokens. ## Two-way Binding -`native:model` binds the group's selected value to a string property on your component: +`native:model` binds the group's selected value to a public string property on your component: @verbatim ```blade - - - +@php $billing = 'monthly'; @endphp + + + + + +Billed: {{ $billing }} ``` @endverbatim +`billing` is a public string property on your component (the `@php` line stands in for +`public string $billing = 'monthly';`). Picking an option syncs the new value back automatically, +so the `{{ $billing }}` echo updates as soon as you tap a different option. + ## Children `` declares a single option: @@ -61,17 +74,25 @@ Per Model 3, all colors come from theme tokens. @verbatim ```blade - +@php $selectedPlan = 'free'; @endphp + + + +Current plan: {{ $selectedPlan }} ``` @endverbatim ### Manual handler +When you need side effects beyond a simple property write, bind `:value` yourself and handle +`@change` — `$shippingMethod` is a public string property and `setShipping()` a public method on +your component, receiving the new value as its parameter: + @verbatim ```blade diff --git a/resources/views/docs/mobile/4/edge-components/refreshable.md b/resources/views/docs/mobile/4/edge-components/refreshable.md index 8811e657..f78ee07a 100644 --- a/resources/views/docs/mobile/4/edge-components/refreshable.md +++ b/resources/views/docs/mobile/4/edge-components/refreshable.md @@ -11,17 +11,19 @@ component method, and the platform handles the gesture, spinner, and physics for their native pull-to-refresh spinner, with system haptics on iOS. @verbatim -```blade +```blade static @foreach($items as $item) - {{ $item->title }} + {{ $item->name }} @endforeach ``` @endverbatim +The refreshable container wants the full height of the screen — run it in your app to feel the pull gesture. + ## Events - `@refresh` - Component method called when the user pulls down past the release threshold (optional, string) @@ -50,7 +52,7 @@ content — cards, a [``](column), a dashboard — rather than a ### Refreshable feed @verbatim -```blade +```blade static @foreach($posts as $post) diff --git a/resources/views/docs/mobile/4/edge-components/row.md b/resources/views/docs/mobile/4/edge-components/row.md index a957e7de..b3311954 100644 --- a/resources/views/docs/mobile/4/edge-components/row.md +++ b/resources/views/docs/mobile/4/edge-components/row.md @@ -12,7 +12,7 @@ and inline groupings. ```blade - 4.8 Rating + 4.8 Rating ``` @endverbatim @@ -43,9 +43,9 @@ Everything else from the shared list applies the same as on any element (`w-*`, @verbatim ```blade - Title + Title - + ``` @endverbatim @@ -55,9 +55,9 @@ Everything else from the shared list applies the same as on any element (`w-*`, @verbatim ```blade - One - Two - Three + One + Two + Three ``` @endverbatim diff --git a/resources/views/docs/mobile/4/edge-components/scroll-view.md b/resources/views/docs/mobile/4/edge-components/scroll-view.md index 2a47811e..60dba1cb 100644 --- a/resources/views/docs/mobile/4/edge-components/scroll-view.md +++ b/resources/views/docs/mobile/4/edge-components/scroll-view.md @@ -11,6 +11,21 @@ Android and `ScrollView` on iOS for efficient rendering. @verbatim ```blade + + + @foreach (range(1, 20) as $i) + Scrollable row {{ $i }} + @endforeach + + +``` +@endverbatim + +The fixed `h-[240]` here just gives the preview a bounded viewport so the content overflows and scrolls. On a real +screen you'd typically let the scroll view fill the page instead: + +@verbatim +```blade static @foreach($items as $item) @@ -50,12 +65,15 @@ scrollable content. ### Vertical list +A full-screen list of posts. `safe-area` keeps the content clear of the notch and home indicator, so this one is +meant for a real page root — run it in your app to see it edge-to-edge: + @verbatim -```blade - - +```blade static + + @foreach($posts as $post) - + {{ $post->title }} {{ $post->excerpt }} @@ -76,8 +94,7 @@ scrollable content. :width="120" :height="80" center - bg="#F1F5F9" - :border-radius="12" + class="bg-theme-surface-variant rounded-xl" > {{ $category->name }} @@ -89,9 +106,12 @@ scrollable content. ### Full-page scrollable layout +Another page-root pattern — `h-full` and `safe-area` only make sense against a real screen, so try this one in your +app: + @verbatim -```blade - +```blade static + Welcome @@ -105,9 +125,12 @@ scrollable content. ### Chat-style stick-to-bottom +The view opens at the latest message and stays pinned to the bottom as new content arrives. The fixed `h-[200]` +bounds the preview so there's something to scroll — in a real chat screen you'd use `fill` instead: + @verbatim ```blade - + @foreach($messages as $message) {{ $message->body }} diff --git a/resources/views/docs/mobile/4/edge-components/select.md b/resources/views/docs/mobile/4/edge-components/select.md index cff5942c..ae31ec2b 100644 --- a/resources/views/docs/mobile/4/edge-components/select.md +++ b/resources/views/docs/mobile/4/edge-components/select.md @@ -8,19 +8,24 @@ order: 350 A single-choice dropdown picker over a flat list of strings. On iOS, renders as a SwiftUI `Menu` (popover); on Android, as an M3 `ExposedDropdownMenuBox` with an outlined trigger. -Per Model 3, colors and borders come from theme tokens. +Per Material 3, colors and borders come from theme tokens. @verbatim ```blade +@php $shippingCountry = null; @endphp + ``` @endverbatim +Here `shippingCountry` is a public string property on your component (the `@php` line stands in for +`public ?string $shippingCountry = null;`) — while it is `null`, the placeholder shows. + Options are a flat list of display strings — pass the strings you want shown, and the selected string is the value bound back to your component. An associative `value => label` array is flattened to its labels, so the displayed text is what you get. @@ -51,21 +56,36 @@ Margin classes position the picker; its colors and borders come from the theme. @verbatim ```blade - +@php $country = 'Canada'; @endphp + + + +Shipping to: {{ $country }} ``` @endverbatim +`country` is a public string property on your component (the `@php` line stands in for +`public string $country = 'Canada';`), and `$countries` is an array of option strings. Picking an option +syncs the selected string back automatically — no `@change` handler needed — so the echoed text updates +with the selection. + ## Examples ### Country picker @verbatim ```blade +@php $destination = 'Japan'; @endphp + ``` @endverbatim diff --git a/resources/views/docs/mobile/4/edge-components/shapes.md b/resources/views/docs/mobile/4/edge-components/shapes.md index 71e57ed2..8aa3d94a 100644 --- a/resources/views/docs/mobile/4/edge-components/shapes.md +++ b/resources/views/docs/mobile/4/edge-components/shapes.md @@ -15,19 +15,21 @@ These are typically placed inside a [``](canvas) or used standalo ## Rect -A rectangle filled with `bg`. All [shared layout and style attributes](layout) apply, so border, radius, opacity, -and elevation behave as on any other element. +A rectangle filled with `bg`. All [shared layout and style attributes](layout) apply — use Tailwind-style classes +(`rounded-*`, `border-*`, `opacity-*`, `shadow-*`) for radius, borders, opacity, and elevation, just as on any +other element. @verbatim ```blade - + ``` @endverbatim ### Props -- `left` - X position offset in dp (optional, float). Used inside an absolutely-positioned parent -- `top` - Y position offset in dp (optional, float) +The `left` / `top` position props are accepted by the PHP element but are not currently read by the iOS or Android +renderers. To offset a rect inside a parent, use absolute-positioning classes instead — e.g. +`class="absolute top-[8] left-[8]"`. `` is a self-closing element, so it doesn't accept tag children. To layer content on top of the fill, overlay the rect and your content inside a [``](stack). In PHP, the `Rect` element accepts children via @@ -46,33 +48,35 @@ perfect circle use equal `width` and `height`. ### Props -- `left` - X position offset in dp (optional, float) -- `top` - Y position offset in dp (optional, float) +As with ``, the `left` / `top` position props exist on the PHP element but the renderers don't read +them — position circles with absolute-positioning classes (`class="absolute top-[8] left-[8]"`) or by centering +them in a [``](stack). `` is a self-closing element. It does not accept children. ## Line -A 1pt horizontal rule across the available width. +A horizontal rule. Style it with `border-*` classes: @verbatim -```blade - +```blade static + ``` @endverbatim ### Props -All [shared layout and style attributes](layout) are supported. The most useful: +All [shared layout and style attributes](layout) are supported. Set the stroke through classes: -- `border-color` - Line color as hex string (optional, default: platform separator color) -- `border-width` - Stroke thickness in dp (optional, float, default: `1`) +- `border-theme-outline` / `border-[#94A3B8]` - Line color (default: platform separator color) +- `border` / `border-2` / `border-4` - Stroke thickness in dp (default: `1`) @@ -93,7 +97,7 @@ Overlay the label on a filled rect with a ``. Give the rect an exp @verbatim ```blade - + New ``` @@ -101,9 +105,17 @@ Overlay the label on a filled rect with a ``. Give the rect an exp ### Decorative separator +@verbatim +```blade static + +``` +@endverbatim + +For a full-width rule that renders consistently on both platforms today, use a divider instead: + @verbatim ```blade - + ``` @endverbatim diff --git a/resources/views/docs/mobile/4/edge-components/side-nav.md b/resources/views/docs/mobile/4/edge-components/side-nav.md index 7462227b..4e81ab28 100644 --- a/resources/views/docs/mobile/4/edge-components/side-nav.md +++ b/resources/views/docs/mobile/4/edge-components/side-nav.md @@ -21,7 +21,7 @@ order: 370 A slide-out navigation drawer with support for groups, headers, and dividers. @verbatim -```blade +```blade static +@php $brightness = 60; @endphp + + ``` @endverbatim +`brightness` is a public property on your component — the `@php` line stands in for +`public int $brightness = 60;`. + ## Props - `value` - Current value (optional, float) @@ -41,19 +46,26 @@ Margin classes position the slider; the active track and thumb colors come from @verbatim ```blade +@php $intensity = 50; @endphp + {{-- Every drag tick fires --}} - + {{-- Only fires on drag release --}} - + {{-- Coalesce ticks into one event after 300ms idle --}} - + + +Intensity: {{ $intensity }} ``` @endverbatim -`live` is the default and stress-tests the runtime's round-trip; `blur` is the most efficient for unsteady hands; -`debounce` is the middle ground. Omit the interval (`native:model.debounce`) and it defaults to 300ms. +`intensity` is a public property on your component (`public int $intensity = 50;`). All three sliders bind +the same property, so dragging any one of them syncs the others and the echo — notice *when* each modifier +pushes its update. `live` is the default and stress-tests the runtime's round-trip; `blur` is the most +efficient for unsteady hands; `debounce` is the middle ground. Omit the interval (`native:model.debounce`) +and it defaults to 300ms. ## Examples @@ -61,21 +73,30 @@ Margin classes position the slider; the active track and thumb colors come from @verbatim ```blade +@php $volume = 40; @endphp + - - Volume - {{ $volume }}% + + Volume + {{ $volume }}% ``` @endverbatim +Declare `volume` as a public property on your component (`public int $volume = 40;`) and the label +tracks the thumb as it settles. + ### Stepped picker @verbatim ```blade +@php $rating = 3; @endphp + + +Rating: {{ $rating }} / 5 ``` @endverbatim diff --git a/resources/views/docs/mobile/4/edge-components/spacer.md b/resources/views/docs/mobile/4/edge-components/spacer.md index 384d87ab..1c127c1d 100644 --- a/resources/views/docs/mobile/4/edge-components/spacer.md +++ b/resources/views/docs/mobile/4/edge-components/spacer.md @@ -9,7 +9,7 @@ A flexible space element that expands to fill remaining space within a column or push elements apart without calculating explicit sizes. @verbatim -```blade +```blade static ``` @endverbatim @@ -48,7 +48,7 @@ See the full shared list at [Layout & Styling](layout#supported-tailwind-classes @verbatim ```blade - + Welcome Get started with your app. @@ -57,6 +57,10 @@ See the full shared list at [Layout & Styling](layout#supported-tailwind-classes ``` @endverbatim +In a real app this column is usually the page root with `h-full`, so the spacer pushes the button to the bottom of the +screen. The fixed `h-[220]` here just gives the preview a bounded height — a spacer can only grow when its parent's +main axis is constrained. + ### Toolbar with right-aligned trailing icon @verbatim @@ -75,7 +79,7 @@ See the full shared list at [Layout & Styling](layout#supported-tailwind-classes ```blade Section One - + Section Two ``` @@ -83,8 +87,9 @@ See the full shared list at [Layout & Styling](layout#supported-tailwind-classes @@ -93,6 +98,6 @@ often more readable. ```php use Native\Mobile\Edge\Elements\Spacer; -Spacer::make(); // flex-grow: 1 -Spacer::make()->height(8); // fixed 8dp vertical +Spacer::make(); // flex-grow: 1 +Spacer::make()->height(8)->flexGrow(0); // fixed 8dp vertical ``` diff --git a/resources/views/docs/mobile/4/edge-components/stack.md b/resources/views/docs/mobile/4/edge-components/stack.md index 7f21d368..f4a89d75 100644 --- a/resources/views/docs/mobile/4/edge-components/stack.md +++ b/resources/views/docs/mobile/4/edge-components/stack.md @@ -12,10 +12,10 @@ Useful for badges, image overlays, floating labels, and layered UI effects. @verbatim ```blade - - + + - Overlay Text + Overlay Text ``` @@ -51,12 +51,15 @@ Everything else from the shared list applies as on any element (`p-*`, `m-*`, `b @verbatim ```blade - + ``` @endverbatim +In a real app the base layer would typically be a `` avatar (e.g. +``). + ### Badge on an icon @verbatim @@ -75,8 +78,8 @@ Everything else from the shared list applies as on any element (`p-*`, `m-*`, `b @verbatim ```blade - - + + Featured Article Read more about this topic @@ -100,7 +103,7 @@ use Native\Mobile\Edge\Elements\Image; use Native\Mobile\Edge\Elements\Text; Stack::make( - Image::make('https://example.com/photo.jpg'), + Image::make('https://picsum.photos/seed/nativephp/400/300'), Text::make('Overlay'), )->width(200)->height(200); ``` diff --git a/resources/views/docs/mobile/4/edge-components/tab-row.md b/resources/views/docs/mobile/4/edge-components/tab-row.md index 0f35125c..310c1d06 100644 --- a/resources/views/docs/mobile/4/edge-components/tab-row.md +++ b/resources/views/docs/mobile/4/edge-components/tab-row.md @@ -12,19 +12,24 @@ Distinct from [``](bottom-nav) — bottom nav is your app's p URL routing, while `` is an in-screen sectioning control whose tabs swap content within the same screen. -Per Model 3, the active tab uses `theme.primary` and the underline is `theme.primary`. Inactive tabs use +Per Material 3, the active tab uses `theme.primary` and the underline is `theme.primary`. Inactive tabs use `theme.onSurfaceVariant`. @verbatim ```blade +@php $activeTab = 0; @endphp + - + ``` @endverbatim +`activeTab` is a public int property on your component — the `@php` line stands in for +`public int $activeTab = 0;`. + ## Props (Row) - `value` / `selected-index` - Currently selected tab index (optional, int, default: `0`) @@ -38,24 +43,31 @@ Per Model 3, the active tab uses `theme.primary` and the underline is `theme.pri ## Two-way Binding -`native:model` binds the selected index to an integer property on your component: +`native:model` binds the selected index to an integer property on your component. Tapping a tab syncs the new +index back automatically: @verbatim ```blade - +@php $currentTab = 0; @endphp + + + +Selected: {{ ['One', 'Two', 'Three'][$currentTab] }} ``` @endverbatim +Here `currentTab` stands in for `public int $currentTab = 0;` on your component. + ## Children `` declares a single tab. Each accepts: - `label` - Tab label (required, string). Can also be passed as the first argument to `make()` -- `icon` - Optional [icon](icons) name rendered above the label +- `icon` - Optional [icon](icon#icon-name-reference) name rendered above the label - `a11y-label` - Accessibility label override (optional) ## Examples @@ -64,7 +76,9 @@ Per Model 3, the active tab uses `theme.primary` and the underline is `theme.pri @verbatim ```blade - +@php $section = 0; @endphp + + @@ -72,30 +86,35 @@ Per Model 3, the active tab uses `theme.primary` and the underline is `theme.pri @if($section === 0) - - Overview content + + Overview content @elseif($section === 1) - - Activity content + + Activity content @else - - Members content + + Members content @endif ``` @endverbatim +`section` is a public int property on your component (`public int $section = 0;`). On a real screen you would +typically add `fill` to the outer column and the content panes so they occupy the remaining screen height. + ### Tabs with icons @verbatim ```blade +@php $filter = 0; @endphp + - + ``` @endverbatim @@ -109,7 +128,7 @@ use Nativephp\NativeUi\Elements\Tab; TabRow::make( Tab::make('Recent')->icon('history'), Tab::make('Starred')->icon('star'), - Tab::make('Archived')->icon('archive'), + Tab::make('Archived')->icon('archive-box'), ) ->selectedIndex($activeTab) ->onChange('setActiveTab'); @@ -126,4 +145,4 @@ TabRow::make( ### `Tab` methods - `make(string $label = '')` - Create a tab with a label -- `icon(?string $name = null, IosSymbol|string|null $ios = null, AndroidSymbol|string|null $android = null)` - Tab icon. Pass a shared [icon](icons) name, or override per platform with the `ios:` / `android:` named arguments +- `icon(?string $name = null, IosSymbol|string|null $ios = null, AndroidSymbol|string|null $android = null)` - Tab icon. Pass a shared [icon](icon#icon-name-reference) name, or override per platform with the `ios:` / `android:` named arguments 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 c4f7b4c0..de76304b 100644 --- a/resources/views/docs/mobile/4/edge-components/text-input.md +++ b/resources/views/docs/mobile/4/edge-components/text-input.md @@ -16,12 +16,14 @@ All three share the same prop set and event API. Choose the outlined / filled pa reach for bare when you want to style the input yourself. On iOS the outlined and filled variants render as SwiftUI `TextField` / `SecureField` with Material3-style chrome; on -Android they map to `OutlinedTextField` / `TextField` (filled). Per Model 3 these two have no per-instance color or +Android they map to `OutlinedTextField` / `TextField` (filled). Per Material 3 these two have no per-instance color or border overrides — all chrome resolves from the theme. For fully custom input visuals reach for the bare variant, or drop to [``](pressable) wrapping your own drawing. @verbatim ```blade +@php $email = ''; @endphp + `](pressable) wrapping your own drawing. ``` @endverbatim +`email` is a public string property on your component — the `@php` line stands in for +`public string $email = '';` and seeds the inline preview. + ## Props All three variants accept the same shared prop set. The bare variant adds a `color` attribute on top — see @@ -111,12 +116,19 @@ Use the `native:model` directive for automatic two-way binding with a component @verbatim ```blade - - - +@php $name = 'Ada'; $email = ''; $search = ''; @endphp + + + + + +Hello, {{ $name }}! ``` @endverbatim +`name`, `email`, and `search` are public string properties on your component — typing syncs them back +automatically, so the `{{ $name }}` echo updates as you type. + `sync-mode` semantics: - `live` (default) — every keystroke fires `@change` @@ -142,6 +154,8 @@ Two things set it apart: @verbatim ```blade +@php $draft = ''; @endphp + ``` @@ -173,6 +189,8 @@ The `color` attribute can be set explicitly or picked up from a `text-*` class o @verbatim ```blade +@php $email = ''; $password = ''; @endphp + + Hello, world! ``` @@ -58,7 +58,7 @@ into your app's `resources/fonts/` directory, then reference one by its filename @verbatim ```blade - + Custom heading ``` @@ -128,7 +128,7 @@ Arbitrary values are supported too: `leading-[1.4]` (multiplier) or `leading-[24 @verbatim ```blade - + A comfortably spaced paragraph that wraps across several lines with a little extra breathing room between them. @@ -160,7 +160,7 @@ Style text with Tailwind classes — these compose with `text-*` size and `font- @verbatim ```blade - + Styled with Tailwind ``` @@ -193,8 +193,8 @@ whole region selectable. Use `select-none` to opt a nested subtree back out: @verbatim ```blade - Selectable heading - This body copy can be selected and copied. + Selectable heading + This body copy can be selected and copied. Not selectable @@ -226,13 +226,13 @@ Use the `dark:` prefix with Tailwind classes or pass a dark-mode color override. @verbatim ```blade -Thin (1) -Light (2) -Regular (3) -Medium (4) -SemiBold (5) -Bold (6) -Heavy (7) +Thin (1) +Light (2) +Regular (3) +Medium (4) +SemiBold (5) +Bold (6) +Heavy (7) ``` @endverbatim @@ -240,7 +240,7 @@ Use the `dark:` prefix with Tailwind classes or pass a dark-mode color override. @verbatim ```blade - + This text will be truncated with an ellipsis after two lines if it overflows the available space in its container. @@ -251,7 +251,7 @@ Use the `dark:` prefix with Tailwind classes or pass a dark-mode color override. @verbatim ```blade - + Welcome Back ``` @@ -261,7 +261,7 @@ Use the `dark:` prefix with Tailwind classes or pass a dark-mode color override. @verbatim ```blade - + Learn more ``` @@ -271,12 +271,16 @@ Use the `dark:` prefix with Tailwind classes or pass a dark-mode color override. @verbatim ```blade - +@php $score = 1250; @endphp + + Score: {{ $score }} ``` @endverbatim +Here `$score` stands in for a public property on your component — `public int $score = 1250;`. +