From d4b7383829c9dc6574b911d397ab00c7b74b223f Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Sat, 25 Jul 2026 11:47:45 +0100 Subject: [PATCH] docs(mobile/v4): document stack anchor/origin + attribute positioning Covers the new positioning capabilities in NativePHP/mobile-air#226: - Positioning page: absolute/relative and top/right/bottom/left now work as plain attributes, not only utility classes; adds the two-point anchor (point on the parent) / origin (point on the child) model, both defaulting to center, and notes that a child can draw outside its container. - Stack page: children are absolutely positioned by default and place themselves via anchor/origin; replaces the old relative-parent workaround; documents wrap-to-largest-child sizing. - Layout & Styling: adds anchor-*/origin-* to the shared class table. Co-Authored-By: Claude Fable 5 --- .../docs/mobile/4/edge-components/layout.md | 1 + .../docs/mobile/4/edge-components/stack.md | 49 ++++++++-- .../docs/mobile/4/the-basics/positioning.md | 96 ++++++++++++++++--- 3 files changed, 121 insertions(+), 25 deletions(-) diff --git a/resources/views/docs/mobile/4/edge-components/layout.md b/resources/views/docs/mobile/4/edge-components/layout.md index 2c22151d..52fda3b7 100644 --- a/resources/views/docs/mobile/4/edge-components/layout.md +++ b/resources/views/docs/mobile/4/edge-components/layout.md @@ -284,6 +284,7 @@ The parser recognizes the classes listed below. | Margin | `m-N`, `mx-N`, `my-N`, `mt-N`, `mr-N`, `mb-N`, `ml-N`, arbitrary `m-[N]` etc. | | Gap | `gap-N`, `gap-[N]` (uniform — no `gap-x-*` or `gap-y-*`) | | Position | `absolute`, `relative`, `top-N`, `right-N`, `bottom-N`, `left-N`, arbitrary `top-[N]` etc. | +| Anchor / origin | `anchor-{point}`, `origin-{point}` — where `{point}` is `center`, an edge (`top`/`right`/`bottom`/`left`) or a corner (`top-left`…`bottom-right`). See [Positioning](../the-basics/positioning#anchor-amp-origin) | | Flex | `flex-1`, `flex-grow`, `flex-grow-0`, `flex-shrink`, `flex-shrink-0`, `flex-wrap`, `flex-nowrap`, `flex-wrap-reverse` | | Items (cross-axis) | `items-start`, `items-center`, `items-end`, `items-stretch` | | Justify (main-axis) | `justify-start`, `justify-center`, `justify-end`, `justify-between`, `justify-around`, `justify-evenly` | diff --git a/resources/views/docs/mobile/4/edge-components/stack.md b/resources/views/docs/mobile/4/edge-components/stack.md index f4a89d75..4928d821 100644 --- a/resources/views/docs/mobile/4/edge-components/stack.md +++ b/resources/views/docs/mobile/4/edge-components/stack.md @@ -26,8 +26,35 @@ Useful for badges, image overlays, floating labels, and layered UI effects. Accepts any EDGE elements as children. Children are rendered in order, with later children appearing on top of earlier ones. -Each child is **placed at its natural size and centered** in the stack's bounds. Give a child `w-full` or `h-full` to -force it to fill the stack. +Every child is positioned **absolutely** and placed at its natural size — you don't need `relative` on the stack or +`absolute` on the children. By default each child is **centered** in the stack's bounds. Give a child `w-full` or +`h-full` to force it to fill the stack. + +The stack itself **sizes to its largest child** when you don't give it explicit dimensions, so a small overlaid +element (a badge, a dot) won't shrink the stack. + +### Anchoring children + +Move a child away from the centre with two points — one on the stack, one on the child: + +- **`anchor`** — the point on the **stack** the child hooks onto. +- **`origin`** — the point **on the child** that lands there. + +Both default to `center` and accept `center`, the four edges (`top`, `right`, `bottom`, `left`) and the four corners +(`top-left` … `bottom-right`) — as an attribute or an `anchor-*` / `origin-*` class. The child's `origin` point is +placed exactly on the stack's `anchor` point, so a child can sit on — or hang off — an edge or corner. See +[Positioning](../the-basics/positioning#anchor-amp-origin) for the full model. + +@verbatim +```blade + + + {{-- The dot's centre (origin default) sits on the stack's top-right corner. --}} + + +``` +@endverbatim ## Supported Tailwind classes @@ -46,19 +73,21 @@ Everything else from the shared list applies as on any element (`p-*`, `m-*`, `b ## Examples -### Avatar with centered badge +### Avatar with a corner status dot @verbatim ```blade - - + + {{-- The dot's centre sits on the avatar's bottom-right corner. --}} + ``` @endverbatim -In a real app the base layer would typically be a `` avatar (e.g. -``). +Set `origin` too if you want a different part of the badge on the corner — e.g. `anchor="top-right" +origin="top-right"` tucks the badge fully *inside* the corner instead of straddling it. ### Badge on an icon @@ -89,9 +118,9 @@ In a real app the base layer would typically be a `` avatar (e.g. diff --git a/resources/views/docs/mobile/4/the-basics/positioning.md b/resources/views/docs/mobile/4/the-basics/positioning.md index 1168e6f9..19cf2e29 100644 --- a/resources/views/docs/mobile/4/the-basics/positioning.md +++ b/resources/views/docs/mobile/4/the-basics/positioning.md @@ -7,31 +7,96 @@ order: 190 Most layouts use the flex engine — children flow inside their parent column or row. For overlays like floating action buttons, badges that hang off the edge of an avatar, or a "skip" button pinned to a corner, the framework -also supports CSS-style absolute positioning. +also supports CSS-style absolute positioning, plus a two-point **anchor / origin** model for precise placement. -## Tailwind classes +## Absolute positioning + +Take an element out of flex flow and position it relative to its parent. You can use either Tailwind classes or +plain attributes — they are equivalent. @verbatim ```blade +{{-- Tailwind classes --}} {{-- Pinned to the bottom-right corner of the parent --}} + +{{-- The same thing as attributes --}} + + ... + +``` +@endverbatim + +| Class | Attribute | Effect | +|---|---|---| +| `absolute` | `absolute` / `position="absolute"` | Take this element out of flex flow and position it against its parent | +| `relative` | `relative` / `position="relative"` | Default; element flows normally | +| `top-[N]` | `:top="N"` | Inset from the parent's top edge (dp) | +| `right-[N]` | `:right="N"` | Inset from the parent's right edge (dp) | +| `bottom-[N]` | `:bottom="N"` | Inset from the parent's bottom edge (dp) | +| `left-[N]` | `:left="N"` | Inset from the parent's left edge (dp) | + +When an explicit class form and its attribute are both present (e.g. `class="top-4"` and `:top="99"`), the class +form wins. + +### Inset convention + +When `right` is set and `left` is unset, the child anchors to the parent's right edge offset by that amount. Same +for `bottom`. This mirrors CSS `position: absolute` shorthand. If both `left` and `right` are set, the child +stretches between them; likewise for `top` and `bottom`. + +## Anchor & origin + +For precise overlay placement, an absolutely-positioned child can align **two points** — one on the parent and one +on itself — instead of pinning to an edge: + +- **`anchor`** — the point on the **parent** the child hooks onto. +- **`origin`** — the point **on the child** that lands on that parent point. + +Both default to `center`, and both accept the same nine values (or the `anchor-*` / `origin-*` class form): + +``` +top-left top top-right +left center right +bottom-left bottom bottom-right +``` + +(`top` is an alias for `top-center`, `left` for `center-left`, and so on.) + +The child is placed so its `origin` point sits exactly on the parent's `anchor` point: + +@verbatim +```blade +{{-- The dot's CENTRE (origin defaults to center) sits on the parent's top-right + corner — so it straddles the corner, half inside and half outside. --}} + + + + + +{{-- Give the child its own origin to change which part of it lands on the anchor. + Here the badge's bottom-left corner hooks the parent's top-right corner. --}} + + ... + ``` @endverbatim -- `absolute` - Take this element out of flex flow and position it relative to the nearest positioned ancestor -- `relative` - Default; element flows normally -- `top-[N]` - Inset from the parent's top edge (dp) -- `right-[N]` - Inset from the parent's right edge (dp) -- `bottom-[N]` - Inset from the parent's bottom edge (dp) -- `left-[N]` - Inset from the parent's left edge (dp) +`anchor` and `origin` apply to any absolutely-positioned child. Insets (`top`/`right`/`bottom`/`left`) still apply +on top as a nudge from the anchored position. A plain `absolute top-0 right-0` child with no `anchor`/`origin` +keeps the simple edge-inset behaviour described above. -## Anchor convention + ## Common pattern: floating action button @@ -56,8 +121,9 @@ Absolute children only occupy their placed bounds — siblings receive scroll an