{{-- M3 Expressive's top app bar: the title of the screen, a navigation button and its actions. `variant`: `small` (the default, 64px), `center` (the title centred), `medium` and `large` (a big title under the row that collapses into the small one as the page scrolls), and `search` (a search bar fills the row: put an `` in the slot). `title` and `subtitle`; the title is an `

` unless `heading` names another element. Slots: `navigation` (the leading icon button: back, or the menu) and `actions` (trailing icon buttons, an avatar). `actions` can instead be a list, `:actions="[['label' => 'Share', 'icon' => 'share', 'wire:click' => 'share'], …]"`, in the order of use — M3 puts the most used nearest the headline. Each entry takes what `` takes: `label` and `icon`, `link` (with `external` or `no-wire-navigate`), `disabled`, `selected`, and any other key — `wire:click`, `x-on:click` — as an attribute. Every entry is rendered twice, as an icon button named and tooltipped by its label and as a menu item, and the window's width decides which one shows. M3 allows "up to two icon buttons" after the headline, gives a larger screen "up to four trailing icons" (said of the search app bar, the only count it gives for a wider window), and lets actions at the trailing edge "collapse into an overflow menu at smaller breakpoints" and "become visible again at larger sizes" (docs/reference/m3/components-navigation-selection-inputs.md § Top App Bar → Behaviour and guidelines). So below `medium` (600px) the bar shows at most two icon buttons and from there at most four, the overflow button — `more_vert`, "More options" — counted among them: with more actions than that, the first one (or three) stay and the rest go into its menu. Each width has a menu of its own holding only what overflows there, so the arrow keys never land on a hidden row, and it is all CSS (resources/css/components/app-bar.css): nothing moves after the page has drawn. Only the list overflows; markup in the slot is drawn as written. A slot and a list are alternatives — a slot of the same name replaces the attribute. Sticky at the top by default (`:sticky="false"` for one that scrolls away), under the top safe area; the surface turns surface-container once content scrolls under it (resources/css/components/app-bar.css, resources/js/app-bar.js). A collapsing bar needs the window to be what scrolls: an ancestor with `overflow: hidden` or `auto` would stop it sticking (`overflow-x: clip` is fine). The root renders `data-md-app-bar` with `data-md-variant`, `data-md-sticky`, `data-md-subtitled`, and `data-md-scrolled`/`data-md-collapsed` once the page has scrolled under it; its row is `data-md-app-bar-row` holding `data-md-app-bar-leading`, `data-md-app-bar-headline` (`data-md-app-bar-title`, `data-md-app-bar-subtitle`), `data-md-app-bar-search` and `data-md-app-bar-trailing` (`data-md-app-bar-action`, `data-md-app-bar-overflow`); a flexible bar's big title is `data-md-app-bar-expanded`. Drawn by resources/css/components/app-bar.css, which imports button.css, menu.css and menu-item.css for what the view renders. --}} @props([ 'title' => null, 'subtitle' => null, 'variant' => 'small', 'sticky' => true, 'heading' => 'h1', 'actions' => null, ]) @php $variant = in_array($variant, ['small', 'center', 'medium', 'large', 'search'], true) ? $variant : 'small'; $flexible = in_array($variant, ['medium', 'large'], true); $heading = in_array($heading, ['h1', 'h2', 'h3', 'div', 'p'], true) ? $heading : 'h1'; // The list form of `actions`, each entry split into the props an icon button and a menu item // share and the attributes (its action) both of them carry. $list = is_iterable($actions) ? collect($actions)->values()->map(fn (array $action): array => [ 'label' => $action['label'] ?? null, 'icon' => $action['icon'] ?? null, 'link' => $action['link'] ?? null, 'external' => (bool) ($action['external'] ?? false), 'noWireNavigate' => (bool) ($action['noWireNavigate'] ?? $action['no-wire-navigate'] ?? false), 'disabled' => (bool) ($action['disabled'] ?? false), 'selected' => $action['selected'] ?? null, 'attributes' => new \Illuminate\View\ComponentAttributeBag(\Illuminate\Support\Arr::except($action, [ 'label', 'icon', 'link', 'external', 'noWireNavigate', 'no-wire-navigate', 'disabled', 'selected', ])), ])->all() : null; // How many stay icon buttons: two trailing icon buttons below `medium`, four from it, the // overflow button one of them whenever it is there. $count = count($list ?? []); $shown = [ 'compact' => $count > 2 ? 1 : $count, 'medium' => $count > 4 ? 3 : $count, ]; @endphp
@isset($navigation)
{{ $navigation }}
@endisset @if ($variant === 'search')
{{ $slot }}
@elseif (filled($title)) @endif @if ($list !== null) @if ($count > 0)
@foreach ($list as $index => $action) @if ($index < $shown['medium']) = $shown['compact']) data-md-overflows-compact @endif> @endif @endforeach @foreach ($shown as $width => $kept) @if ($count > $kept) @foreach (array_slice($list, $kept) as $action) @endforeach @endif @endforeach
@endif @elseif (isset($actions))
{{ $actions }}
@endif
@if ($flexible && filled($title))
<{{ $heading }} data-md-app-bar-title>{{ $title }} @if (filled($subtitle))

{{ $subtitle }}

@endif
@endif @if ($variant !== 'search' && $slot->hasActualContent()) {{ $slot }} @endif