Navigation
Control how resources appear in the menu and how users navigate between screens.
Menu placement
Set the group, sort order, and label on your resource:
class CustomerResource extends Resource
{
protected static ?string $navigationGroup = 'Sales'; // Menu tab
protected static int $navigationSort = 1; // Position within tab
protected static ?string $navigationLabel = 'Customers'; // Defaults to $label
protected static bool $showInNavigation = true; // false to hide from menu
}Tab order
Resources are grouped into menu tabs by $navigationGroup. Control the tab sequence in config/twowee.php:
'menu' => [
'default_tab' => 'Home',
'tab_order' => ['Home', 'Sales', 'Purchasing', 'Finance'],
],Tabs not listed appear at the end alphabetically.
Example
class CustomerResource extends Resource {
protected static ?string $navigationGroup = 'Sales';
protected static int $navigationSort = 1;
}
class ItemResource extends Resource {
protected static ?string $navigationGroup = 'Sales';
protected static int $navigationSort = 2;
}
class SalesOrderResource extends Resource {
protected static ?string $navigationGroup = 'Sales';
protected static int $navigationSort = 3;
protected static bool $navigationSeparatorBefore = true; // divider above
}
class VendorResource extends Resource {
protected static ?string $navigationGroup = 'Purchasing';
protected static int $navigationSort = 1;
}
class CustomerLedgerEntryResource extends Resource {
protected static bool $showInNavigation = false; // only via drill-down
}This produces:
- Sales: Customers, Items, ─── (separator), Sales Orders
- Purchasing: Vendors
Popup groups
Group related destinations into a floating sub-list. Resources with the same $navigationPopup value (within the same group) appear together under one label:
class PostedInvoiceResource extends Resource {
protected static ?string $navigationGroup = 'Sales';
protected static ?string $navigationPopup = 'Posted';
protected static int $navigationSort = 10;
}
class PostedCreditMemoResource extends Resource {
protected static ?string $navigationGroup = 'Sales';
protected static ?string $navigationPopup = 'Posted';
protected static int $navigationSort = 11;
}The user sees "Posted ▸" in the Sales tab. Enter opens a floating list: Posted Invoices, Posted Credit Memos.
Separators
Add a visual divider above an item to break a long tab into logical groups:
class SalesOrderResource extends Resource {
protected static bool $navigationSeparatorBefore = true;
}The separator is a blank line — not selectable, navigation skips it.
Navigation parent
Every screen has a parent — where Escape goes when there's no navigation history. The plugin sets this automatically:
- Card / HeaderLines → the resource's list screen
- List / Grid →
/menu/main
For resources under a sub-menu, override it:
class PostedInvoiceResource extends Resource {
protected static ?string $navigationParent = 'menu/sales';
}The Escape chain then builds automatically:
Posted Invoice Card → Escape → Posted Invoices List → Escape → Sales Sub-Menu → Escape → Main MenuMost resources don't need this — the default is correct when resources live directly under the main menu.
Custom menu items
Add placeholders, sub-menus, or other non-resource items via config:
// config/twowee.php
'menu' => [
'items' => [
['label' => 'Reports', 'group' => 'Finance', 'sort' => 99,
'action' => ['type' => 'message', 'text' => 'Coming soon.']],
['label' => 'Setup', 'group' => 'Admin', 'sort' => 1,
'action' => ['type' => 'open_menu', 'url' => '/terminal/menu/setup']],
],
],| Action type | Behavior |
|---|---|
open_screen | Navigate to a screen URL |
open_menu | Open a sub-menu |
popup | Floating list of destinations |
message | Show text in the status bar |
separator | Visual divider |
open_url | Open URL in system browser |