Package views now write <x-livewire-material::button>, so a configured prefix (which Blade spells <x-m::button>) and an application component of the same name can no longer break or shadow them. The showcase rewrites its examples to the configured prefix. Adds the README, and waits for the adaptive rail to hear a resize before the navigation tests press its menu button. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
82 lines
3.9 KiB
PHP
82 lines
3.9 KiB
PHP
{{-- The navigation inside one area of an app — the sections of settings, of an admin — which is a
|
|
single destination in the app's own navigation.
|
|
|
|
`items`, a list of `['title' => …, 'url' => …]` with an optional `icon`, `active` and `badge`
|
|
(an item is current when `active` is true, or when its `url` is the request's). From `sm` they
|
|
are M3's secondary tabs as links, the current one underlined; below `sm`, where a row of them
|
|
never fits, a button naming the current section opens a menu of all of them. The same list is
|
|
rendered for both, and CSS shows one.
|
|
|
|
A row too long for its column wraps onto a grid rather than scrolling: below `xl` five or six
|
|
sections go 3 + 3 and seven or more go four to a row — tabs that scroll hid the last sections on
|
|
a tablet. `label` names the navigation ("Sections"). Links use `wire:navigate` unless
|
|
`no-wire-navigate`. --}}
|
|
|
|
@props([
|
|
'items' => [],
|
|
'label' => null,
|
|
'noWireNavigate' => false,
|
|
])
|
|
|
|
@php
|
|
$label ??= __('Sections');
|
|
$isCurrent = fn (array $item): bool => ($item['active'] ?? false) || (filled($item['url'] ?? null) && url()->current() === url($item['url']));
|
|
$current = collect($items)->first($isCurrent) ?? ($items[0] ?? null);
|
|
|
|
$layout = match (true) {
|
|
count($items) < 5 => 'sm:flex',
|
|
count($items) < 7 => 'sm:grid sm:grid-cols-3 xl:flex',
|
|
default => 'sm:grid sm:grid-cols-4 xl:flex',
|
|
};
|
|
@endphp
|
|
|
|
<div {{ $attributes->class(['min-w-0']) }} data-section-nav>
|
|
@if ($current)
|
|
<div class="sm:hidden" data-section-picker>
|
|
<x-livewire-material::menu :$label position="bottom-start">
|
|
<x-slot:trigger>
|
|
<button type="button" class="focus-ring flex h-12 w-[min(20rem,calc(100vw-2rem))] cursor-pointer items-center gap-3 rounded-corner-xs border border-outline px-4 text-start type-body-lg text-on-surface">
|
|
@isset($current['icon'])
|
|
<x-livewire-material::icon :name="$current['icon']" class="size-5 text-on-surface-variant" />
|
|
@endisset
|
|
<span class="min-w-0 flex-1 truncate">{{ $current['title'] }}</span>
|
|
<x-livewire-material::icon name="arrow_drop_down" class="size-6 text-on-surface-variant" />
|
|
</button>
|
|
</x-slot:trigger>
|
|
|
|
@foreach ($items as $item)
|
|
<x-livewire-material::menu-item :label="$item['title']" :icon="$item['icon'] ?? null" :link="$item['url']" :selected="$isCurrent($item)" :no-wire-navigate="$noWireNavigate" />
|
|
@endforeach
|
|
</x-livewire-material::menu>
|
|
</div>
|
|
@endif
|
|
|
|
<nav aria-label="{{ $label }}" class="max-sm:hidden">
|
|
<ul data-tabs-bar data-variant="secondary" class="{{ $layout }}">
|
|
@foreach ($items as $item)
|
|
@php($on = $isCurrent($item))
|
|
|
|
<li class="flex min-w-0">
|
|
<a
|
|
href="{{ $item['url'] }}"
|
|
data-tab
|
|
@if ($on) aria-current="page" @endif
|
|
@unless ($noWireNavigate) wire:navigate @endunless
|
|
>
|
|
<span data-tab-content>
|
|
@isset($item['icon'])
|
|
<x-livewire-material::icon :name="$item['icon']" :filled="$on" class="size-5" />
|
|
@endisset
|
|
<span class="truncate">{{ $item['title'] }}</span>
|
|
@if (filled($item['badge'] ?? null))
|
|
<x-livewire-material::badge :value="$item['badge']" />
|
|
@endif
|
|
<span data-tab-indicator aria-hidden="true"></span>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
</nav>
|
|
</div>
|