App shell — a full-width top bar (brand + inline context + actions) over a fixed, collapsible left sidebar and a main content column. Breadcrumb chrome is a first-class layout region (goprint-style sticky trail under the appbar), not a per-app one-off.
<.app_shell id="app">
<:brand><.icon name="bolt" /> <span class="lui-brand-name">Acme</span></:brand>
<:header>…switchers…</:header>
<:actions>…user menu…</:actions>
<:breadcrumb>
<.breadcrumb items={@breadcrumbs} />
</:breadcrumb>
<:sidebar>
<.nav_group label="Workspace">
<.nav_item label="Dashboard" icon="chart-bar" navigate="/" active />
<.nav_item label="Buckets" icon="cloud" navigate="/buckets" />
</.nav_group>
</:sidebar>
<:sidebar_footer>
<.nav_link label="Documentation" icon="book-open" href="/docs" />
<.nav_link label="Terms" href="/terms" />
</:sidebar_footer>
<.page_header title="Buckets" description="Object storage.">
<:actions><.button>New</.button></:actions>
</.page_header>
main content…
</.app_shell>page_header/1 can also be used on its own. breadcrumb_bar/1 is the
standalone breadcrumb region used by app_shell/1 and can wrap a
breadcrumb/1 plus an optional actions slot.
The brand sits top-left; :header is inline context in the appbar (switchers);
:breadcrumb is the compact sticky trail under the appbar; optional
:breadcrumb_actions are right-aligned on that same bar (Linear pattern);
:actions is top-right of the appbar. A collapse control at the sidebar's
foot toggles the icon rail; the state persists per id in localStorage via
the LanternSidebar hook.
On narrow viewports the sidebar becomes an off-canvas drawer opened by the
hamburger in the bar, over a scrim. It closes on scrim click, Escape, and on
tapping a nav item — so a navigate link doesn't leave the drawer covering
the page it just went to.
Summary
Functions
Compact sticky breadcrumb region for use outside app_shell (or when the
host app still owns the outer shell). Same chrome app_shell's
:breadcrumb slot renders.
A labelled group of nav items. The label hides when the rail is collapsed.
A sidebar nav item. Renders a link when given navigate/patch/href, or a
button when given phx-click. Collapses to an icon-only rail item (with a
tooltip) when the sidebar is collapsed.
A quiet link for the shell's :sidebar_footer — support, docs, legal.
Page title row — compact, goprint-density. Renders under the breadcrumb bar inside main content. Title + optional description + right-side actions.
Functions
Attributes
id(:string) (required) - stable id — the collapse state is persisted per id.collapsed(:boolean) - Initial sidebar collapsed (icon-rail) state. Defaults tofalse.class(:any) - Extra classes merged onto the root element. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
brand(required) - logo/name, top-left corner.header- inline context after the brand (switchers, etc.).actions- top-right of the bar (user menu, etc.).breadcrumb- compact sticky trail under the appbar (pass <.breadcrumb>).breadcrumb_actions- Right-side actions on the breadcrumb bar (same region as breadcrumb_bar/1 :actions). Omitted when empty so existing call sites stay unchanged. Accepts attributes:label(:string) - Label used when this entry collapses into the breadcrumb overflow menu.phx-click(:string) - LiveView click event on the overflow menu item.phx-value-id(:string) - Optional phx-value-id for the overflow menu item.phx-target(:any) - LiveView target for the overflow menu item.disabled(:boolean) - Disable the overflow menu item.navigate(:string) - Destination for a NAVIGATING entry. REQUIRED on any entry whose inline button navigates: a folded item renders from these attrs, not from the slot body, so an entry carrying a path only on its inner button becomes a menu item with no click target and silently does nothing.patch(:string) - Live-patch destination for a folded navigating entry.href(:any) - Plain href for a folded navigating entry.data-confirm(:string) - Confirmation prompt for the folded menu item. REQUIRED on destructive entries: a folded item renders from these attrs, not from the slot body, so a confirm set only on an inner button is lost once the entry passes :max_inline.
sidebar(required) - nav_group / nav_item.sidebar_footer- Persistent links pinned below the nav and above the collapse control (support, docs, legal). Passnav_link/1s. Hidden on the icon rail, where there is no room for text-only links.inner_block(required) - Main content column.
Compact sticky breadcrumb region for use outside app_shell (or when the
host app still owns the outer shell). Same chrome app_shell's
:breadcrumb slot renders.
With an :actions slot, the bar is the Linear-style action row: trail on
the left, actions right-aligned. At most :max_inline entries (default 2)
render as quick buttons; everything after that folds into a More menu (the
APG menu/1 — no extra JS).
The cap is fixed, not width-based. A responsive cap would have to hide an inline button that is not in the menu, which makes that action unreachable at narrow widths; a fixed split keeps every action reachable at every size.
<.breadcrumb_bar>
<.breadcrumb home="/" items={@crumbs} />
<:actions>
<.button size="sm">New project</.button>
</:actions>
</.breadcrumb_bar>
<.breadcrumb_bar>
<.breadcrumb home="/" items={@crumbs} />
<:actions><.button size="sm">New</.button></:actions>
<:actions label="Import" phx-click="import">
<.button size="sm" phx-click="import">Import</.button>
</:actions>
<:actions label="Export" phx-click="export">
<.button size="sm" phx-click="export">Export</.button>
</:actions>
</.breadcrumb_bar>Without :actions, markup is unchanged from the trail-only chrome.
Attributes
class(:any) - Extra classes merged onto the root element. Defaults tonil.id(:string) - Stable id for the overflow menu when multi-entry actions collapse; auto-generated when omitted. Defaults tonil.max_inline(:integer) - How many entries render as quick buttons before the rest fold into the More menu. Defaults to2.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
inner_block(required) - Usually a single <.breadcrumb>.actions- Right-side actions. The first:max_inlineentries render as quick buttons; the rest fold into a More menu. Accepts attributes:label(:string) - Label used for this entry when it is collapsed into the overflow menu.phx-click(:string) - LiveView click event on the overflow menu item.phx-value-id(:string) - Optional phx-value-id for the overflow menu item.phx-target(:any) - LiveView target for the overflow menu item.disabled(:boolean) - Disable the overflow menu item.navigate(:string) - Destination for a NAVIGATING entry. REQUIRED on any entry whose inline button navigates: a folded item renders from these attrs, not from the slot body, so an entry carrying a path only on its inner button becomes a menu item with no click target and silently does nothing.patch(:string) - Live-patch destination for a folded navigating entry.href(:any) - Plain href for a folded navigating entry.data-confirm(:string) - Confirmation prompt for the folded menu item. REQUIRED on destructive entries: a folded item renders from these attrs, not from the slot body, so a confirm set only on an inner button is lost once the entry passes :max_inline.
Page title row — compact, goprint-density. Renders under the breadcrumb bar inside main content. Title + optional description + right-side actions.
Attributes
title(:string) - Page heading. Defaults tonil.description(:string) - Optional supporting line under the title. Defaults tonil.class(:any) - Extra classes merged onto the root element. Defaults tonil.- Global attributes are accepted. Arbitrary HTML/
phx-*attributes passed through.
Slots
actions- Right-side actions (buttons, menus).inner_block- Optional body under the title row (rarely needed).