diff --git a/config/docs.php b/config/docs.php index c1e7695d..788c1388 100644 --- a/config/docs.php +++ b/config/docs.php @@ -59,7 +59,7 @@ 1 => ['1.0', '1.1'], 2 => ['2.0'], 3 => ['3.0', '3.1', '3.2', '3.3'], - 4 => ['4.0', '4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7'], + 4 => ['4.0', '4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9'], ], ], diff --git a/resources/views/docs/mobile/4/edge-components/menus.md b/resources/views/docs/mobile/4/edge-components/menus.md index 86df571f..5d6162b3 100644 --- a/resources/views/docs/mobile/4/edge-components/menus.md +++ b/resources/views/docs/mobile/4/edge-components/menus.md @@ -13,7 +13,8 @@ standalone element — you build a list of actions and attach it with an attribu - `items()` on a nav-bar action — see [Menus in the nav bar](#menus-in-the-nav-bar) below. All of them share one item model: an array of `NavAction`, the same builder used -[throughout layouts](../the-basics/layouts#builder-reference). +[throughout layouts](../the-basics/layouts#builder-reference). Nav-bar menus can also be grouped into +[sections, rows and submenus](#sections-rows-and-submenus). ## Building the items @@ -109,21 +110,166 @@ with dividers and destructive tinting, exactly like the inline menus above. This 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. +> **Note** Menus are only supported on nav-bar actions. Bottom-nav / tab-bar items and a +> [`custom`](top-bar#custom-bars) `` render their actions as plain buttons, so `items()` is ignored +> there. An inline `` without `custom` takes a menu as nested `` elements; see +> [Menus in Blade](#menus-in-blade). + +## Sections, rows and submenus + + + +A nav-bar menu doesn't have to be a flat list. You can group items into titled sections, put a compact row of +buttons across the top, nest a submenu, and give any item a subtitle or a checkmark. This menu is laid out like the +one behind the ⋯ button in Apple's Notes app: + +```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('more') + ->icon('ellipsis') + ->a11yLabel('More') + ->items([ + NavAction::row([ + NavAction::make('scan') + ->label('Scan') + ->icon(ios: 'doc.viewfinder', android: 'document_scanner') + ->press('scan'), + NavAction::make('pin') + ->label($this->pinned ? 'Unpin' : 'Pin') + ->icon('pin') + ->press('togglePin'), + NavAction::make('lock')->label('Lock')->icon('lock')->press('lock'), + ]), + NavAction::section(items: [ + NavAction::make('find')->label('Find in Note')->icon('search')->press('find'), + NavAction::make('move') + ->label('Move Note') + ->subtitle($this->folder) + ->icon('folder') + ->press('move'), + ]), + NavAction::section('View', [ + NavAction::make('paper') + ->label('Lines & Grids') + ->icon(ios: 'squareshape.split.3x3', android: 'grid_on') + ->items([ + NavAction::make('paper_none') + ->label('None') + ->checked($this->paper === 'none') + ->press("setPaper('none')"), + NavAction::make('paper_lines') + ->label('Lines') + ->checked($this->paper === 'lines') + ->press("setPaper('lines')"), + NavAction::make('paper_grid') + ->label('Grid') + ->checked($this->paper === 'grid') + ->press("setPaper('grid')"), + ]), + NavAction::make('attachments') + ->label('Show Attachments') + ->icon(ios: 'paperclip', android: 'attach_file') + ->checked($this->showAttachments) + ->press('toggleAttachments'), + ]), + NavAction::section(items: [ + NavAction::make('delete')->label('Delete')->icon('trash')->press('delete')->destructive(), + ]), + ]) + ); +} +``` + +Here's what each piece does: + +- `NavAction::row([...])` puts its items side by side across the top of the menu, each with its icon above a short + label. A row fits a few items, so keep the labels short. +- `NavAction::section('View', [...])` groups its items under a heading. Use `NavAction::section(items: [...])` for a + group with no heading. It still gets separated from the items around it. +- An item with its own `items()` is a submenu. `Lines & Grids` above opens a submenu of paper styles. +- `subtitle()` adds a second, smaller line under an item's label. Here it shows the folder the note is in. +- `checked()` puts a checkmark on an item. Pass it a boolean from your screen's state, like the paper styles do, and + the checkmark moves when the state changes. + +Rows and sections are containers, not tappable items. Their ids are fixed placeholders (`row` and `section`, like +`divider` for a divider), and they ignore `icon()`, `press()` and the other item methods. Give each item inside them +its own unique id. + +### How they look on each platform + +On iOS, the menu is a native `UIMenu`. Sections are drawn inline, with the title as a small heading above the group +and a separator line between groups. The row uses UIKit's medium element size: each item is a small button with its +icon above its label, the same as the Scan, Pin and Lock buttons in Notes. A submenu shows a chevron and opens in +place over the menu it came from. Checked items get the system checkmark, and destructive items are red. + +On Android, the menu is a Material dropdown. A divider separates each section from the items around it, and the +section's title shows as a small heading. The row is a line of buttons, each with an icon and a label. Tapping a +submenu replaces the dropdown's items with the submenu's, with a back row at the top to return to the previous +level. Checked items show a check mark at the end of the item, and a subtitle sits under the label in a smaller, +quieter style. + +### Menus in Blade + +An inline [``](top-bar) builds the same menu from nested `` elements. Add +`section` (with an optional `label` for its heading) or `row` to an action to make it a container, and nest actions +inside an item to make a submenu. `subtitle` and `checked` are attributes like any other: + +@verbatim +```blade + + + + + + + + + + + + + + + + + + + + + +``` +@endverbatim + + ## Item reference The menu-relevant `NavAction` methods: -- `make(string $id)` — create an item with a unique id -- `icon(?string $name = null, ios:, android:)` — a leading [icon](icon) -- `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 +- `make(string $id)` - create an item with a unique id +- `icon(?string $name = null, ios:, android:)` - a leading [icon](icon) +- `label(string)` - the item's text +- `subtitle(string)` - a second, smaller line under the label (nav-bar menus) +- `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, or an item inside one into a + submenu (nav-bar actions only) +- `a11yLabel(string)` - screen-reader label for icon-only actions +- `destructive(bool = true)` - tint the item as destructive +- `checked(bool = true)` - show a checkmark on the item (nav-bar menus) +- `NavAction::divider()` - a separator row +- `NavAction::section(?string $title = null, array $items = [])` - an inline group of items under an optional heading + (nav-bar menus) +- `NavAction::row(array $items)` - a compact row of icon-over-label buttons (nav-bar menus) See the [`NavAction` builder](../the-basics/layouts#builder-reference) for the full list. diff --git a/resources/views/docs/mobile/4/edge-components/top-bar.md b/resources/views/docs/mobile/4/edge-components/top-bar.md index 493d3cf8..5122cc2a 100644 --- a/resources/views/docs/mobile/4/edge-components/top-bar.md +++ b/resources/views/docs/mobile/4/edge-components/top-bar.md @@ -96,13 +96,17 @@ On iOS, if more than 5 actions are provided, they collapse into an overflow menu ### `` Props -- `id` - Unique identifier (required) +- `id` - Unique identifier (required, except on a `section` or `row`) - `icon` - A named [icon](icon#icon-name-reference) — the cross-platform fallback (optional if a platform icon is given) - `ios-icon` / `android-icon` - Per-platform icon overrides: an enum case (`App\Icons\Ios`, `App\Icons\Android`, `App\Icons\AndroidOutlined`) or a raw symbol string. `ios` / `android` are accepted as shorthand (optional). See [Platform icons](#platform-icons) - `material-variant` - Material style hint for Android, e.g. `outlined` (optional). Set automatically when you use an `AndroidOutlined` enum case - `label` - Text label. Used for accessibility and displayed in overflow menus (optional but recommended) - `url` - A URL to navigate to when tapped (optional) - `destructive` - Render in the destructive (red) tint (optional, boolean) +- `subtitle` - A second, smaller line under the label, for an action inside a menu (optional, string) +- `checked` - Show a checkmark, for an action inside a menu (optional, boolean) +- `section` - Group the actions nested inside this one, with `label` as the heading (optional, boolean). See [Menus](#menus) +- `row` - Show the actions nested inside this one as a compact row of icon-over-label buttons (optional, boolean). See [Menus](#menus) +### Menus + +Nest `` elements inside an action and it opens a pull-down menu of them instead of firing a +press. Inside a menu, an action with its own nested actions is a submenu, and the `section` and `row` attributes +group items the way [`NavAction::section()` and `NavAction::row()`](menus#sections-rows-and-submenus) do: + +@verbatim +```blade static + + + + + + + + + + + +``` +@endverbatim + +See [Menus](menus#menus-in-blade) for a full example and how menus look on each platform. A `custom` bar draws its +actions as plain buttons and ignores nested actions. + ### Platform icons `` resolves icons through the same contract as [``](icon#typed-icon-enums): a diff --git a/resources/views/docs/mobile/4/the-basics/layouts.md b/resources/views/docs/mobile/4/the-basics/layouts.md index d755d9a2..0daf233f 100644 --- a/resources/views/docs/mobile/4/the-basics/layouts.md +++ b/resources/views/docs/mobile/4/the-basics/layouts.md @@ -147,7 +147,10 @@ Any icon you pass to these builders can also be one of your own - `press(string $method)` — screen method to call when tapped - `url(string)` — navigate to a URL when tapped; `event(string)` — dispatch a native event (advanced) - `destructive(bool = true)` — render in the destructive tint -- `items(array $actions)` — nest `NavAction`s to render a pull-down menu; `NavAction::divider()` adds a separator +- `items(array $actions)` — nest `NavAction`s to render a pull-down menu; `NavAction::divider()` adds a separator, + `NavAction::section($title, $items)` groups items under a heading, `NavAction::row($items)` adds a compact row of + buttons, and an item with its own `items()` opens a submenu. See [Sections, rows and submenus](../edge-components/menus#sections-rows-and-submenus) +- `subtitle(string)` and `checked(bool = true)` add a second line and a checkmark to an item inside a menu #### Custom title view / logo