338c190ae8
Enhance the navigation with a modern floating glass design, new Browse and Community dropdown links, and improved theme/blur toggles that now handle multiple instances. Update dropdown components with rounded styling and support for wider widths, refine nav-link active states, and add navigation feature tests.
171 lines
12 KiB
PHP
171 lines
12 KiB
PHP
<div class="flex items-center relative">
|
|
<form method="POST" action="{{ route('hentai.searchredirect') }}" class="w-full">
|
|
@csrf
|
|
<div class="relative group">
|
|
<label for="live-search" class="sr-only">Search</label>
|
|
<div class="relative w-full sm:min-w-[200px] md:min-w-[200px] lg:min-w-[240px] xl:min-w-[300px]">
|
|
{{-- Search Icon --}}
|
|
<div class="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
|
|
<svg class="w-4 h-4 text-gray-400 dark:text-gray-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
|
|
</svg>
|
|
</div>
|
|
|
|
{{-- Search Input --}}
|
|
<input
|
|
wire:model.live.debounce.600ms="navSearch"
|
|
type="search"
|
|
id="live-search"
|
|
name="live-search"
|
|
class="block w-full pl-10 pr-24 py-3 text-sm rounded-2xl border border-gray-200 bg-white/80 dark:bg-neutral-900/50 dark:border-neutral-700 placeholder-gray-400 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-rose-600 focus:border-rose-700 transition"
|
|
placeholder="@if(request()->path() !== 'search'){{ __('search.search-hentai') }}@endif"
|
|
required
|
|
@if(request()->path() == 'search') disabled @endif
|
|
aria-autocomplete="list"
|
|
aria-label="Search"
|
|
>
|
|
|
|
{{-- Submit button to redirect to advanced search --}}
|
|
<button
|
|
type="submit"
|
|
class="absolute right-1 top-1/2 -translate-y-1/2 px-4 py-2 text-sm font-medium rounded-xl bg-rose-700 text-white hover:bg-rose-800 focus:outline-none focus:ring-2 focus:ring-rose-300 disabled:bg-gray-300 disabled:hover:bg-gray-300 disabled:dark:bg-gray-500 disabled:dark:hover:bg-gray-500"
|
|
@if(request()->path() == 'search') disabled @endif
|
|
>{{ __('search.search') }}</button>
|
|
</div>
|
|
|
|
@if((! $hide) && request()->path() != 'search' && request()->path() != 'download-search')
|
|
<div
|
|
class="pointer-events-auto absolute left-0 right-0 mt-3 z-50 flex justify-center"
|
|
aria-live="polite"
|
|
>
|
|
<div
|
|
class="w-full max-h-[70vh] overflow-auto rounded-2xl bg-white dark:bg-neutral-900 border border-gray-200 dark:border-neutral-700 shadow-xl transition-all transform hidden group-focus-within:block group-focus-within:translate-y-0">
|
|
{{-- Header --}}
|
|
<div class="flex items-center justify-between px-5 py-3 border-b border-gray-100 dark:border-neutral-800">
|
|
<div class="text-sm text-gray-700 dark:text-gray-200 font-medium">
|
|
@if($episodes->count())
|
|
{{ __('Search result for ') }}<span class="text-rose-600 dark:text-rose-400 font-semibold">"{{ $query ?: $navSearch }}"</span>
|
|
@else
|
|
{{ __('No results') }}
|
|
@endif
|
|
</div>
|
|
|
|
{{-- Loading indicator using Livewire --}}
|
|
<div class="flex items-center gap-2">
|
|
<div wire:loading.class.remove="hidden" class="hidden">
|
|
<svg class="w-5 h-5 animate-spin text-rose-600" viewBox="0 0 24 24" fill="none">
|
|
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-opacity="0.2" stroke-width="4"></circle>
|
|
<path d="M22 12a10 10 0 0 1-10 10" stroke="currentColor" stroke-width="4" stroke-linecap="round"></path>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Results List --}}
|
|
<div>
|
|
@if($episodes->count())
|
|
<ul class="divide-y divide-gray-100 dark:divide-neutral-800" role="listbox">
|
|
@foreach($episodes as $episode)
|
|
<li role="option" aria-selected="false">
|
|
<a href="{{ route('hentai.index', ['title' => $episode->slug ]) }}"
|
|
class="flex items-center gap-4 px-5 py-2 group/row hover:bg-rose-50/60 dark:hover:bg-rose-950/30 transition-colors duration-150"
|
|
>
|
|
{{-- Left: Cover Image --}}
|
|
<div class="flex-shrink-0 relative">
|
|
<div class="w-16 h-[6rem] rounded-lg overflow-hidden ring-1 ring-gray-200/80 dark:ring-neutral-700/80 shadow-sm group-hover/row:ring-rose-300 dark:group-hover/row:ring-rose-700 group-hover/row:shadow-md transition-all duration-200">
|
|
<img
|
|
alt="{{ $episode->title }} - {{ $episode->episode }}"
|
|
loading="lazy"
|
|
class="object-cover w-full h-full group-hover/row:scale-105 transition-transform duration-300"
|
|
src="{{ $episode->cover_url }}"
|
|
>
|
|
</div>
|
|
<span class="absolute -top-1.5 -right-1.5 bg-rose-600 text-white text-[0.6rem] font-bold leading-none px-1.5 py-0.5 rounded-md shadow-sm">
|
|
E{{ $episode->episode }}
|
|
</span>
|
|
</div>
|
|
|
|
{{-- Center: Title, Publisher, Tags --}}
|
|
<div class="flex-1 min-w-0">
|
|
{{-- Row 1: Title --}}
|
|
<h3 class="text-sm font-semibold text-gray-900 dark:text-white truncate group-hover/row:text-rose-700 dark:group-hover/row:text-rose-400 transition-colors duration-150">
|
|
{{ $episode->title }}
|
|
</h3>
|
|
|
|
{{-- Row 2: Publisher --}}
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1 truncate">
|
|
<i class="fa-regular fa-building mr-1 text-[0.65rem] opacity-70"></i>
|
|
{{ $episode->studio?->name ?? __('Unknown') }}
|
|
</p>
|
|
|
|
{{-- Row 3: Tags --}}
|
|
<div class="mt-1.5 flex items-center gap-1 flex-wrap">
|
|
@php
|
|
$tags = $episode->tagNames();
|
|
$visibleTags = array_slice($tags, 0, 3);
|
|
$remainingCount = count($tags) - 3;
|
|
@endphp
|
|
@foreach($visibleTags as $tag)
|
|
<span class="inline-flex items-center px-1.5 py-0 text-[0.6rem] font-medium leading-tight rounded-md bg-rose-100/80 text-rose-700 dark:bg-rose-900/50 dark:text-rose-300 ring-1 ring-inset ring-rose-200/60 dark:ring-rose-800/60">
|
|
{{ $tag }}
|
|
</span>
|
|
@endforeach
|
|
@if($remainingCount > 0)
|
|
<span class="inline-flex items-center px-1.5 py-0 text-[0.6rem] font-medium leading-tight rounded-md bg-gray-100 text-gray-500 dark:bg-neutral-800 dark:text-gray-400">
|
|
+{{ $remainingCount }}
|
|
</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Right: View Count, Like Count --}}
|
|
<div class="flex-shrink-0 flex flex-col items-end gap-1.5">
|
|
<div class="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400 tabular-nums" title="{{ __('Views') }}">
|
|
<i class="fa-regular fa-eye text-[0.65rem] opacity-70"></i>
|
|
<span class="font-medium text-gray-700 dark:text-gray-300">{{ $episode->viewCountFormatted() }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400 tabular-nums" title="{{ __('Likes') }}">
|
|
<i class="fa-regular fa-heart text-[0.65rem] opacity-70 text-rose-500 dark:text-rose-400"></i>
|
|
<span class="font-medium text-gray-700 dark:text-gray-300">{{ number_format($episode->likeCount()) }}</span>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</li>
|
|
@endforeach
|
|
|
|
{{-- Advanced Search footer --}}
|
|
<li>
|
|
<a href="{{ route('hentai.search', ['search' => $query]) }}"
|
|
class="block px-5 py-3.5 text-center group/advanced hover:bg-rose-50/60 dark:hover:bg-rose-950/30 transition-colors duration-150"
|
|
>
|
|
<div class="flex items-center justify-center gap-2">
|
|
<span class="text-sm font-semibold text-gray-700 dark:text-gray-200 group-hover/advanced:text-rose-700 dark:group-hover/advanced:text-rose-400 transition-colors">
|
|
{{ __('Advanced Search') }}
|
|
</span>
|
|
<span class="text-xs text-gray-400 dark:text-gray-500">{{ __('View all results') }}</span>
|
|
<svg class="w-4 h-4 text-gray-400 group-hover/advanced:text-rose-600 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
</svg>
|
|
</div>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
@else
|
|
{{-- Empty state --}}
|
|
<div class="py-12 text-center text-sm text-gray-600 dark:text-gray-300">
|
|
<div class="mb-3">{{ __('No results found for') }} <span class="font-semibold text-rose-600">"{{ $query ?: $navSearch }}"</span></div>
|
|
<a href="{{ route('hentai.search', ['search' => $navSearch ?: $query]) }}" class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-rose-700 text-white text-sm font-medium hover:bg-rose-800 transition shadow-sm hover:shadow-md">
|
|
<span>{{ __('Try advanced search') }}</span>
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</form>
|
|
</div> |