flatroy/nova-progressbar-field
flatroy/nova-progressbar-field adds a customizable progress bar field to Laravel Nova resources. Show percentage-based progress in index and detail views, with configurable colors, labels, and value formatting for quick visual status tracking.
flatroy/nova-progressbar-field is a Laravel Nova field package — it renders a progress bar inside a Nova resource instead of a raw number. It ships no service provider config worth publishing and no migrations, so setup is short:
composer require flatroy/nova-progressbar-field
Grab the exact field class/namespace from the README before your first import (the package has been renamed/renamespaced across early releases, and the class name does not match the Composer package name). Then drop it into a resource:
public function fields(NovaRequest $request)
{
return [
Progressbar::make('Progress'), // verify import from README
];
}
Look first at: the README usage block (class name, min/max, formatting options), then the field's src/ directory to see which Field methods are actually implemented — this package is thin, so the source is the real documentation.
First use case: show a completion percentage on the index list — e.g. onboarding completion, a course's lesson progress, or a project's task burn-down. Start with ->onlyOnIndex() so you validate rendering before wiring it into detail views.
Backing the bar with a computed value. Don't store a redundant percentage column. Resolve it at render time:
Progressbar::make('Progress')
->resolveUsing(fn ($resource) => $resource->completed_tasks / max($resource->total_tasks, 1) * 100)
->onlyOnIndex(),
Or expose it as an accessor on the model (getProgressAttribute()) so the field stays dumb and the logic is testable outside Nova.
Avoiding N+1 on index lists. A resolveUsing closure runs per row. If progress depends on related records, use withCount() in the resource's indexQuery and compute from the counts:
public static function indexQuery(NovaRequest $request, $query)
{
return $query->withCount(['tasks', 'tasks as done_tasks_count' => fn ($q) => $q->whereDone(true)]);
}
Sizing (new in 0.0.6). Custom width support means the bar no longer has to fill the table cell. Use it to keep a progress column visually subordinate to the primary columns, and to prevent very wide bars on detail views where Nova's field area is much wider than the index cell. Check PR #4 for the exact method name and whether it accepts a CSS length ('180px', '50%') or a unitless number — the two behave very differently in a table cell.
Pairing with a numeric field. Progress bars lose precision. A common pattern is bar on index, raw number on detail:
Progressbar::make('Progress')->onlyOnIndex(),
Number::make('Progress', 'progress')->suffix('%')->onlyOnDetail(),
Scoping by view. ->onlyOnIndex(), ->onlyOnDetail(), ->hideWhenCreating(), ->hideWhenUpdating() — a progress bar is a read-only affordance and should never appear on create/update forms unless it's genuinely editable (it usually isn't; this is a display field).
Inline vs. full-row. On dense index tables, keep the bar narrow via the new width option and add ->help() or a tooltip to carry the exact number; on detail views let it breathe.
0.0.x, minor bumps are effectively patch-level API changes. Pin the version in composer.json and read the diff on every bump — 0.0.6 is additive, but that's not guaranteed going forward.composer update, run php artisan nova:publish (or your asset build) and hard-refresh. A stale compiled field is the most common "the bar doesn't render" symptom.min/max typically render as an over-wide or clamped bar rather than throwing. Guard nullables explicitly (?? 0) — a null progress on a fresh model is the usual cause of an empty cell that looks like a rendering bug.->sortable() silently won't work. Either sort on the underlying numeric column instead, or skip sortability.px width larger than the column will clip or force horizontal scroll. Prefer percentages on index, fixed widths on detail.config/progressbar.php to tweak — colors, height, and thresholds (if present) are set per-field or not at all. If you need conditional coloring (red under 30%, green over 80%), do it in the resolver and check whether the field exposes a color/style hook before reaching for CSS overrides in Nova::style().How can I help you explore Laravel packages today?