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 Toolbar Actions Laravel Package

opscale-co/nova-toolbar-actions

A Laravel Nova package that adds configurable toolbar actions to resources, placing quick-access buttons for common tasks above resource tables. Define actions once and expose them cleanly in the Nova UI without custom frontend work, simplifying repetitive admin workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

opscale-co/nova-toolbar-actions is a Laravel Nova add-on that surfaces Nova Actions in the resource index toolbar (alongside "Create") instead of the per-row dropdown. v1.0.0 is the first tagged release, so treat the API as unproven and read the source before leaning on it in production.

Minimal steps:

composer require opscale-co/nova-toolbar-actions

Nova packages are auto-discovered, so there is normally no provider registration step — verify with php artisan about or php artisan package:discover if the toolbar does not appear.

First place to look: a Nova Resource's action registration. The package's entry point is almost certainly a trait or a method override on App\Nova\Resource (e.g. toolbarActions() or a ToolbarActions trait/interface). Open vendor/opscale-co/nova-toolbar-actions/src and read the service provider plus the trait — at 1.0.0 that is faster and more reliable than any docs.

First use case: a single "Export selected / Export all" style action on a large index. Generate a standard Nova action (php artisan nova:action ExportRecords), then register it in the toolbar slot rather than actions():

// app/Nova/Resource.php
public static function toolbarActions(Request $request): array
{
    return [new \App\Nova\Actions\ExportRecords];
}

Then confirm: the button renders on the index, opens the action modal, and handle() receives the expected $models collection.

Implementation Patterns

Register on the base Resource, not per-resource. Toolbar actions are a cross-cutting concern; putting the override on App\Nova\Resource and filtering inside the method keeps every resource consistent and avoids copy-paste drift:

public static function toolbarActions(Request $request): array
{
    return array_filter([
        Nova::whenServing(fn () => new ExportRecords, fn () => null),
    ]);
}

Scope by resource class when a toolbar action only makes sense on some models:

public static function toolbarActions(Request $request): array
{
    return static::class === \App\Nova\Order::class
        ? [new BulkResendInvoices]
        : [];
}

Design for both contexts. A toolbar action is ambiguous about selection: it can be clicked with nothing selected, with a page selected, or "select all matching". Handle all three explicitly in handle():

public function handle(ActionFields $fields, Collection $models)
{
    if ($models->isEmpty()) {
        return Action::danger('Select at least one row.');
    }
    // dispatch a job per chunk rather than looping inline
    $models->chunk(500)->each(fn ($chunk) => ExportChunk::dispatch($chunk->modelKeys()));
    return Action::message('Export queued.');
}

Pair with showOnTableRow() / onlyOnIndex() deliberately. Keep destructive toolbar actions out of the row dropdown so there is exactly one affordance for "delete all selected", and always return an Action::confirm() modal for anything irreversible.

Compose with Nova's built-in export and filters. Toolbar actions read the filtered index query in most implementations — sanity-check this early, because "act on what the user is currently looking at" is the whole value of a toolbar versus a global command.

Gotchas and Tips

  • v1.0.0 has no meaningful documentation. The changelog is three commits (first release, Initial commit, a semantic-release dependency fix). Budget an hour to read src/ and write your own notes; do not assume the method signature from the package name.
  • Version pin tightly. No patch releases yet means no signal on backwards-compatibility policy. Use "opscale-co/nova-toolbar-actions": "1.0.*" and re-test on every bump.
  • Authorization is your job. authorize() on the Action gates the button, but toolbar rendering may not call it — check authorize() runs before the button paints, otherwise non-privileged users see a button that 403s on click.
  • $models may be empty or may be the full filtered set. Instrument handle() with a Log::info($models->count()) on first integration; behaviour differs between "none selected" and "select all".
  • Modal/field rendering. If your action defines fields(), confirm the modal opens from the toolbar — some toolbar implementations pass a different request payload than the row-dropdown path, which breaks dependent fields (dependsOn).
  • Dark mode and Nova version drift. Toolbar button components are the most likely thing to break between Nova 4 and Nova 5. Pin your Nova major and check the button renders in both themes before shipping.
  • Redirects from toolbar actions behave differently from row actions (no row context to return to). Prefer Action::message() over Action::redirect() unless you have tested the return path.
  • Long-running work must be queued. A toolbar action implies "operate on many records"; synchronous handle() will hit PHP max_execution_time. Dispatch jobs and return a message immediately.
  • Extension point to watch: if the package exposes a config file (config/nova-toolbar-actions.php), publish it with php artisan vendor:publish --tag=nova-toolbar-actions-config before editing — you want your customisations diffable against upstream defaults.
  • Debugging a missing toolbar: php artisan nova:publish after install, clear php artisan optimize:clear, and check the browser console for a failed Nova asset chunk — the button often fails silently on asset mismatch rather than throwing server-side.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
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