Navigation
Navigation chrome lives inside a layout — the sidebars, menus, dropdowns, and breadcrumbs that wrap your pages. These are server-driven components built from PHP, so a renamed route or a changed permission updates the navigation with no client work. This page covers those components; see Layouts for the shell they sit in.
The sidebar’s links are Menu and MenuItem components:
Sidebar::make()->collapsible()->items([...])— the shell sidebar;collapsible()remembers its open state. Below themdbreakpoint it becomes an off-canvas drawer instead of consuming layout width.- The sidebar renders no toggle button itself. Place one wherever you like (typically the
Topbar) with aButtonthat fires thetoggle-sidebareffect on the client — see below. Menu::make()->items([...])— a list of menu items.MenuItem::make($label)->href($url)->icon($icon)— a link. Nest a group with->children([...]).MenuItem::fromPage(SomePage::class)— builds an item that links to a page’s route automatically, so the URL stays in sync with the page. Override the label with->label().
MenuItem::fromPage(ProductsPage::class)->label('Products')->icon(Icon::Table);Because menu items reference pages by class, navigation can’t drift out of sync with the pages it links to — a renamed route updates the link with no extra work.
A menu item can submit with a non-GET method — useful for a logout link — by setting ->method():
use Lattice\Lattice\Core\Enums\HttpMethod;
MenuItem::make('Log out')->href(route('logout', absolute: false))->icon('log-out')->method(HttpMethod::Post);Toggling the sidebar
Section titled “Toggling the sidebar”A Button can dispatch effects on the client when clicked — no request to the server. The
toggle-sidebar effect collapses the rail on desktop and opens the off-canvas drawer on mobile, so
the toggle button can live anywhere (here, in the Topbar):
use Lattice\Lattice\Ui\Components\Button;use Lattice\Lattice\Ui\Enums\ButtonVariant;use Lattice\Lattice\Facades\Effects;
Button::make('Toggle sidebar', 'sidebar-toggle') ->icon('panel-left') ->variant(ButtonVariant::Ghost) ->effects(Effects::toggleSidebar('app-sidebar'));->effects() accepts any effect, giving a button instant client-side behavior (open a modal, show a
toast, reset a form) without a round-trip.
Dropdowns
Section titled “Dropdowns”Dropdown renders a composed trigger that reveals its MenuItems in a popover — for grouping actions
without nesting them in the sidebar tree:
use Lattice\Lattice\Ui\Components\Icon;use Lattice\Lattice\Ui\Components\Text;use Lattice\Lattice\Ui\Enums\Placement;use Lattice\Lattice\Layouts\Components\Dropdown;use Lattice\Lattice\Layouts\Components\MenuItem;
Dropdown::make('account-menu') ->placement(Placement::Bottom) ->trigger([ Icon::make('settings'), Text::make('Account'), ]) ->items([ MenuItem::fromPage(SettingsPage::class)->label('Settings'), MenuItem::make('Log out')->href(route('logout', absolute: false))->method(HttpMethod::Post), ]);Raw blocks
Section titled “Raw blocks”RawBlock renders trusted server HTML. Use it for small layout-specific fragments such as an avatar,
team glyph, or badge when a dedicated Lattice component would be too specific:
use Lattice\Lattice\Ui\Components\RawBlock;
RawBlock::make('avatar')->blade('components.avatar', [ 'name' => $user->name, 'src' => $user->avatar,]);Use ->html() when the markup is already available:
RawBlock::make('initials')->html('<span class="avatar">AL</span>');User dropdown
Section titled “User dropdown”Build user menus from the same dropdown shell. The avatar, identity text, and menu placement are all server-driven, so there is no dedicated frontend component:
use Lattice\Lattice\Ui\Components\RawBlock;use Lattice\Lattice\Ui\Components\Stack;use Lattice\Lattice\Ui\Components\Text;use Lattice\Lattice\Ui\Enums\Placement;use Lattice\Lattice\Layouts\Components\Dropdown;use Lattice\Lattice\Layouts\Components\MenuItem;
$user = $request->user();
Dropdown::make('user-menu') ->placement(Placement::Top) ->trigger([ Stack::make('user-menu-trigger')->direction('row')->schema([ RawBlock::make('avatar')->blade('components.avatar', [ 'name' => $user->name, 'src' => $user->avatar, ]), Stack::make('user-menu-identity')->schema([ Text::make($user->name), Text::make($user->email), ])->hideWhenCollapsed(), ]), ]) ->items([ MenuItem::fromPage(SettingsPage::class)->label('Settings'), MenuItem::make('Log out')->href(route('logout', absolute: false))->method(HttpMethod::Post), ]);Breadcrumbs
Section titled “Breadcrumbs”Breadcrumbs::make() renders the current page’s breadcrumb trail. It carries no data of its own — it
reads whatever the active page returns from Page::breadcrumbs(), so drop it once in your layout (a
header bar is the usual spot) and every page fills it in:
use Lattice\Lattice\Layouts\Components\Breadcrumbs;
Stack::make('app-main')->width(Width::Fill)->schema([ Breadcrumbs::make(), Outlet::make(),]);Pinning a sidebar footer
Section titled “Pinning a sidebar footer”To keep navigation at the top of the sidebar and a user menu pinned to the bottom, wrap them in a
full-height Stack with ->justify(Justify::Between). A column Stack lays out as a grid by default;
giving it a justify switches it to a flex column so the space distributes:
use Lattice\Lattice\Ui\Enums\Justify;use Lattice\Lattice\Ui\Enums\Placement;use Lattice\Lattice\Ui\Enums\Width;use Lattice\Lattice\Ui\Components\RawBlock;use Lattice\Lattice\Ui\Components\Stack;use Lattice\Lattice\Ui\Components\Text;use Lattice\Lattice\Layouts\Components\Dropdown;use Lattice\Lattice\Layouts\Components\Menu;use Lattice\Lattice\Layouts\Components\MenuItem;use Lattice\Lattice\Layouts\Components\Sidebar;
Sidebar::make('app-sidebar')->collapsible()->items([ Stack::make('sidebar-body')->width(Width::Fill)->justify(Justify::Between)->schema([ Menu::make('sidebar')->items([ MenuItem::fromPage(HomePage::class)->icon('house'), ]), Dropdown::make('user-menu') ->placement(Placement::Top) ->trigger([ RawBlock::make('avatar')->blade('components.avatar', ['name' => $user->name]), Text::make($user->name)->hideWhenCollapsed(), ]) ->items([ MenuItem::make('Log out')->href(route('logout', absolute: false))->method(HttpMethod::Post), ]), ]),]);