Skip to main content

Data display

Stat code

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

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

@props([
    'label',
    'value',
    'icon' => null,
    'trend' => null,
    'trendDirection' => 'up',
    'description' => null,
    'size' => 'base',
])

@php
    /*
    | KPI / metric tile.
    |
    | size: sm, base
    | trendDirection: up (green), down (red), neutral (gray)
    |
    | Usage:
    |   <x-ui.stat label="Revenue" value="$48.2k" icon="trend-up" trend="12%" trend-direction="up" />
    |   <x-ui.stat size="sm" label="Customers" value="1,284" icon="users" />
    */
    $trendConfig = [
        'up' => ['color' => 'text-green-600 dark:text-green-400', 'icon' => 'trend-up'],
        'down' => ['color' => 'text-red-600 dark:text-red-400', 'icon' => 'trend-down'],
        'neutral' => ['color' => 'text-gray-500 dark:text-gray-400', 'icon' => 'minus'],
    ][$trendDirection] ?? null;

    $isCompact = $size === 'sm';

    $rootClass = $isCompact
        ? 'min-w-0 rounded-xl border border-gray-200 bg-white p-3 dark:border-gray-800 dark:bg-gray-900'
        : 'min-w-0 rounded-2xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900 sm:p-6';

    $labelClass = $isCompact
        ? 'min-w-0 truncate text-xs font-medium text-gray-500 dark:text-gray-400'
        : 'min-w-0 truncate text-sm font-medium text-gray-500 dark:text-gray-400';

    $iconWrapClass = $isCompact
        ? 'flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-brand-50 text-brand-600 dark:bg-brand-950/60 dark:text-brand-400'
        : 'flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-brand-50 text-brand-600 dark:bg-brand-950/60 dark:text-brand-400 sm:h-9 sm:w-9';

    $valueRowClass = $isCompact
        ? 'mt-1.5 flex min-w-0 flex-wrap items-baseline gap-x-2 gap-y-0.5'
        : 'mt-3 flex min-w-0 flex-wrap items-end gap-x-2 gap-y-1';

    $valueClass = $isCompact
        ? 'min-w-0 text-xl font-semibold tracking-tight text-gray-900 tabular-nums dark:text-white'
        : 'min-w-0 text-2xl font-semibold tracking-tight text-gray-900 tabular-nums dark:text-white sm:text-3xl';

    $trendClass = $isCompact
        ? 'inline-flex shrink-0 items-center gap-0.5 text-xs font-medium'
        : 'inline-flex shrink-0 items-center gap-1 text-xs font-medium sm:text-sm';
@endphp

<div {{ $attributes->merge(['class' => $rootClass]) }}>
    <div class="flex items-start justify-between gap-2">
        <p class="{{ $labelClass }}">{{ $label }}</p>
        @if ($icon)
            <span class="{{ $iconWrapClass }}">
                <x-ui.icon :name="$icon" :size="$isCompact ? 'base' : 'lg'" />
            </span>
        @endif
    </div>

    <div class="{{ $valueRowClass }}">
        <p class="{{ $valueClass }}">{{ $value }}</p>

        @if ($trend && $trendConfig)
            <span class="{{ $trendClass }} {{ $trendConfig['color'] }}">
                <x-ui.icon :name="$trendConfig['icon']" weight="bold" size="sm" />
                {{ $trend }}
            </span>
        @endif

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

    @if ($description && ! $isCompact)
        <p class="mt-1 truncate text-xs text-gray-400 dark:text-gray-500">{{ $description }}</p>
    @endif
</div>