Skip to content

Commit 8116c5b

Browse files
shanerbaner82claude
andcommitted
docs(mobile/3): full revise of edge-components + new chrome / nav / safe-area pages
Edge components — reconciled every existing page with element + iOS/Android renderers: - bottom-nav: active-color, background-color, text-color, news; TabBar / Tab builder API; safe-area auto-handling; tab taps use replace semantics. - top-bar: subtitle, background-color, text-color, elevation (hairline overlay, not SwiftUI shadow); NavBar / NavAction builder API; navigationOptions(). - scroll-view: shows-indicators flagged iOS-only; Android LazyRow/Column. - stack: rewrote around the new custom Layout — children at natural size, centered. - layout: align-self stretch override of items-center; flex-1 shorthand. - button, toggle, checkbox, slider, select, radio-group, button-group, chip, text-input: Model 3 styling rule (per-instance bg/padding/font-size dropped). - text-input: replaced the (non-existent) <native:text-input> doc with separate outlined and filled coverage; corrected keyboard string enum. - image: corrected fit modes (renderer collapses to fit/fill). - text: fixed font-weight 7 → .heavy (was "extrabold"). - shapes: per-shape sections (rect / circle / line); flagged that <native:line> ignores from/to (renderer always draws horizontal). - divider: clarified border-color drives line color; horizontal-divider alias. - introduction: refreshed component inventory. New edge-components pages: - badge, button-group, canvas, card, carousel, checkbox, chip, list (covers list-item), modal, progress-bar, radio-group (covers radio), screen, select, slider, tab-row (covers tab). New the-basics pages: - layouts: NativeLayout + StackLayout / TabsLayout, route attachment, wrapWithChrome flow, navigationOptions / setNavBar / navTitle. - navigation: navigate / back / replace / exitToWeb, transitions, param/data. - safe-area: safeArea / safeAreaTop / safeAreaBottom; bitmask + auto-handling via wrapWithChrome based on which bars are present. - positioning: absolute / relative + anchor convention; FAB pattern; stack caveat. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ad015a8 commit 8116c5b

39 files changed

Lines changed: 2645 additions & 241 deletions

resources/views/docs/mobile/3/edge-components/activity-indicator.md

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ order: 350
55

66
## Overview
77

8-
A native loading spinner. Use this to indicate background activity or loading states. Renders as a platform-native
9-
progress indicator (spinning wheel on iOS, circular indicator on Android).
8+
A circular spinner indicating background activity. Always indeterminate — for determinate progress use
9+
[`<native:progress-bar>`](progress-bar). Renders as a SwiftUI `ProgressView` on iOS and Material3
10+
`CircularProgressIndicator` on Android.
1011

1112
@verbatim
1213
```blade
@@ -18,13 +19,17 @@ progress indicator (spinning wheel on iOS, circular indicator on Android).
1819

1920
All [shared layout and style attributes](layout) are supported, plus:
2021

21-
- `size` - Indicator size (optional, float): `0`=default, `1`=large, `2`=small
22-
- `color` - Spinner color as hex string (optional, default: platform default)
22+
- `size` - `"sm"`, `"md"` (default), or `"lg"` (optional, string). Legacy ints `1`=large, `2`=small are also accepted
23+
- `color` - Spinner color as hex string (optional). Leave unset to use `theme.primary`
24+
- `a11y-label` - Accessibility label (optional)
2325

2426
<aside>
2527

2628
`<native:activity-indicator />` is a self-closing element. It does not accept children.
2729

30+
The default tint comes from `theme.primary`. The `color` prop is an escape hatch — useful when the spinner sits on
31+
a non-theme-styled container (e.g. a light spinner over a dark image overlay).
32+
2833
</aside>
2934

3035
## Examples
@@ -34,7 +39,7 @@ All [shared layout and style attributes](layout) are supported, plus:
3439
@verbatim
3540
```blade
3641
<native:column fill center>
37-
<native:activity-indicator :size="1" color="#7C3AED" />
42+
<native:activity-indicator size="lg" />
3843
<native:text class="text-base text-slate-400 mt-4">Loading...</native:text>
3944
</native:column>
4045
```
@@ -45,24 +50,32 @@ All [shared layout and style attributes](layout) are supported, plus:
4550
@verbatim
4651
```blade
4752
<native:row :gap="8" :align-items="1">
48-
<native:activity-indicator :size="2" />
53+
<native:activity-indicator size="sm" />
4954
<native:text class="text-sm text-slate-500">Refreshing</native:text>
5055
</native:row>
5156
```
5257
@endverbatim
5358

54-
### Conditional loading
59+
### Override the tint
5560

5661
@verbatim
5762
```blade
58-
@if($loading)
59-
<native:column fill center>
60-
<native:activity-indicator color="#3B82F6" />
61-
</native:column>
62-
@else
63-
<native:column fill :padding="16">
64-
{{-- Content --}}
65-
</native:column>
66-
@endif
63+
<native:activity-indicator color="#7C3AED" />
6764
```
6865
@endverbatim
66+
67+
## Element
68+
69+
```php
70+
use Nativephp\NativeUi\Elements\ActivityIndicator;
71+
72+
ActivityIndicator::make()
73+
->size('lg')
74+
->color('#7C3AED')
75+
->a11yLabel('Loading messages');
76+
```
77+
78+
- `make()` - Create a new indicator
79+
- `size(string|int $size)` - `"sm" | "md" | "lg"`. Legacy: `1`=large, `2`=small
80+
- `color(string $hex)` - Override the theme tint
81+
- `a11yLabel(string $value)` - Accessibility label
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
title: Badge
3+
order: 360
4+
---
5+
6+
## Overview
7+
8+
A small count or text marker, typically used as an overlay on nav items, list rows, or buttons. Renders as a capsule
9+
pill.
10+
11+
Per Model 3, colors come from the theme via the semantic `variant` prop — there are no per-instance overrides.
12+
13+
@verbatim
14+
```blade
15+
<native:badge :count="3" />
16+
```
17+
@endverbatim
18+
19+
## Props
20+
21+
- `count` - Numeric count. Renders as `"99+"` for values above 99 (optional, int)
22+
- `label` - Arbitrary short text. Wins over `count` when both are set (optional, string)
23+
- `variant` - Color variant (optional, string, default: `destructive`):
24+
- `destructive``theme.destructive` / `theme.onDestructive`
25+
- `primary``theme.primary` / `theme.onPrimary`
26+
- `accent``theme.accent` / `theme.onAccent`
27+
- `a11y-label` - Accessibility label (optional)
28+
29+
<aside>
30+
31+
`<native:badge />` is a self-closing element. It does not accept children. For a badge attached to a navigation
32+
icon, see the `badge` and `news` props on [`<native:bottom-nav-item>`](bottom-nav).
33+
34+
</aside>
35+
36+
## Examples
37+
38+
### Count badge
39+
40+
@verbatim
41+
```blade
42+
<native:row :gap="8" :align-items="1">
43+
<native:icon name="notifications" :size="24" />
44+
<native:badge :count="$unreadCount" />
45+
</native:row>
46+
```
47+
@endverbatim
48+
49+
### Label badge
50+
51+
@verbatim
52+
```blade
53+
<native:badge label="New" variant="primary" />
54+
```
55+
@endverbatim
56+
57+
### Anchored to an icon
58+
59+
Use a [`<native:stack>`](stack) to layer the badge over its target:
60+
61+
@verbatim
62+
```blade
63+
<native:stack :width="40" :height="40">
64+
<native:icon name="cart" :size="32" />
65+
<native:column class="absolute" :top="-2" :right="-2">
66+
<native:badge :count="$cartItems" />
67+
</native:column>
68+
</native:stack>
69+
```
70+
@endverbatim
71+
72+
## Element
73+
74+
```php
75+
use Nativephp\NativeUi\Elements\Badge;
76+
77+
Badge::make()
78+
->count(3)
79+
->variant('primary');
80+
81+
Badge::make()
82+
->label('New')
83+
->variant('accent');
84+
```
85+
86+
- `make()` - Create a badge
87+
- `count(int $count)` - Numeric count (capped display at `99+`)
88+
- `label(string $text)` - Short text label (wins over `count`)
89+
- `variant(string $variant)` - `destructive | primary | accent`
90+
- `a11yLabel(string $value)` - Accessibility label

resources/views/docs/mobile/3/edge-components/bottom-nav.md

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,28 +40,84 @@ A bottom navigation bar with up to 5 items. Used for your app's primary navigati
4040

4141
- `label-visibility` - `labeled`, `selected`, or `unlabeled` (optional, default: `labeled`)
4242
- `dark` - Force dark mode styling (optional)
43+
- `active-color` - Color of the active tab's icon and label. Hex string (optional)
44+
- `background-color` - Bar background color. Hex string. Wins over `dark`'s default (optional)
45+
- `text-color` - Color of inactive tab icons and labels. Hex string. Active tabs use `active-color` (optional)
46+
47+
<aside>
48+
49+
The bar handles its own bottom safe-area inset internally — the home-indicator zone on iOS, the gesture-bar zone on
50+
Android. Don't add your own padding for it. The bar's background extends to the screen edge while its content stays
51+
above the indicator, mirroring iOS `UITabBar`.
52+
53+
</aside>
4354

4455
## Children
4556

4657
A `<native:bottom-nav>` can contain up to 5 `<native:bottom-nav-item>` elements.
4758

59+
### Props
60+
4861
- `id` - Unique identifier (required)
4962
- `icon` - A named [icon](icons) (required)
5063
- `label` - Accessibility label (required)
5164
- `url` - A URL to navigate to in the web view (required)
5265
- `active` - Highlight this item as active (optional, default: `false`)
53-
- `badge` - Badge text/number (optional)
54-
- `news` - Show "new" indicator dot (optional, default: `false`)
66+
- `badge` - Badge text/number, e.g. `"2"` — small red pill anchored top-right of the icon (optional)
67+
- `news` - Show a small red dot anchored top-right of the icon. Mutually exclusive with `badge` (optional, default: `false`)
5568

5669
<aside>
5770

58-
Any `url` that doesn't match the web view's domain will open in the user's default browser.
71+
Tab taps use `replace` semantics — tapping a tab swaps the current screen rather than pushing onto the stack. The
72+
back chevron pops the entire tabs section in one step instead of stepping through tab history.
73+
74+
Any `url` that doesn't match a registered native route will exit to the web view and load that URL there.
5975

6076
</aside>
6177

6278
### `badge` example
79+
6380
<div class="sm:w-1/2">
6481

6582
![](/img/docs/edge-bottom-nav-item-badge.png)
6683

6784
</div>
85+
86+
## Builder API
87+
88+
When a `<native:bottom-nav>` is supplied by a [layout](../the-basics/layouts), you build it fluently with the `TabBar`
89+
and `Tab` builders rather than writing it in Blade.
90+
91+
```php
92+
use Native\Mobile\Edge\Layouts\Builders\Tab;
93+
use Native\Mobile\Edge\Layouts\Builders\TabBar;
94+
95+
TabBar::make()
96+
->dark()
97+
->activeColor('#0891b2')
98+
->labelVisibility('labeled')
99+
->backgroundColor('#0F172A')
100+
->textColor('#94A3B8')
101+
->add(Tab::link('Chats', '/syncup', icon: 'chat_bubble')->badge('2'))
102+
->add(Tab::link('Friends', '/syncup/friends', icon: 'person.3.fill')->news())
103+
->add(Tab::link('Profile', '/syncup/profile', icon: 'person')->active());
104+
```
105+
106+
### `TabBar` methods
107+
108+
- `make()` - Create a new builder
109+
- `dark(bool $dark = true)` - Force dark mode styling
110+
- `activeColor(string $color)` - Color of the active tab's icon and label
111+
- `backgroundColor(string $color)` - Bar background color (overrides `dark()`'s default)
112+
- `textColor(string $color)` - Color of inactive tab icons and labels
113+
- `labelVisibility(string $mode)` - `"labeled"`, `"selected"`, or `"unlabeled"`
114+
- `add(Tab $tab)` - Append a tab item
115+
116+
### `Tab` methods
117+
118+
- `link(string $label, string $url, ?string $icon = null)` - Build a tab. The id defaults to the label slugified
119+
- `id(string $id)` - Override the auto-generated id
120+
- `icon(string $icon)` - A named [icon](icons)
121+
- `badge(string $badge, ?string $color = null)` - Show a numeric/text badge
122+
- `news(bool $news = true)` - Show a red dot indicator
123+
- `active(bool $active = true)` - Mark this tab as active

resources/views/docs/mobile/3/edge-components/bottom-sheet.md

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ order: 700
55

66
## Overview
77

8-
A modal bottom sheet that slides up from the bottom of the screen. Use it for contextual actions, forms, and detail
9-
views that overlay the main content. Renders as a native bottom sheet on both iOS and Android.
8+
A modal panel that slides up from the bottom of the screen. Use it for contextual actions, forms, and detail views
9+
that overlay the main content. Renders as SwiftUI's `.sheet` with `presentationDetents` on iOS and a Material3
10+
`ModalBottomSheet` on Android.
11+
12+
Per Model 3, the container color resolves from `theme.surface`. For a custom surface wrap content in a
13+
`<native:column class="bg-...">`.
1014

1115
@verbatim
1216
```blade
@@ -22,13 +26,18 @@ views that overlay the main content. Renders as a native bottom sheet on both iO
2226

2327
## Props
2428

25-
All [shared layout and style attributes](layout) are supported, plus:
26-
2729
- `visible` - Whether the sheet is shown (required, boolean)
30+
- `detents` - Allowed sheet heights (optional, default: `"medium,large"`). Comma-separated combination of:
31+
- `small` (25% of screen)
32+
- `medium`
33+
- `large`
34+
- `full` (100% of screen)
35+
- A numeric fraction `0.0``1.0` for a custom height (e.g. `"0.4"` for 40%)
36+
- `a11y-label` - Accessibility label (optional)
2837

2938
## Events
3039

31-
- `@dismiss` - Livewire method called when the sheet is dismissed (e.g. by swiping down or tapping the scrim)
40+
- `@dismiss` - Livewire method called when the sheet is dismissed (swipe down or tap outside)
3241

3342
## Children
3443

@@ -40,18 +49,18 @@ Accepts any EDGE elements as children. The children are rendered inside the shee
4049

4150
@verbatim
4251
```blade
43-
<native:bottom-sheet :visible="$showActions" @dismiss="hideActions">
52+
<native:bottom-sheet :visible="$showActions" @dismiss="hideActions" detents="small">
4453
<native:column class="w-full gap-0 pb-8">
4554
<native:pressable @press="editItem" class="w-full px-4 py-3">
4655
<native:row :gap="12" :align-items="1">
47-
<native:icon name="edit" :size="24" color="#1E293B" />
56+
<native:icon name="edit" :size="24" />
4857
<native:text class="text-base">Edit</native:text>
4958
</native:row>
5059
</native:pressable>
5160
<native:divider />
5261
<native:pressable @press="shareItem" class="w-full px-4 py-3">
5362
<native:row :gap="12" :align-items="1">
54-
<native:icon name="share" :size="24" color="#1E293B" />
63+
<native:icon name="share" :size="24" />
5564
<native:text class="text-base">Share</native:text>
5665
</native:row>
5766
</native:pressable>
@@ -71,42 +80,50 @@ Accepts any EDGE elements as children. The children are rendered inside the shee
7180

7281
@verbatim
7382
```blade
74-
<native:bottom-sheet :visible="$showForm" @dismiss="closeForm">
83+
<native:bottom-sheet :visible="$showForm" @dismiss="closeForm" detents="medium,large">
7584
<native:column class="w-full p-4 gap-4">
7685
<native:text class="text-xl font-bold">Add Item</native:text>
77-
<native:text-input label="Name" @model="itemName" />
78-
<native:text-input label="Description" @model="itemDescription" multiline :min-lines="3" />
86+
<native:outlined-text-input label="Name" native:model="itemName" />
87+
<native:outlined-text-input label="Description" native:model="itemDescription" multiline :min-lines="3" />
7988
<native:row :gap="8" :justify-content="2">
80-
<native:button label="Cancel" @press="closeForm" />
81-
<native:button label="Save" @press="saveItem" color="#7C3AED" label-color="#FFFFFF" />
89+
<native:button label="Cancel" variant="secondary" @press="closeForm" />
90+
<native:button label="Save" @press="saveItem" />
8291
</native:row>
8392
</native:column>
8493
</native:bottom-sheet>
8594
```
8695
@endverbatim
8796

88-
### Toggling a sheet
89-
90-
The sheet is controlled by a Livewire property. Set `visible` to `true` to show it, and handle the `@dismiss` event to
91-
hide it when the user swipes it away.
97+
### Custom height
9298

9399
@verbatim
94100
```blade
95-
{{-- Trigger --}}
96-
<native:button label="Show Options" @press="showSheet" />
97-
98-
{{-- Sheet --}}
99-
<native:bottom-sheet :visible="$showSheet" @dismiss="hideSheet">
100-
<native:column class="w-full p-4">
101-
<native:text>Sheet content</native:text>
102-
</native:column>
101+
<native:bottom-sheet :visible="$showPreview" @dismiss="closePreview" detents="0.4">
102+
<native:image src="{{ $previewUrl }}" class="w-full h-full" :fit="2" />
103103
</native:bottom-sheet>
104104
```
105105
@endverbatim
106106

107107
<aside>
108108

109-
Always handle the `@dismiss` event to update your Livewire state. If you don't, the `visible` property will be out of
110-
sync with the actual sheet state after the user dismisses it by gesture.
109+
Always handle the `@dismiss` event to update your Livewire state. If you don't, the `visible` property will be out
110+
of sync with the actual sheet state after the user dismisses it by gesture.
111111

112112
</aside>
113+
114+
## Element
115+
116+
```php
117+
use Nativephp\NativeUi\Elements\BottomSheet;
118+
119+
BottomSheet::make()
120+
->visible($showSheet)
121+
->detents('medium,large')
122+
->onDismiss('hideSheet');
123+
```
124+
125+
- `make()` - Create a bottom sheet
126+
- `visible(bool $value = true)` - Toggle visibility
127+
- `detents(string $detents)` - Allowed heights
128+
- `a11yLabel(string $value)` - Accessibility label
129+
- `onDismiss(string $method)` - Livewire method invoked on dismissal

0 commit comments

Comments
 (0)