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 Action Button Selectors Laravel Package

lexicon/nova-action-button-selectors

A Laravel Nova package that adds configurable action button selectors to your resources, letting you control which action buttons appear and when. Simplify conditional action visibility and tailor the Nova UI to each resource's workflow without writing custom JavaScript or extra components.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Verify the install name before you type it. The repo (pitchayakit/nova-action-button-selector) and the Composer package (lexicon/nova-action-button-selectors) do not share a namespace, which is a common sign of a renamed/vendored fork. Check what's actually published:

composer show lexicon/nova-action-button-selectors --all
# or, if nothing comes back, add a VCS repo entry and require the repo name:
composer config repositories.nova-abs vcs https://github.com/pitchayakit/nova-action-button-selector
composer require lexicon/nova-action-button-selectors

Confirm the autoloaded namespace in vendor/lexicon/nova-action-button-selectors/composer.json — everything below assumes the class resolves as Lexicon\NovaActionButtonSelectors\ActionButtonSelector. Adjust to whatever the package actually ships.

2. Register it. Most Nova UI packages of this shape either ship a service provider (auto-discovered) or require explicit registration in app/Providers/NovaServiceProvider.php. Look for a NovaServiceProvider-style tools() / assets() registration or a publishable config:

// config/app.php or NovaServiceProvider — whichever the README specifies
public function tools()
{
    return [
        new \Lexicon\NovaActionButtonSelectors\ActionButtonSelector(),
    ];
}

Then publish assets if the package has them (php artisan vendor:publish --tag=nova-action-button-selectors) and recompile.

3. Where to look first. Read the source, not just the README (17 stars, archived — documentation will be thin). Start with:

  • src/ — the field/tool class and its component() string
  • resources/js/ — the Vue component, to see what props it expects (actions, resourceId, resourceName)
  • dist/ — whether prebuilt assets exist at all; if not, you must npm run dev inside the package or vendor the build

4. First use case. The payoff for this package is collapsing a resource's action bar. Instead of Nova rendering five separate buttons above a detail view, you get one dropdown:

// app/Nova/User.php
public function actions(NovaRequest $request)
{
    return [
        ActionButtonSelector::make()
            ->actions([
                ApproveUser::class,
                SuspendUser::class,
                ResendWelcomeEmail::class,
            ]),
    ];
}

Ship that on one internal-admin resource first. It's the easiest place to catch authorization and confirmation-dialog regressions before rolling it across the app.

Implementation Patterns

Index vs. detail parity. Nova's actions() method is shared by both contexts. The selector will render in the index row and the detail header, but the underlying actions receive different request payloads (resources as an array of IDs on index, resource on detail). Test both. If an action only makes sense in one place, keep the per-action flags:

ActionButtonSelector::make()
    ->actions([
        ApproveUser::make()->onlyOnDetail(),
        BulkSuspend::make()->onlyOnIndex(),
    ]),

Authorization flows through — lean on it. Don't hand-roll visibility in the selector; put it on the actions. ->canSee(fn ($request) => $request->user()->isAdmin()) on each action is the cleanest way to keep the dropdown from showing options that will 403 on click. If the selector supports a ->canSee() of its own, use it to hide the whole button when no child action is permitted, otherwise you get an empty dropdown.

State-dependent grouping. The most valuable pattern is splitting destructive vs. safe operations rather than dumping everything in one list:

ActionButtonSelector::make()
    ->label('Manage')
    ->actions([
        ApproveUser::class,
        ResendWelcomeEmail::class,
        // destructive last
        SuspendUser::make()->withConfirmButton('Suspend')->withConfirmation(),
    ])
    ->canSee(fn ($request) => $request->user()->can('manage', $this->resource)),

Keep destructive actions at the bottom of the list — muscle memory means the top item gets clicked.

Confirmation dialogs. Nova actions already support ->withConfirmation(). The selector typically re-uses the action's modal, so configure confirmation on the action, not the selector. If you end up with two confirmations, the selector is intercepting the click — drop the selector-level one.

Resource vs. tool placement. Two integration shapes:

  • Inline in a resource (actions() as above) — best for per-record operations.
  • As a standalone Nova tool/page — useful for cross-resource workflows (e.g., "Run nightly import"). Register via tools() and give it a Nova::script() entry.

Frontend extension. Because this is a Vue component, the highest-leverage customization is a thin wrapper: copy the package's .vue into resources/js/components/, register it with Nova.booting(), and point your selector at it. That buys you icon-only mode, custom button classes, and keyboard nav without forking.

Testing. Cover the endpoints, not the component. Assert that actions appear/disappear for different users, and hit the action's route directly to confirm the server-side authz still applies:

$this->actingAs($admin)
    ->get("/nova-api/users/action?action=ApproveUser")
    ->assertOk();

Add one Dusk/browser assertion that the dropdown opens and a child action fires — that's the only thing unit tests can't catch here.

Gotchas and Tips

Archived with zero dependents is the headline risk. Budget for a fork. Before adopting, diff the package against the Nova version you run; if it targets Nova 3 (webpack/Mix) and you're on Nova 4 (Vite), the compiled assets will be served but the component registration will not fire, and you'll see a blank button with no console error unless you check the Network tab for a 404 on js/…js.

Package name ≠ repo name. This is the single most common install failure for forks. If composer require lexicon/nova-action-button-selectors 404s, use the VCS repository route shown above and let Composer infer the name from the package's composer.json. Pin it: "lexicon/nova-action-button-selectors": "dev-main#<sha>".

Nova asset cache. After any config or asset change:

php artisan nova:publish
php artisan optimize:clear
php artisan vendor:publish --tag=nova-assets --force

A stale public/vendor/nova is the cause of ~80% of "component doesn't render" reports. Hard-refresh the browser too.

Silent empty dropdown. If the button renders but the list is empty, the selector is calling authorizedToSee() and every action is failing its policy check. Action::canSee closures receive the Nova request, not the model — don't reference $this->resource inside them when used in a selector, since the selector aggregates actions before any record is bound. Use ->canSee(fn ($request) => ...) with only $request, and move model-dependent logic into ->canRun().

Batch actions and selectedResources. On the index, Nova passes selected IDs. If your action reads $this->resources expecting a collection but the selector fired it in detail mode, you get a null. Guard both:

public function handle(ActionFields $fields, Collection $models)
{
    foreach ($models as $model) { /* ... */ }
}

Don't nest selectors. Multiple ActionButtonSelector instances on one resource tend to fight over the same dropdown state; if you need two groups, put them on separate tools or accept one merged menu.

Debugging checklist, in order: browser console → Network tab for the component JS → Nova::script() registration → nova:publish → check component() string matches the registered Vue name (action-button-selector vs action-button-selectors is an easy typo to inherit from a fork).

Extension points worth knowing. The action class's fields()/handle() are untouched by this package, so all your existing Nova action logic ports over unchanged. The selector is purely a presentation layer — which is also its limitation: anything you want (conditional enable/disable, per-row state, icons) has to be baked into a wrapper component, because the archived package won't be getting feature work.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource