Skip to main content

Layout primitives

Stat Card code

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

resources/views/components/ui/stat-card.blade.php

@props([
    'title',
    'status' => null,
    'statusVariant' => 'green',
    'meta' => null,
    'description' => null,
    'stats' => [],
    'hover' => false,
    'href' => null,
])

@php
    /*
    | Card with a status indicator and inline headline stats.
    | Useful for dashboards, service health panels and resource summaries.
    |
    | statusVariant: gray, brand, green, red, amber, blue, outline
    | stats: array of ['label' => 'Visitors', 'value' => '18.4k']
    |
    | Usage:
    |   <x-ui.stat-card
    |       title="Marketing site"
    |       status="Live"
    |       status-variant="green"
    |       meta="Updated 2 hours ago"
    |       :stats="[
    |           ['label' => 'Visitors', 'value' => '18.4k'],
    |           ['label' => 'Uptime', 'value' => '99.9%'],
    |       ]"
    |       hover
    |       href="/sites/marketing"
    |   />
    */
    $statCount = count($stats);
    $statColumns = match (true) {
        $statCount <= 1 => 'grid-cols-1',
        $statCount === 2 => 'grid-cols-2',
        $statCount === 3 => 'grid-cols-2 sm:grid-cols-3',
        default => 'grid-cols-2 sm:grid-cols-4',
    };

    $statusStyles = [
        'gray' => 'text-gray-500 dark:text-gray-400',
        'brand' => 'text-brand-600 dark:text-brand-400',
        'green' => 'text-green-600 dark:text-green-400',
        'red' => 'text-red-600 dark:text-red-400',
        'amber' => 'text-amber-600 dark:text-amber-400',
        'blue' => 'text-accent-600 dark:text-accent-400',
        'outline' => 'text-gray-600 dark:text-gray-300',
    ];

    $statusIcons = [
        'gray' => 'circle',
        'brand' => 'sparkle',
        'green' => 'check-circle',
        'red' => 'warning-octagon',
        'amber' => 'warning',
        'blue' => 'info',
        'outline' => 'circle',
    ];
@endphp

<x-ui.card :hover="$hover" :href="$href" {{ $attributes }}>
    <div class="flex items-start justify-between gap-3">
        <div class="min-w-0">
            <h3 class="truncate text-sm font-semibold text-gray-900 dark:text-white">{{ $title }}</h3>

            @if ($meta)
                <p class="text-xs text-gray-500 dark:text-gray-400">{{ $meta }}</p>
            @endif
        </div>

        @if ($status)
            <span @class([
                'inline-flex shrink-0 items-center gap-1 text-xs font-medium',
                $statusStyles[$statusVariant] ?? $statusStyles['gray'],
            ])>
                <x-ui.icon :name="$statusIcons[$statusVariant] ?? 'warning-circle'" weight="fill" size="sm" />
                {{ $status }}
            </span>
        @endif
    </div>

    @if ($description)
        <p class="mt-4 text-sm text-gray-600 dark:text-gray-400">{{ $description }}</p>
    @endif

    @if ($statCount > 0)
        <div @class([
            'grid min-w-0 gap-4',
            $statColumns,
            'mt-5 border-t border-gray-100 pt-5 dark:border-gray-800' => filled($description),
            'mt-5' => blank($description),
        ])>
            @foreach ($stats as $stat)
                <div class="min-w-0">
                    <p class="text-xs font-medium text-gray-500 dark:text-gray-400">{{ $stat['label'] }}</p>
                    <p class="mt-0.5 text-lg font-semibold tabular-nums tracking-tight text-gray-900 dark:text-white">{{ $stat['value'] }}</p>
                </div>
            @endforeach
        </div>
    @endif
</x-ui.card>