Files
livewire-material/resources/views/components/section-nav.blade.php
T
Andreas Reinhold / reiniandClaude Opus 5 1e580c573e Resolve the package's own components through its namespace
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
2026-09-13 09:05:24 +02:00

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>