Skip to main content

General

Sparkline code

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

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

@props([
    'label' => null,
    'summary' => null,
    'data' => [],
    'series' => [],
    'type' => 'line',
    'color' => null,
    'fill' => true,
    'dualAxis' => false,
    'width' => '100%',
    'height' => 40,
    'reveal' => false,
])

@php
    /*
    | Compact, axis-less trend line/bar. Perfect inside a stat tile or table cell.
    |
    | type:      line | bar
    | data:      [12, 19, 14, 22, 18, ...] — single series
    | series:    multiple series for dual-axis or grouped bar cards. Each: [
    |                'label' => 'Sessions',
    |                'data'  => [3, 7, 4, 9, 6, 11],
    |                'color' => '#16a34a',  // optional
    |                'axis'  => 'left',       // left | right
    |            ]
    | dualAxis:  show a y-axis on each side (requires series)
    | color:     optional hex; defaults to the brand color
    | fill:      soft area fill under a line (ignored for bars / multi-series)
    | reveal:    defer the draw until the sparkline scrolls into view
    |
    | Usage:
    |   <x-ui.sparkline :data="[3, 7, 4, 9, 6, 11, 8]" />
    |   <x-ui.sparkline type="bar" :series="[
    |       ['label' => 'Avg', 'data' => [12, 18, 9, 22], 'color' => '#99a0a5'],
    |       ['label' => 'Max', 'data' => [18, 26, 14, 32], 'color' => '#f59e0b'],
    |   ]" />
    |   <x-ui.sparkline
    |       dual-axis
    |       :series="[
    |           ['label' => 'Sessions', 'data' => [3, 7, 4, 9, 6, 11], 'axis' => 'left'],
    |           ['label' => 'Revenue', 'data' => [48, 52, 44, 58, 49], 'axis' => 'right', 'color' => '#16a34a'],
    |       ]"
    |       :height="120"
    |   />
    */
    $config = count($series) > 0
        ? [
            'series' => array_values(array_map(fn (array $item) => [
                'label' => $item['label'] ?? '',
                'data' => array_values($item['data'] ?? []),
                'color' => $item['color'] ?? null,
                'axis' => $item['axis'] ?? 'left',
                'fill' => $item['fill'] ?? true,
            ], $series)),
            'dualAxis' => (bool) $dualAxis,
            'type' => $type,
            'reveal' => (bool) $reveal,
        ]
        : [
            'data' => array_values($data),
            'type' => $type,
            'color' => $color,
            'fill' => $type === 'line' ? (bool) $fill : false,
            'reveal' => (bool) $reveal,
        ];

    $pointCount = count($series) > 0
        ? max(array_map(fn (array $item) => count($item['data'] ?? []), $series) ?: [0])
        : count($data);

    $seriesLabels = collect($series)
        ->pluck('label')
        ->filter()
        ->values()
        ->all();

    $accessibleLabel = $summary;

    if (! $accessibleLabel) {
        $accessibleLabel = trim(implode(' ', array_filter([
            $label ? $label.'.' : ($seriesLabels !== [] ? implode(', ', $seriesLabels).'.' : null),
            Str::headline($type).' sparkline.',
            $pointCount > 0 ? $pointCount.' data point'.($pointCount === 1 ? '' : 's').'.' : null,
        ])));

        if ($accessibleLabel === '') {
            $accessibleLabel = 'Sparkline chart';
        }
    }
@endphp

<div
    x-data="uiSparkline(@js($config))"
    wire:ignore
    {{ $attributes->merge(['class' => 'relative']) }}
    style="width: {{ is_numeric($width) ? $width.'px' : $width }}; height: {{ is_numeric($height) ? $height.'px' : $height }}"
>
    <canvas x-ref="canvas" role="img" aria-label="{{ $accessibleLabel }}"></canvas>
</div>