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

Nova Status Field Laravel Package

wesselperik/nova-status-field

A Laravel Nova field for displaying statuses as colorful labels or badges in index and detail views. Define custom status labels and colors, then drop the field into any Nova resource for a clean, readable status display.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register nothing. This package has no service provider, no config publish, no migrations, and no assets to compile. That is the entire install:

composer require wesselperik/nova-status-field

Then drop the field into a Nova resource's fields() method:

use WesselPerik\NovaStatusField\StatusField;

public function fields(Request $request): array
{
    return [
        StatusField::make('Status', 'status')
            ->labels([
                'pending'   => 'Pending',
                'active'    => 'Active',
                'suspended' => 'Suspended',
            ])
            ->colors([
                'pending'   => 'bg-yellow-100 text-yellow-800',
                'active'    => 'bg-green-100 text-green-800',
                'suspended' => 'bg-red-100 text-red-800',
            ]),
    ];
}

Where to look first. The README is the only real documentation and it is short — read it end to end, especially the color and icon examples, before you write any mapping. Do not trust third-party write-ups describing Filament popups or tooltips; those describe a different package. Verify the accepted color format (Tailwind token classes vs. raw CSS colors) and the supported Nova major directly against the install.

First use case. Pick one high-traffic resource you already own — an orders table, a ticket queue, a user list — where an operator scans a column and wants status legible at a glance. Add the field to the index and detail views, render a handful of statuses, and confirm the badges look right in both light and dark mode. That's a 20-minute first pass and it tells you whether your Tailwind build actually ships the classes you're handing it.

Before you commit, verify three behaviors because the docs won't tell you clearly:

  1. What renders when a status value has no entry in labels() or colors() — a default badge, a blank cell, or an exception?
  2. Do badges look identical to a hand-rolled badge when you never call background() / textColor()?
  3. Does your exact Nova major + PHP version work? Budget a scratch-resource spike rather than assuming.

Implementation Patterns

Centralize the palette immediately. The package is per-field configuration, which means without discipline you will end up with the same status array copy-pasted across six resources and drifting. Put the map in one place — an enum, a config file, or a small helper class:

final class StatusPalette
{
    public const LABELS = [
        'pending'   => 'Pending',
        'active'    => 'Active',
        'suspended' => 'Suspended',
    ];

    public const COLORS = [
        'pending'   => 'bg-yellow-100 text-yellow-800',
        'active'    => 'bg-green-100 text-green-800',
        'suspended' => 'bg-red-100 text-red-800',
    ];
}

If you have a PHP enum backing the status column, derive the map from the cases rather than hand-writing keys — that eliminates the most common failure mode (a typo'd key that fails silently):

->labels(collect(OrderStatus::cases())->mapWithKeys(
    fn ($case) => [$case->value => $case->label()]
)->all())

Wrap it in a per-domain factory. Every resource that shows a status column should call the same factory, so the palette is applied consistently across index, detail, and relation-manager tables:

final class OrderStatusColumn
{
    public static function make(string $attribute = 'status'): StatusField
    {
        return StatusField::make('Status', $attribute)
            ->labels(StatusPalette::LABELS)
            ->colors(StatusPalette::COLORS)
            ->icons([...])
            ->background([...])
            ->textColor([...]);
    }
}
// In the resource
OrderStatusColumn::make(),

Now a brand-color change is a one-file edit, and every table picks it up. This is the single highest-leverage pattern with this package.

Use background() / textColor() deliberately (3.1.0+). These affect the popup, not the badge itself — new in 3.1.0, and additive, so omitting them leaves existing rendering untouched. They accept a single value or a per-icon map, and support Tailwind tokens or raw colors:

->background('bg-gray-900')          // single value, all statuses
->textColor(['active' => '#00ff00']) // per-icon map

Treat raw colors as the safer choice in a Tailwind setup: they cannot be purged. Reach for Tailwind tokens only when you control the safelist.

Separate index from detail where it matters. The field renders in both places; if the detail view needs more context than the index badge, register two field instances (the detail one can carry richer labels or popup colors) rather than compromising one configuration for two jobs.

Pair the column with a filter and a metric. The badge is a rendering concern only — it does not give you filtering. Add a Nova filter for the same status set and, on dashboards, a value metric per status. Build all three from the same palette constants so the numbers and the badges agree.

When a color key doesn't exist, provide a fallback. Whether the package defaults gracefully is something you should confirm in the spike; if it doesn't, add a catch-all key (default) that renders a neutral badge, so a new status added to the database doesn't produce an invisible cell.

Gotchas and Tips

Mapping key mismatches fail quietly. A status value with no matching labels()/colors() entry does not throw — it produces an unstyled or blank badge, and nobody notices until someone screenshots the dashboard. Derive maps from enum cases or assert coverage in a unit test that walks every case against the palette arrays. This is the number one support ticket with this package.

Tailwind purge will eat your tokens. bg-green-100 text-green-800 only renders if those classes survive the compiled bundle. Classes referenced from a config file or a dynamically-built string are invisible to Tailwind's content scanner. Either add them to safelist in tailwind.config.js, list the palette file explicitly in content, or prefer raw color values. Re-check badges after any change to content paths — the failure is silent and looks like a CSS bug, not a config bug.

3.1.0 tightened return types in StatusField.php. If you subclass the field, wrap it in a decorator, or mock it in tests, audit those signatures before upgrading. Plain consumers are unaffected, but a signature mismatch is fatal in CI, not production — which is exactly when you want to find it. Pin the version so the next tightening doesn't arrive unannounced: with ~30 stars and zero dependents, you are the first serious adopter and there is no ecosystem watching the changelog for you.

Dark mode is your contrast test. background() and textColor() are set independently, so a combination that looks fine on light surfaces can be unreadable on dark ones. Check both themes for each status, and prefer paired values (background token + matching text token) over mixing raw hex with Tailwind classes in the same badge.

Test the unmapped path in code, not by hope. Write a small test that iterates OrderStatus::cases() and asserts each value has a label and color. It costs ten lines and permanently retires the "why is this cell blank" question.

No config publish means no upgrade surface — and no escape hatch. Because everything lives in your resource code, upgrades are low risk, but it also means there is no vendor file to patch in a hurry. Extract the factory helper (above) early so that if you ever need to swap the package out or fork it, you're changing one class instead of every resource.

Extension points are limited by design. There is no custom Vue component, so you cannot add interactive popup behavior, action buttons, or AJAX content. If a stakeholder asks for that, it's a different field — don't try to stretch this one. Same for tooltips and accessibility beyond a colored label: this gives you legible text, not a certified a11y component.

Ramp-up is under an hour for a Nova developer. The genuine cost is not learning the API; it's establishing the shared palette and documenting which color format the team uses. Write a one-page internal note covering "Tailwind token vs. raw color" and "always use OrderStatusColumn::make()" — that eliminates most repeat questions before they form.

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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk