Feedback & status
Page Loader code
Copy the implementation or inspect every file that belongs to this component unit.
resources/views/components/ui/page-loader.blade.php
@props([
'name' => 'page',
'show' => false,
'fixed' => true,
'variant' => 'spinner',
'title' => null,
'message' => null,
'progress' => null,
'backdrop' => true,
'blur' => true,
])
@php
/*
| Full-page / overlay loading state. Covers the viewport (fixed) or its
| nearest positioned ancestor (fixed="false", parent must be relative) with a
| backdrop, a loading indicator and optional title, message and determinate
| progress. For small inline cases use <x-ui.spinner> instead.
|
| Toggle it by dispatching window events with the matching name:
| $dispatch('show-loader', 'page') / $dispatch('hide-loader', 'page')
|
| variant: spinner, dots, bars
|
| Usage:
| <x-ui.page-loader title="Loading workspace" message="Fetching your data..." />
| <x-ui.page-loader :fixed="false" variant="dots" /> {{-- container overlay --}}
| <x-ui.page-loader name="save" :show="true" :progress="60" title="Uploading" />
*/
$position = $fixed ? 'fixed' : 'absolute';
$surface = $backdrop
? 'bg-white/80 dark:bg-gray-950/80'.($blur ? ' backdrop-blur-sm' : '')
: '';
@endphp
<div
x-data="{
show: @js((bool) $show),
fixed: @js((bool) $fixed),
}"
x-on:show-loader.window="$event.detail === @js($name) ? (show = true) : null"
x-on:hide-loader.window="$event.detail === @js($name) ? (show = false) : null"
x-effect="fixed ? document.body.classList.toggle('overflow-hidden', show) : null"
x-show="show"
x-cloak
x-transition:enter="ease-out duration-200" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-150" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"
{{ $attributes->merge(['class' => "{$position} inset-0 z-50 flex items-center justify-center {$surface}"]) }}
role="status"
aria-live="polite"
:aria-busy="show.toString()"
>
<div class="flex flex-col items-center gap-4 px-6 text-center">
{{-- Indicator --}}
@if ($variant === 'dots')
<span class="flex items-center gap-2" aria-hidden="true">
@foreach ([0, 150, 300] as $delay)
<span class="h-3 w-3 animate-bounce rounded-full bg-brand-500" style="animation-delay: {{ $delay }}ms"></span>
@endforeach
</span>
@elseif ($variant === 'bars')
<span class="flex items-end gap-1.5" aria-hidden="true">
@foreach ([0, 120, 240, 360, 480] as $delay)
<span class="h-8 w-1.5 animate-pulse rounded-full bg-brand-500" style="animation-delay: {{ $delay }}ms"></span>
@endforeach
</span>
@else
<x-ui.spinner size="xl" class="text-brand-500 dark:text-brand-400" :label="$title ?? 'Loading'" />
@endif
{{-- Text --}}
@if ($title)
<p class="text-base font-semibold text-gray-900 dark:text-white">{{ $title }}</p>
@endif
@if ($message)
<p class="max-w-xs text-sm text-gray-500 dark:text-gray-400">{{ $message }}</p>
@endif
{{-- Determinate progress --}}
@if ($progress !== null)
<div class="w-56 max-w-full">
<x-ui.progress :value="$progress" size="sm" show-value />
</div>
@endif
{{-- Extra content --}}
@if (trim($slot) !== '')
<div class="text-sm text-gray-500 dark:text-gray-400">{{ $slot }}</div>
@endif
</div>
</div>