{{-- M3's tabs: the sections of one thing, with the chosen one marked by an active indicator. The bar is rendered on the server from `tabs`, a list of `['name' => …, 'label' => …]` with an optional `icon`, `badge` and `disabled` — so it arrives with the page, never a moment after it. The panels are `` in the slot; every panel is rendered, so switching never waits on the server. The chosen tab is the Livewire property in `wire:model` (entangled; `wire:model.live` tells the server at once), or, without it, `selected` (the first tab by default) and `x-model`. The bar is a real tablist (resources/js/tabs.js). `variant` is `primary` (the default: the indicator under the label, in primary) or `secondary` (under the whole tab, for tabs inside a section); `stacked` puts a primary tab's icon over its label (64px); `scrollable` lets tabs keep their own width and scroll sideways instead of sharing the width equally (resources/css/components/tabs.css). --}} @props([ 'tabs' => [], 'variant' => 'primary', 'selected' => null, 'stacked' => false, 'scrollable' => false, ]) @php $model = $attributes->wire('model')->value() ?: null; $variant = $variant === 'secondary' ? 'secondary' : 'primary'; $id = $attributes->get('id') ?? 'tabs-'.substr(md5($model.'|'.implode('|', array_column($tabs, 'name'))), 0, 8); $initial = $selected ?? (collect($tabs)->first(fn (array $tab): bool => ! ($tab['disabled'] ?? false))['name'] ?? null); if ($model !== null && ($component = \Livewire\Livewire::current()) !== null && filled(data_get($component, $model))) { $initial = data_get($component, $model); } @endphp
whereDoesntStartWith('wire:model')->except(['id'])->class(['min-w-0']) }} >
@foreach ($tabs as $tab) @php($isInitial = (string) $tab['name'] === (string) $initial) @endforeach
{{ $slot }}