Skip to main content

Layout primitives

Metrics Card code

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

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

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

@php
    /*
    | Compact vertical metrics card with key/value rows and optional progress bars.
    | Useful for resource usage, quotas, health checks and host summaries.
    |
    | statusVariant: gray, brand, green, red, amber, blue
    | items: array of [
    |     'label' => 'CPU',
    |     'value' => '38%',
    |     'progress' => 38,          // optional, 0–100
    |     'variant' => 'brand',      // optional progress + value color
    |     'valueVariant' => 'red',   // optional value color override
    | ]
    |
    | refreshable: show a refresh icon button in the header
    |
    | Usage:
    |   <x-ui.metrics-card
    |       title="web-01.production"
    |       status="Healthy"
    |       status-variant="green"
    |       meta="Checked 30s ago"
    |       :items="[
    |           ['label' => 'CPU', 'value' => '38%', 'progress' => 38],
    |           ['label' => 'Memory', 'value' => '4.1 / 8 GiB', 'progress' => 51],
    |           ['label' => 'Connections', 'value' => '847'],
    |       ]"
    |   />
    */
    $statusStyles = [
        'gray' => 'text-gray-600 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',
    ];

    $valueStyles = $statusStyles;
@endphp

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

            @if ($refreshable)
                <x-ui.icon-button icon="arrows-clockwise" label="Refresh" size="sm" class="shrink-0" />
            @endif
        </div>

        @if ($meta || $status)
            <div class="flex items-center justify-between gap-3">
                @if ($meta)
                    <p class="min-w-0 truncate text-xs text-gray-500 dark:text-gray-400">{{ $meta }}</p>
                @endif

                @if ($status)
                    <span @class([
                        'shrink-0 text-xs font-medium',
                        ! $meta ? 'ml-auto' : '',
                        $statusStyles[$statusVariant] ?? $statusStyles['gray'],
                    ])>
                        {{ $status }}
                    </span>
                @endif
            </div>
        @endif
    </div>

    @if (count($items) > 0)
        <dl class="mt-4 min-w-0 space-y-3 border-t border-gray-100 pt-4 dark:border-gray-800">
            @foreach ($items as $item)
                @php
                    $valueVariant = $item['valueVariant'] ?? ($item['variant'] ?? null);
                @endphp
                <div>
                    <div class="flex items-baseline justify-between gap-3">
                        <dt class="text-xs text-gray-500 dark:text-gray-400">{{ $item['label'] }}</dt>
                        <dd @class([
                            'shrink-0 text-xs font-medium tabular-nums',
                            filled($valueVariant)
                                ? ($valueStyles[$valueVariant] ?? 'text-gray-900 dark:text-white')
                                : 'text-gray-900 dark:text-white',
                        ])>{{ $item['value'] }}</dd>
                    </div>

                    @if (isset($item['progress']))
                        <x-ui.progress
                            :value="$item['progress']"
                            :variant="$item['variant'] ?? 'brand'"
                            size="sm"
                            class="mt-1.5"
                        />
                    @endif
                </div>
            @endforeach
        </dl>
    @endif

    {{ $slot }}
</x-ui.card>