Skip to content

Dashboard widgets · Open source

Stat Cards

Adds progress bars, icon tiles, card and text colours, trends, badges and bar charts to the stats overview widget you already have, by changing one import.

Filament 4 and 5 Laravel 12 and 13 PHP 8.2+ v1.0.1 Free · MIT
Stat Cards: Adds progress bars, icon tiles, card and text colours, trends, badges and bar charts to the stats overview widget you already have, by changing one import.

What it solves

Filament's stat card shows a label, a value, a description and a line sparkline.

A target, a percentage change against last month or a coloured card means writing your own widget view.

This package's Stat is a subclass of Filament's stats overview Stat, so it goes in the same getStats() array and core's methods still work. It adds a progress bar with an optional label, the icon in a coloured tile at the start or end of the card, colours for the card, icon, label, value and description, trend(current, previous) that writes "12.4% increase" with an arrow in green or red, a badge next to the label and a bar chart drawn as plain SVG. The styles are plain CSS, so there is no theme or build step. It also accepts the stat method names of eightynine/filament-advanced-widgets. An independent plugin, not made or endorsed by Filament.

  • A subclass of Filament's stats overview Stat: swap one use line, keep your widget, and mix core and enhanced stats in the same widget
  • Progress bars filled to value / max, clamped to 0-100%, with the percentage or your own text underneath
  • Icon tiles: the icon in a coloured square, before the label or at the far end of the card
  • Colours for the card background, the icon, the label, the value and the description, from any Filament colour name or palette array
  • trend($current, $previous) writes "12.4% increase" or "22.5% decrease" with an arrow, green when the change is good and red when it is bad, with higherIsBetter: false for refunds or churn
  • A badge after the label, such as "This month" or "Live"
  • chartType('bar') draws the chart data as columns in plain SVG, with no JavaScript
  • Plain CSS, linked when published by filament:assets and printed inline otherwise; no theme, Tailwind config or npm build
  • Dark mode uses solid colours on neutral surfaces, never a translucent colour wash
Two rows of stat cards in a light Filament panel. Sales: Revenue $48,200 with a This month badge, an icon tile at the end, 12.4% increase in green and a progress bar labelled 80% of the $60k target; Refunds 31 with 22.5% decrease in green and a red bar chart; New signups 1,204 on a light blue card with a blue value and a line sparkline. Operations: Pending orders 86 on a yellow card with a Needs attention badge and a 72% progress bar; Uptime 99.98% in green with 0.07% increase; Storage used 612 GB with a blue progress bar labelled 612 of 1,024 GB; and a core Filament stat, unchanged, in the same widget.
Two rows of stat cards in a light Filament panel. Sales: Revenue $48,200 with a This month badge, an icon tile at the end, 12.4% increase in green and a progress bar labelled 80% of the $60k target; Refunds 31 with 22.5% decrease in green and a red bar chart; New signups 1,204 on a light blue card with a blue value and a line sparkline. Operations: Pending orders 86 on a yellow card with a Needs attention badge and a 72% progress bar; Uptime 99.98% in green with 0.07% increase; Storage used 612 GB with a blue progress bar labelled 612 of 1,024 GB; and a core Filament stat, unchanged, in the same widget.

Install

Requires PHP 8.2+, Filament 4 and 5, and Laravel 12 and 13.

composer require amjadiqbal/filament-stat-cards

Usage

use AmjadIqbal\FilamentStatCards\Stat;

protected function getStats(): array
{
    return [
        Stat::make('Revenue', '$48,200')
            ->icon('heroicon-o-banknotes')
            ->iconBackgroundColor('primary')
            ->trend(48200, 42880)
            ->progress(48200, 60000)
            ->progressLabel('80% of the $60k target')
            ->badge('This month', 'primary'),
    ];
}

Setup

There is no plugin to register on the panel, no new widget class and no theme or npm build: the service provider is discovered automatically and the styles are plain CSS. If you run php artisan filament:assets, the panel links the published stylesheet; if not, the same CSS (about 5 KB) is printed inline in the panel's head. Core Stat objects and these ones can sit in the same widget.

  1. 1 composer require amjadiqbal/filament-stat-cards
  2. 2 In a stats overview widget, replace use Filament\Widgets\StatsOverviewWidget\Stat; with use AmjadIqbal\FilamentStatCards\Stat;
  3. 3 Optional: php artisan vendor:publish --tag=filament-stat-cards-translations to change the trend and progress texts.

Progress bars

progress($value, $max = 100) shows a bar under the description, filled to $value / $max and clamped to 0-100%. The bar uses progressBarColor() (or its alias progressColor()), else the stat's color(), else primary. progressLabel(true) prints the percentage under the bar, rounded to a whole number; a string prints that text instead.

Stat::make('Storage used', '612 GB')
    ->progress(612, 1024)
    ->progressBarColor('info')
    ->progressLabel('612 of 1,024 GB');

Icon tiles

iconBackgroundColor() puts the stat's icon in a coloured square. The icon takes the tile's colour unless iconColor() sets another; iconColor() on its own colours a plain icon. iconPosition('start'), the default, puts the icon before the label as core does; iconPosition('end') puts it at the far end of the top row. before and after, and Filament's IconPosition enum, also work; any other value throws an exception.

Stat::make('Revenue', '$48,200')
    ->icon('heroicon-o-banknotes')
    ->iconBackgroundColor('primary')
    ->iconPosition('end');

Colours

backgroundColor() tints the card. labelColor() and valueColor() colour the text, and textColor($label, $value, $description) sets all three at once, skipping any you pass as null. The label and value colours also take a closure; the description colour is core's, a name or a palette array. Core's descriptionColor() and chartColor() work as before.

  • A colour is any Filament colour name (primary, success, warning, danger, info, gray, or one you registered) or a palette array such as Color::Sky or Color::hex('#0ea5e9').
  • Named colours point at the panel's own colour variables, so the cards follow your theme.
Stat::make('New signups', '1,204')
    ->backgroundColor('info')
    ->valueColor('info')
    ->description('Since Monday');

Trends

trend($current, $previous, $higherIsBetter = true, $precision = 1) writes the description, the arrow and the colour from two numbers. The change is (current - previous) / previous, as a percentage of the previous value's size, rounded to $precision decimals, with trailing zeros dropped: 48200 against 42880 gives "12.4% increase", and an exact 12.0 shows as "12%". A rise gets an up arrow and a fall a down arrow. The text is green when the change is good and red when it is bad; higherIsBetter: false flips that for numbers that should go down.

  • Previous is 0: no percentage can be worked out, so the description is "New this period" (or "No change" if current is 0 too), with no arrow, in the stat's color() if it has one.
  • A change that rounds to zero reads "No change", with no arrow.
  • Your own description(), descriptionIcon() or descriptionColor() wins over the one trend() would write.
  • The texts come from the package's translation file, which you can publish.
Stat::make('Refunds', '31')
    ->trend(31, 40, higherIsBetter: false); // "22.5% decrease", green

Badges

badge($text, $color = null) shows a small badge after the label, such as "Live", "Beta" or "This month". Without a colour it uses the stat's color(), else gray.

Stat::make('Pending orders', '86')
    ->badge('Needs attention', 'warning');

Bar charts

chartType('bar') draws the chart() data as columns instead of core's line sparkline. The bars are plain SVG with no JavaScript, scaled to the largest value, and use chartColor(), else the stat's color(), else gray. chartType('line'), the default, leaves core's sparkline as it is. Any other type throws an exception.

Stat::make('Refunds', '31')
    ->chart([4, 9, 6, 12, 8, 14])
    ->chartType('bar')
    ->chartColor('danger');

Coming from eightynine/filament-advanced-widgets

eightynine/filament-advanced-widgets (MIT, by Eighty Nine) popularised these cards for Filament 3 and 4. Stat Cards is a separate, independent implementation for Filament 4 and 5 with no shared code. It accepts the same stat method names: backgroundColor, progress, progressBarColor, iconBackgroundColor, iconColor, iconPosition, labelColor, valueColor, textColor, descriptionIcon, descriptionColor and chartColor. It is not affiliated with or endorsed by its author.

  1. 1 Replace use EightyNine\FilamentAdvancedWidget\AdvancedStatsOverviewWidget\Stat; with use AmjadIqbal\FilamentStatCards\Stat;
  2. 2 Replace use EightyNine\FilamentAdvancedWidget\AdvancedStatsOverviewWidget as BaseWidget; with use Filament\Widgets\StatsOverviewWidget as BaseWidget;
  3. 3 Check the result in the browser: the cards look different.
  • The icon defaults to the start of the card, as in core. Add iconPosition('end') where you want it at the end.
  • progress() takes a number (out of 100 unless you pass a maximum), not a word: replace 'full' with 100 and 'empty' with 0.
  • chartColor() takes one colour, as in core; a second argument is ignored, and borderColor() and graphColor() do not exist here.
  • Only the stats widget is covered, not eightynine's chart or table widgets.

Dark mode

In dark mode, colours appear only as solid text, lines, bars and borders on Filament's neutral surfaces. The package never puts a translucent colour wash on a dark card, where warm colours turn muddy.

  • A card with backgroundColor() keeps the neutral dark surface and gets a solid coloured line along its top.
  • Icon tiles and badges become coloured outlines on a transparent background.
  • Core's sparkline is drawn as a line without its area fill, in these cards only.

Hire me

Need this built into your app, or something custom?

I wrote Stat Cards. I can wire it into your Filament panel, extend it for your case, or build the feature around it. Tell me what you need and you'll get a plan and a quote, free.

Support

Found a bug or want a feature? Open an issue on GitHub. For help adding it to your own project, use the quote form above.

Need something built?

Free quote in 60 seconds