Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Count Up Laravel Package

xplodman/filament-count-up

xplodman/filament-count-up is a Laravel Filament package that adds smooth animated count-up effects to numeric stats, KPI cards, and dashboard widgets. Built for quick setup and flexible styling, it makes admin panels more engaging with minimal configuration. Ideal for dashboards and reporting views...

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and register

    composer require xplodman/filament-count-up
    php artisan filament:assets   # Filament v3 asset pipeline; v4 may not need it
    

    There is no service provider to register manually in a standard Laravel 11+ app — Filament packages auto-discover. Confirm the package's composer.json lists a Filament version constraint compatible with yours before installing; a 9-star package is unlikely to carry a wide support matrix.

  2. Read the README's first example, then the source

    • The README is one page; the whole package is a thin wrapper around countUp.js, so the fluent API will mirror countUp.js options (duration, decimals, separator, prefix, suffix, easing).
    • Look at src/ for the two entry points (a stat widget/stat class and a table column class), then resources/views/ and resources/js/ to see how the Alpine component is bootstrapped. That view is your escape hatch.
    • Check the composer.json namespace (likely Xplodman\FilamentCountUp\...) — the README examples are authoritative; don't guess class paths.
  3. First use case: a KPI card on an existing dashboard Take one numeric stat you already render and swap the class:

    use Xplodman\FilamentCountUp\Widgets\CountUpStat; // verify exact FQCN
    
    protected function getStats(): array
    {
        return [
            CountUpStat::make('Monthly revenue', $this->monthlyRevenue)
                ->prefix('$')
                ->decimals(0)
                ->duration(1200),
        ];
    }
    

    Do this on a single stat before rolling it across a dashboard — it confirms assets load and the animation fires.

Implementation Patterns

  • Stat widgets are the primary fit. Use count-up on values a user lands on and reads once: revenue, MRR, open tickets, conversion rate. It is decoration for the first paint, not for every re-render.
  • Table columns are the secondary fit, and the riskier one. A CountUpColumn re-animates on pagination, sorting, filtering, and search because Filament re-renders rows. Good for a small "top 10 accounts by spend" table; bad for a 50-row paginated ledger.
  • Keep formatting server-side where it matters. Let the animated element do the transition, but ensure the settled text equals what Filament would otherwise print. If you already use ->money('USD') or ->numeric(decimalPlaces: 2), match decimals and separators in the count-up config or you get a visible "snap" at the end of the animation.
  • Feed it floats/ints, not strings. Eloquent decimal casts return strings; wrap in (float) or cast in the model. A string like "1234.56" will typically animate to 0 or throw in the JS layer with no PHP error.
  • Combine with description() and descriptionIcon() on the stat — the animation composes fine with Filament's standard stat chrome, and the description is where the non-animated delta belongs.
  • Polling widgets: decide deliberately. Either keep polling and accept a re-animation every interval (visually noisy but signals "this updated"), or set the polling interval to a longer window so re-animation is a rare event.
  • Pair with a chart for trend, count-up for the headline. The animation makes the hero number feel alive; the chart carries the detail. Don't animate both.

Gotchas and Tips

  • Assets are the #1 failure mode. If numbers render statically with no animation, open devtools: check the countUp.js script is present in the network tab, then check for a console error. Re-run php artisan filament:assets and php artisan view:clear. In Filament v4 the asset registration path changed, so an older package version may silently no-op.
  • Livewire morphing can kill the animation. On a poll or filter, Livewire patches the DOM rather than re-mounting Alpine, so the component may not re-initialise. If re-animation is required, add a wire:key that changes with the value (e.g. wire:key="revenue-{{ $value }}") or wrap in wire:ignore if you're driving it yourself.
  • Accessibility regression. Count-up spans typically mutate text rapidly, which screen readers may announce as churn. The settled value should be the source of truth. If the package's view doesn't already provide a static accessible value, publish and override the view to add a visually hidden real number and aria-hidden on the animated span. Also respect prefers-reduced-motion — check whether the package does; if not, gate the duration to 0 in CSS or JS.
  • No-JS / SSR fallback. Confirm the server-rendered markup contains the final value, not 0, so a slow script load or a failed asset doesn't show a dashboard of zeros. Test with JS disabled once.
  • Locale separators. countUp.js has separate separator and decimal options. A German locale needs . thousands and , decimals — invert the defaults or the number reads wrong even though the animation succeeds. Derive from app()->getLocale() rather than hardcoding.
  • Extension points are thin. With 9 stars and zero dependents, expect no config file and no documented hook system. Plan on: (a) subclassing the widget/column, (b) publishing and editing the Blade view, or (c) forking. Pin the version in composer.json and read the diff before upgrading — there is likely one maintainer and no meaningful CI gate.
  • Budget the performance. Each animated cell is an Alpine component. Ten stats on a dashboard is free; a hundred table cells on page load is not, especially on mobile.
  • Debugging checklist, in order: rendered HTML contains the expected x-data/data-* attributes → countUp.js present in network tab → no console errors → value is numeric, not a string → duration isn't 0 → Alpine initialised (check for a conflicting x-data on a parent). Almost every issue lands in the first two.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin