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
80 lines
3.1 KiB
PHP
80 lines
3.1 KiB
PHP
{{-- Who is signed in, and what belongs to them rather than to a page: an avatar that opens a menu.
|
|
|
|
`name` and `email` head the menu; `avatar` is an image URL or, by default, the initials of the
|
|
name. The slot holds the items (`<x-menu-item>`: settings, billing…), a theme item follows unless
|
|
`:theme="false"`, and the `footer` slot comes last, after a separator — the place for signing
|
|
out, furthest from the thumb:
|
|
|
|
<x-account-menu :name="$user->name" :email="$user->email">
|
|
<x-menu-item label="Settings" icon="settings" :link="route('settings')" />
|
|
<x-slot:footer>
|
|
<form method="POST" action="{{ route('logout') }}">
|
|
@csrf
|
|
<x-menu-item label="Sign out" icon="logout" type="submit" />
|
|
</form>
|
|
</x-slot:footer>
|
|
</x-account-menu>
|
|
|
|
`label` names the button and the menu ("Account"). `position` as on `<x-menu>` (`bottom-end`). --}}
|
|
|
|
@props([
|
|
'name' => null,
|
|
'email' => null,
|
|
'avatar' => null,
|
|
'label' => null,
|
|
'theme' => true,
|
|
'position' => 'bottom-end',
|
|
])
|
|
|
|
@php
|
|
$label ??= __('Account');
|
|
$image = filled($avatar) && (str_contains((string) $avatar, '/') || str_contains((string) $avatar, '.'));
|
|
$initials = $image ? null : ($avatar ?? \Illuminate\Support\Str::of((string) $name)->explode(' ')->filter()->take(2)->map(fn (string $word): string => mb_strtoupper(mb_substr($word, 0, 1)))->join(''));
|
|
@endphp
|
|
|
|
<x-livewire-material::menu :$label :$position {{ $attributes }}>
|
|
<x-slot:trigger>
|
|
<button
|
|
type="button"
|
|
aria-label="{{ $label }}"
|
|
data-account-menu
|
|
class="focus-ring inline-flex size-10 shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-corner-full bg-primary-container type-label-lg text-on-primary-container"
|
|
>
|
|
@if ($image)
|
|
<img src="{{ $avatar }}" alt="" class="size-full object-cover" />
|
|
@elseif (filled($initials))
|
|
{{ $initials }}
|
|
@else
|
|
<x-livewire-material::icon name="person" />
|
|
@endif
|
|
</button>
|
|
</x-slot:trigger>
|
|
|
|
@if (filled($name) || filled($email))
|
|
<div class="px-3 pt-2 pb-3">
|
|
@if (filled($name))
|
|
<p class="truncate type-title-sm text-on-surface">{{ $name }}</p>
|
|
@endif
|
|
@if (filled($email))
|
|
<p class="truncate type-body-sm text-on-surface-variant">{{ $email }}</p>
|
|
@endif
|
|
</div>
|
|
|
|
<x-livewire-material::menu-separator />
|
|
@endif
|
|
|
|
{{ $slot }}
|
|
|
|
@if ($theme)
|
|
<x-livewire-material::menu-item icon="contrast" x-on:click="$store.theme.toggle()" data-account-theme>
|
|
<span x-text="$store.theme.resolved === 'dark' ? @js(__('Light theme')) : @js(__('Dark theme'))">{{ __('Theme') }}</span>
|
|
</x-livewire-material::menu-item>
|
|
@endif
|
|
|
|
@isset($footer)
|
|
<x-livewire-material::menu-separator />
|
|
|
|
{{ $footer }}
|
|
@endisset
|
|
</x-livewire-material::menu>
|