Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 45 additions & 5 deletions resources/views/docs/mobile/4/edge-components/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,26 @@ Labels map to these integers, which still work if you prefer them (`align-items=

| Integer | `align-items` / `align-self` | `justify-content` |
|---------|------------------------------|-------------------|
| `0` | start | start |
| `0` | *unset* — see below | start |
| `1` | center | center |
| `2` | end | end |
| `3` | stretch | space-between |
| `4` | | space-around |
| `4` | start | space-around |
| `5` | — | space-evenly |

<aside>

For `align-items` and `align-self`, `0` means **unset** — not `start`. Start is `4`.

The renderers have to tell an element that explicitly asked for `items-start` apart from one that never specified
an alignment at all, because the two mean different things. Sharing a value made the first impossible to fix
without changing the second for every element in every app.

Passing `align-items="0"` therefore resolves to nothing and leaves the platform default in place. Use the label
(`align-items="start"`) or the enum rather than the integer — they are unambiguous.

</aside>

### In PHP

When you build elements fluently, pass a label, an enum case, or an integer. The enums live in
Expand Down Expand Up @@ -202,7 +215,8 @@ Visual styling attributes that apply to any element.
@endverbatim

- `bg` - Background color as hex string (e.g. `"#FF0000"`, `"#80FF000080"` for alpha)
- `border-radius` - Corner rounding in dp (float)
- `border-radius` - Corner rounding in dp (float). Applies to all four corners — for per-side or per-corner
rounding, use the `rounded-*` classes below
- `border-width` - Border width in dp (float). Must be used together with `border-color`
- `border-color` - Border color as hex string. Must be used together with `border-width`
- `opacity` - Element opacity from 0.0 to 1.0 (float)
Expand Down Expand Up @@ -299,6 +313,7 @@ The parser recognizes the classes listed below.
|----------|---------|
| Width | `w-full`, `w-N`, fractional (`w-1/2`, `w-1/3`, `w-2/3`, `w-1/4`, `w-3/4`, `w-1/5`…), arbitrary `w-[N]` |
| Height | `h-full`, `h-N`, arbitrary `h-[N]` |
| Min / max size | `min-w-N`, `max-w-N`, `min-h-N`, `max-h-N`, `max-w-none`, the container scale on `max-w` (`max-w-xs` … `max-w-7xl`), arbitrary `max-w-[N]` etc. |
| Aspect ratio | `aspect-square`, `aspect-video`, arbitrary `aspect-[N]` |
| Object fit (images) | `object-contain`, `object-cover`, `object-fill`, `object-none`, `object-scale-down` |
| Padding | `p-N`, `px-N`, `py-N`, `pt-N`, `pr-N`, `pb-N`, `pl-N`, arbitrary `p-[N]` etc. |
Expand All @@ -314,6 +329,8 @@ The parser recognizes the classes listed below.
| Border color | `border-{palette}-{shade}`, `border-white`, `border-black`, `border-transparent`, `border-[#hex]`, `border-theme-{token}` |
| Border width | `border` (1dp), `border-2`, `border-4`, `border-8` |
| Rounded | `rounded` (4dp), `rounded-sm`, `rounded-md`, `rounded-lg`, `rounded-xl`, `rounded-2xl`, `rounded-3xl`, `rounded-full`, `rounded-[N]` |
| Rounded (per side) | `rounded-t-*`, `rounded-r-*`, `rounded-b-*`, `rounded-l-*` — each rounds that side's two corners. A bare side (`rounded-b`) uses the same 4dp default as `rounded` |
| Rounded (per corner) | `rounded-tl-*`, `rounded-tr-*`, `rounded-br-*`, `rounded-bl-*`, including arbitrary values (`rounded-br-[4]`) |
| Shadow | `shadow`, `shadow-sm`, `shadow-md`, `shadow-lg`, `shadow-xl`, `shadow-2xl`, `shadow-inner`, `shadow-none` |
| Opacity | `opacity-{0..100}`, arbitrary `opacity-[0.5]` |
| Text size | `text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, `text-3xl`, `text-4xl`, `text-5xl`, `text-6xl`, arbitrary `text-[N]` |
Expand Down Expand Up @@ -346,10 +363,33 @@ bg-purple-500/40 bg-[#FF0000]/60 text-white/80
border-theme-outline/50
```

**Arbitrary values** — `prefix-[value]` for the prefixes shown above: `w`, `h`, `p`/`px`/`py`/`pt`/`pr`/`pb`/`pl`,
`m`/`mx`/`my`/`mt`/`mr`/`mb`/`ml`, `gap`, `bg`, `text`, `border`, `rounded`, `opacity`, `leading`, `aspect`, `top`,
**Arbitrary values** — `prefix-[value]` for the prefixes shown above: `w`, `h`, `min-w`/`max-w`/`min-h`/`max-h`,
`p`/`px`/`py`/`pt`/`pr`/`pb`/`pl`, `m`/`mx`/`my`/`mt`/`mr`/`mb`/`ml`, `gap`, `bg`, `text`, `border`, `rounded`
(and its per-side / per-corner forms — `rounded-t`, `rounded-br`, …), `opacity`, `leading`, `aspect`, `top`,
`right`, `bottom`, `left`.

Per-corner rounding composes with the uniform class rather than replacing it — set the shape once, then override the
corners you want different. Class order doesn't matter; the more specific class always wins, as it does in Tailwind:

@verbatim
```blade static
{{-- A chat bubble with its tail corner squared off toward its sender --}}
<native:column class="rounded-2xl rounded-br-none bg-theme-primary px-4 py-2">
<native:text class="text-theme-on-primary">Yep — 7pm works</native:text>
</native:column>
```
@endverbatim

### Deliberately unsupported

A handful of Tailwind classes are recognised as real Tailwind but left unparsed on purpose, rather than mapped to
something approximate. They are reported in the dropped-class log in debug builds:

| Class | Why | Use instead |
|-------|-----|-------------|
| `max-w-full`, `max-w-screen`, `min-w-full` | Min and max ride the wire as plain numbers with no accompanying size mode, so "100% of the parent" has nowhere to go | `w-full` |
| `rounded-s-*`, `rounded-e-*`, `rounded-ss-*`, `rounded-se-*`, `rounded-es-*`, `rounded-ee-*` | These are *logical* corners that flip with writing direction, and the renderers do not mirror layout for RTL — accepting them would silently draw left-to-right geometry in a right-to-left layout | the physical `rounded-l-*` / `rounded-tl-*` forms |

<aside>

Tailwind classes are the canonical styling API. The element-level attributes documented above (`bg`, `border-radius`,
Expand Down
34 changes: 34 additions & 0 deletions resources/views/docs/mobile/4/edge-components/scroll-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,40 @@ stretches across the full screen width.

</aside>

### Centering short content

A login screen, an empty state, a confirmation — content that should sit in the middle of the page but must still
scroll once the keyboard appears or the content grows.

Give the scroll view's child `fill`. It then stretches to at least the height of the scroll view's visible area, which
is what gives `justify-center` room to work:

@verbatim
```blade static
<native:scroll-view fill class="bg-theme-background">
<native:column fill class="w-full items-center justify-center p-6 gap-4">
<native:column class="w-full max-w-[360px] bg-theme-surface rounded-2xl p-6 gap-4">
<native:text class="text-2xl font-bold">Welcome back</native:text>
<native:outlined-text-input native:model="email" label="Email" keyboard="email" />
<native:outlined-text-input native:model="password" label="Password" secure />
<native:button class="w-full">Sign in</native:button>
</native:column>
</native:column>
</native:scroll-view>
```
@endverbatim

<aside>

`fill` inside a scroll view is a **minimum**, not a fixed height — the same as `min-height: 100%` on the web. Content
taller than the visible area still grows and scrolls normally, so this is safe to use even when you're not sure how
tall the content will end up.

Without `fill` on that child, the column hugs its own content and `justify-center` has nothing to distribute, leaving
everything pinned to the top.

</aside>

## Element

```php
Expand Down
42 changes: 41 additions & 1 deletion resources/views/docs/mobile/4/edge-components/text-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ All three variants accept the same shared prop set. The bare variant adds a `col
### Behavior

- `keyboard` - Keyboard hint string: `text` (default), `number`, `email`, `phone`, `url`, `decimal`, `password`,
`numberPassword`. On iOS `password` uses the standard keyboard; `secure` is the masking mechanism
`numberPassword`. On iOS `password` uses the standard keyboard; `secure` is the masking mechanism. The keyboard
type also decides capitalization and autocorrect — see [Capitalization](#capitalization)
- `autocapitalize` - Override that capitalization: `none`, `sentences`, `words`, or `characters` (HTML's
vocabulary). Leave it unset to let `keyboard` decide (optional, string)
- `secure` - Mask input for passwords (optional, boolean, default: `false`)
- `multiline` - Allow multiple lines (optional, boolean, default: `false`)
- `max-length` - Maximum character count (optional, int)
Expand Down Expand Up @@ -96,6 +99,43 @@ All three variants accept the same shared prop set. The bare variant adds a `col
- `a11y-label` - Accessibility label (optional)
- `a11y-hint` - Accessibility hint (optional)

## Capitalization

Declaring a `keyboard` type carries its typing behaviour with it, not just the key layout. Fields whose content is
case-sensitive or non-alphabetic never capitalize, and never autocorrect:

| `keyboard` | Capitalization | Autocorrect |
|------------|----------------|-------------|
| `text` (default) | sentences on iOS, none on Android | on |
| `email`, `url` | none | off |
| `number`, `decimal`, `phone`, `password`, `numberPassword` | none | off |

@verbatim
```blade static
{{-- Email keyboard AND no capitalized first letter — no extra attribute needed --}}
<native:outlined-text-input native:model="email" label="Email" keyboard="email" />
```
@endverbatim

Use `autocapitalize` for the cases a keyboard type can't imply:

@verbatim
```blade static
<native:outlined-text-input native:model="name" label="Full name" autocapitalize="words" />
<native:outlined-text-input native:model="code" label="Booking reference" autocapitalize="characters" />
```
@endverbatim

`autocapitalize` always wins over the derived value, and an unrecognised value falls back to the derived behaviour
rather than erroring.

<aside>

A plain text field with neither attribute set capitalizes sentences on iOS and nothing on Android — each platform's
own default, left as-is. Set `autocapitalize` explicitly when you need the two to match.

</aside>

## Events

- `@change` - Component method called when the text changes. Receives the new value
Expand Down