Deploy Ladill Transfer / deploy (push) Successful in 41s
Remove desktop header search, wire mobile search to the transfers and files page, refine file icons and Shared badge, and align Transfers toolbar with Files. Co-authored-by: Cursor <cursoragent@cursor.com>
139 lines
8.5 KiB
PHP
139 lines
8.5 KiB
PHP
@php
|
|
$gridCols = !empty($centerCompose) ? 'grid-cols-5' : 'grid-cols-4';
|
|
$avatarUrl = $avatarUrl ?? null;
|
|
$initials = $initials ?? 'U';
|
|
$notificationsUrl = $notificationsUrl ?? '#';
|
|
$unreadUrl = $unreadUrl ?? null;
|
|
$profileUrl = $profileUrl ?? '#';
|
|
$profileName = trim((string) ($profileName ?? ''));
|
|
$profileSubtitle = trim((string) ($profileSubtitle ?? ''));
|
|
$profileMenuItems = $profileMenuItems ?? [];
|
|
if ($profileMenuItems === [] && $profileUrl !== '#') {
|
|
$profileMenuItems = [['type' => 'link', 'label' => 'Profile', 'href' => $profileUrl]];
|
|
}
|
|
$searchLabel = $searchLabel ?? 'Search';
|
|
$navActive = fn (bool $active) => $active ? 'text-indigo-600' : 'text-slate-600';
|
|
@endphp
|
|
<div x-data="{ profileOpen: false }" class="lg:hidden">
|
|
<nav class="fixed inset-x-0 bottom-0 z-40 border-t border-slate-200 bg-white"
|
|
style="padding-bottom: env(safe-area-inset-bottom, 0px)">
|
|
<div class="grid h-16 {{ $gridCols }}">
|
|
<a href="{{ $homeUrl }}"
|
|
class="flex flex-col items-center justify-center gap-1 px-2 py-2 transition hover:text-slate-900 {{ $navActive($homeActive ?? false) }}">
|
|
<svg class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"/></svg>
|
|
<span class="text-[10px] font-medium">Home</span>
|
|
</a>
|
|
|
|
<a href="{{ $searchUrl }}"
|
|
class="flex flex-col items-center justify-center gap-1 px-2 py-2 transition hover:text-slate-900 {{ $navActive($searchActive ?? false) }}">
|
|
<svg class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"/></svg>
|
|
<span class="text-[10px] font-medium">{{ $searchLabel }}</span>
|
|
</a>
|
|
|
|
@if (!empty($centerCompose))
|
|
<div class="flex items-center justify-center">
|
|
<button type="button"
|
|
@click="$dispatch('compose-open')"
|
|
class="flex h-11 w-11 -translate-y-1 items-center justify-center rounded-full bg-indigo-600 text-white shadow-md ring-4 ring-white transition hover:bg-indigo-700"
|
|
aria-label="Compose">
|
|
<svg class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z"/></svg>
|
|
</button>
|
|
</div>
|
|
@endif
|
|
|
|
<a href="{{ $notificationsUrl }}"
|
|
@if ($unreadUrl)
|
|
x-data="{
|
|
unread: 0,
|
|
init() {
|
|
fetch({{ \Illuminate\Support\Js::from($unreadUrl) }}, {
|
|
headers: { Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
|
|
}).then(r => r.json()).then(d => this.unread = d.unread_count || 0).catch(() => {});
|
|
},
|
|
}"
|
|
@endif
|
|
class="relative flex flex-col items-center justify-center gap-1 px-2 py-2 transition hover:text-slate-900 {{ $navActive($notificationsActive ?? false) }}">
|
|
<svg class="h-6 w-6" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9a6 6 0 1 0-12 0v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.08 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0"/></svg>
|
|
@if ($unreadUrl)
|
|
<span x-show="unread > 0" x-cloak x-text="unread > 9 ? '9+' : unread"
|
|
class="absolute right-3 top-1.5 inline-flex min-w-4 items-center justify-center rounded-full bg-rose-500 px-1 py-0.5 text-[9px] font-semibold text-white"></span>
|
|
@endif
|
|
<span class="text-[10px] font-medium">Notifications</span>
|
|
</a>
|
|
|
|
<button type="button"
|
|
@click="profileOpen = true"
|
|
class="flex flex-col items-center justify-center gap-1 px-2 py-2 transition hover:text-slate-900 {{ $navActive($profileActive ?? false) }}"
|
|
:class="profileOpen ? 'text-indigo-600' : ''"
|
|
aria-label="Open profile menu">
|
|
@if ($avatarUrl)
|
|
<img src="{{ $avatarUrl }}" alt="" class="h-7 w-7 rounded-full object-cover ring-1 ring-slate-200">
|
|
@else
|
|
<span class="inline-flex h-7 w-7 items-center justify-center rounded-full bg-slate-900 text-[10px] font-semibold text-white">{{ $initials }}</span>
|
|
@endif
|
|
<span class="text-[10px] font-medium">Profile</span>
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
|
|
{{-- Profile menu bottom sheet (matches desktop avatar dropdown) --}}
|
|
<div x-show="profileOpen" x-cloak class="fixed inset-0 z-50" @keydown.escape.window="profileOpen = false">
|
|
<div x-show="profileOpen" x-transition.opacity.duration.200ms
|
|
@click="profileOpen = false"
|
|
class="absolute inset-0 bg-slate-900/40 backdrop-blur-[1px]"></div>
|
|
|
|
<div x-show="profileOpen"
|
|
x-transition:enter="transition ease-out duration-300"
|
|
x-transition:enter-start="translate-y-full"
|
|
x-transition:enter-end="translate-y-0"
|
|
x-transition:leave="transition ease-in duration-200"
|
|
x-transition:leave-start="translate-y-0"
|
|
x-transition:leave-end="translate-y-full"
|
|
class="absolute inset-x-0 bottom-0 rounded-t-2xl border-t border-slate-200 bg-white shadow-2xl"
|
|
style="padding-bottom: env(safe-area-inset-bottom, 0px)"
|
|
@click.outside="profileOpen = false">
|
|
<div class="flex justify-center pt-3">
|
|
<span class="h-1 w-10 rounded-full bg-slate-200" aria-hidden="true"></span>
|
|
</div>
|
|
|
|
@if ($profileName !== '' || $profileSubtitle !== '')
|
|
<div class="flex items-center gap-3 border-b border-slate-100 px-5 py-4">
|
|
@if ($avatarUrl)
|
|
<img src="{{ $avatarUrl }}" alt="" class="h-12 w-12 rounded-full object-cover ring-1 ring-slate-200">
|
|
@else
|
|
<span class="inline-flex h-12 w-12 items-center justify-center rounded-full bg-slate-900 text-sm font-semibold text-white">{{ $initials }}</span>
|
|
@endif
|
|
<div class="min-w-0">
|
|
@if ($profileName !== '')
|
|
<p class="truncate text-sm font-semibold text-slate-900">{{ $profileName }}</p>
|
|
@endif
|
|
@if ($profileSubtitle !== '')
|
|
<p class="truncate text-xs text-slate-500">{{ $profileSubtitle }}</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="space-y-1 p-2 pb-4">
|
|
@foreach ($profileMenuItems as $item)
|
|
@if (($item['type'] ?? 'link') === 'link')
|
|
<a href="{{ $item['href'] }}"
|
|
@click="profileOpen = false"
|
|
class="block rounded-xl px-4 py-3 text-sm font-medium text-slate-700 transition hover:bg-slate-100">
|
|
{{ $item['label'] }}
|
|
</a>
|
|
@elseif (($item['type'] ?? '') === 'logout')
|
|
<form method="POST" action="{{ $item['action'] }}" class="border-t border-slate-100 pt-2">
|
|
@csrf
|
|
<button type="submit"
|
|
class="w-full rounded-xl px-4 py-3 text-left text-sm font-medium text-rose-600 transition hover:bg-rose-50">
|
|
{{ $item['label'] }}
|
|
</button>
|
|
</form>
|
|
@endif
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|