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 Tabs Laravel Package

dkulyk/nova-tabs

A Laravel Nova package that organizes resource fields into clean, customizable tabs on create, update, and detail pages. It improves form usability, supports flexible tab configuration, and keeps complex forms easy to navigate.

View on GitHub
Deep Wiki
Context7

Getting Started

Install (in a Nova project):

composer require dkulyk/nova-tabs

No service provider registration is required — it is a Nova field package, auto-discovered by Laravel. There is no publishable config or asset step in the typical install.

Where to look first:

  • vendor/dkulyk/nova-tabs/src/ — the two classes you actually use, the Tabs container and the Tab child field.
  • The package README.md for the exact make() signature of the release pinned in your composer.lock (this package is archived, so the README is the contract you have).
  • Your resource's fields() method — that is the only integration surface.

First use case — breaking a crowded form into tabs:

use Dkulyk\NovaTabs\Tabs;
use Dkulyk\NovaTabs\Tab;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Textarea;

public function fields(Request $request)
{
    return [
        Tabs::make([
            Tab::make('Overview', [
                Text::make('Name')->rules('required'),
                Textarea::make('Summary'),
            ]),
            Tab::make('Settings', [
                Text::make('Slug'),
                Boolean::make('Published'),
            ]),
        ]),
    ];
}

Start by moving only the fields you already have into a single Tabs::make() and confirming it renders on the detail and update screens before adding a second tab. That isolates package issues from field issues.

Implementation Patterns

Split create/update by resource method. Because fields() returns a plain array, you can extract tab construction into a private method and reuse it across resources:

protected function contentTabs(Request $request): array
{
    return [
        Tabs::make([
            Tab::make('Content', [/* ... */]),
            Tab::make('SEO', [/* ... */]),
        ]),
    ];
}

Call it from fields() in both the parent and any related resources that need the same grouping.

Mix tabs with non-tab fields. Keep status/meta fields outside the tab container so they stay visible on every tab:

return [
    Status::make('Status'),

    Tabs::make([ /* ... */ ])->withMeta(['class' => 'mt-4']),

    $this->auditFields(),
];

Combine with panels. Nest Panel inside a Tab when a single tab is long, and keep the Tabs container at the top level of fields(). Avoid nesting Tabs inside Tabs.

Gate whole tabs. Apply the same visibility API you use on fields (->canSee(...) / ->hideWhenCreating()), evaluated on the Tab instance. Compute the closure from $request->user() so tabs disappear for restricted roles rather than rendering empty.

Conditional fields inside a tab. Field-level dependsOn/resolveUsing continues to work normally — the tab is only a layout wrapper, so dependent fields still respond to the fields they reference even when those fields live in another tab.

Validation is unaffected. Rules declared on fields inside a tab are collected into the standard Nova validation payload. Use ->rules() on the field, not on the Tab, and keep rule ordering (required before max) as you would in a flat form.

Detail vs. form. Fields marked onlyOnDetail() or onlyOnForms() remain respected inside tabs; use this to show computed values on detail while keeping the update form lean.

Gotchas and Tips

  • Archived and last released January 2019. This targets the Nova 1.x/2.x era. Before adopting, verify it renders correctly on your Nova major version; the compiled JS and field contract likely predate Nova 4's changes. Pin it in composer.lock and budget for a fork if you are on a recent Nova.
  • No native search/filter integration. Tabs are a display container only; filters and searchable columns must be declared on the underlying fields, not on tabs.
  • Index screens. If any child field has sortable/showOnIndex, confirm the container renders sensibly on the index — layout wrappers were not designed for index tables. Force child fields ->hideFromIndex() and surface key columns as separate top-level fields if the table looks broken.
  • Duplicate field names. Two tabs cannot both declare Text::make('Name') cleanly; Nova resolves by field name. Keep field names unique across all tabs in a resource.
  • Panel + tab ordering. The visual order follows the array order inside Tab::make([...]); reordering the top-level array reorders tabs but not child fields inside a tab. Drag to reorder one level at a time.
  • Debugging empty tabs. dd($this->fields($request)) inside fields() to confirm the tab returns its children. If the container renders but the tab bodies are empty, the issue is almost always a Nova version mismatch in the compiled component, not your field definitions.
  • Assets. If the package references a published JS/CSS bundle and tabs render as raw markup: clear Nova's published assets (php artisan nova:publish after reinstalling), then hard-refresh the browser — stale bundles are the most common cause.
  • Extension points are minimal. There is no config file, no events, and no service provider of your own to extend. Customization means subclassing Tab/Tabs or forking the view/JS. For anything non-trivial, evaluate a maintained alternative (e.g. eminiarts/nova-tabs or outl1ne/nova-tabs) rather than patching an archived package.
  • Upgrade path. Because it is unmaintained, treat nova-tabs as a temporary layout shim. Isolate tab construction in dedicated traits (HasTabbedFields) so that swapping the package for a maintained one is a one-file change per resource.
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.
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
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console