Skip to content

Sidebar

The sidebar shows the brand of the panel (logo and name, a link to the dashboard) and one entry per page and resource.

For each page and resource of the panel the sidebar shows one entry, if

  1. it registers itself in the navigation (shouldRegisterNavigation()), and
  2. the user may open it: the page permission (<panel>.page.<slug>, or none if permission() returns null), the view permission of a resource (canViewAny()).

The dashboard needs no permission, so every user of the panel sees it.

Page Resource Default Purpose
navigationLabel() pluralLabel() / $pluralLabel title / plural of the resource name text of the entry
navigationIcon() $navigationIcon file-earmark / folder Bootstrap icon without bi-
navigationGroup() $navigationGroup or navigationGroup() null label of the group
navigationSort() $navigationSort 0 order within the group (lower first)
shouldRegisterNavigation() $registerNavigation or shouldRegisterNavigation() true false keeps the entry out of the sidebar; the page stays reachable
navigationBadge(), navigationBadgeColor() same null, secondary see Badges
final class InvoiceResource extends Resource
{
protected string $navigationIcon = 'receipt';
protected ?string $navigationGroup = 'Sales';
protected int $navigationSort = 10;
}
final class ReportsPage extends Page
{
public function title(): string { return 'Monthly report'; }
public function navigationLabel(): string { return 'Reports'; } // shorter than the title
public function navigationIcon(): string { return 'bar-chart'; }
public function navigationGroup(): ?string { return 'Reports'; }
public function navigationSort(): int { return 20; }
}

Resources can compute the group, e.g. from a setting, by overriding navigationGroup() instead of setting the property.

Entries are sorted by their sort value, then by label. Entries without a group come first, then the groups in the order of navigationGroups(), then other groups alphabetically.

Entry Sort value
Dashboard -100
Inbox -10
your pages and resources 0 unless set

Use steps of ten (10, 20, …) to leave room for later entries.

A page that is only reached from a link, the user menu or a button returns false:

final class ImportPage extends Page
{
public function shouldRegisterNavigation(): bool
{
return false;
}
}

The page keeps its URL and its permission. For resources set protected bool $registerNavigation = false; – e.g. for a resource that is only used as a relation of another one.

The entry whose URL is the longest prefix of the current URL is marked as active (aria-current="page"): /admin/invoices/<uuid>/edit marks “Invoices”. A group with the active entry always starts open.

  • Large screens: the button at the bottom reduces the sidebar to icons; the label and badge appear as a tooltip. The browser remembers the choice for all panels.
  • Small screens: the sidebar is hidden and opens from the menu button in the topbar as an overlay; it closes with the close button, Esc or a click outside.

Logo and name come from the panel (brand(), logo()), see Panels → Configuration. Without a logo Anvil shows its mark and the name.