Skip to main content

Data display

Skeleton code

Copy the implementation or inspect every file that belongs to this component unit.

resources/views/components/ui/skeleton.blade.php

@props([
    'variant' => 'line',
    'preset' => null,
    'lines' => 1,
    'width' => null,
    'height' => null,
    'rounded' => null,
])

@php
    /*
    | Loading placeholder with a subtle pulse. Pair with spinner / empty-state
    | while content is being fetched.
    |
    | variant: line, circle, rect
    | preset:  text, card, avatar, table — composite layouts that ignore variant
    |
    | Usage:
    |   <x-ui.skeleton :lines="3" />
    |   <x-ui.skeleton variant="circle" width="3rem" height="3rem" />
    |   <x-ui.skeleton variant="rect" height="8rem" rounded="rounded-2xl" />
    |   <x-ui.skeleton preset="card" />
    |   <x-ui.skeleton preset="table" />
    */
    $base = 'animate-pulse bg-gray-200 dark:bg-gray-800';

    $style = collect([
        $width ? "width: {$width}" : null,
        $height ? "height: {$height}" : null,
    ])->filter()->implode('; ');
@endphp

@if ($preset === 'card')
    <div {{ $attributes->merge(['class' => 'space-y-4']) }}>
        <span class="block h-32 rounded-xl {{ $base }}"></span>
        <div class="space-y-2.5">
            <span class="block h-3 w-2/5 rounded {{ $base }}"></span>
            <span class="block h-3 w-full rounded {{ $base }}"></span>
            <span class="block h-3 w-3/5 rounded {{ $base }}"></span>
        </div>
    </div>
@elseif ($preset === 'avatar')
    <div {{ $attributes->merge(['class' => 'flex items-center gap-4']) }}>
        <span class="block h-10 w-10 shrink-0 rounded-full {{ $base }}"></span>
        <div class="flex-1 space-y-2.5">
            <span class="block h-3 w-2/5 rounded {{ $base }}"></span>
            <span class="block h-3 w-3/5 rounded {{ $base }}"></span>
        </div>
    </div>
@elseif ($preset === 'table')
    <div {{ $attributes->merge(['class' => 'space-y-3']) }}>
        <span class="block h-8 rounded-lg {{ $base }}"></span>
        @for ($i = 0; $i < (int) max(1, $lines ?: 4); $i++)
            <span class="block h-4 rounded {{ $base }} {{ $i % 2 === 0 ? 'w-full' : 'w-11/12' }}"></span>
        @endfor
    </div>
@elseif ($preset === 'text')
    <div {{ $attributes->merge(['class' => 'space-y-2.5']) }}>
        @for ($i = 0; $i < (int) max(1, $lines ?: 3); $i++)
            <span class="block h-3 rounded {{ $base }} {{ $i === (int) max(1, $lines ?: 3) - 1 ? 'w-3/5' : 'w-full' }}"></span>
        @endfor
    </div>
@elseif ($variant === 'circle')
    <span {{ $attributes->merge(['class' => "block shrink-0 rounded-full {$base}"]) }}
          style="{{ $style ?: 'width: 2.5rem; height: 2.5rem' }}"></span>
@elseif ($variant === 'rect')
    <span {{ $attributes->merge(['class' => trim($base.' block '.($rounded ?? 'rounded-xl'))]) }}
          style="{{ $style ?: 'height: 6rem' }}"></span>
@else
    <div {{ $attributes->merge(['class' => 'space-y-2.5']) }}>
        @for ($i = 0; $i < (int) $lines; $i++)
            <span class="block h-3 {{ $rounded ?? 'rounded' }} {{ $base }} {{ $lines > 1 && $i === $lines - 1 ? 'w-3/5' : 'w-full' }}"
                  @if ($style && $lines == 1) style="{{ $style }}" @endif></span>
        @endfor
    </div>
@endif