bobimicroweber/accordion
Accordion is a Laravel package that adds collapsible, accessible accordion UI to your Blade views. Group content into expandable panels, control open and closed states, and style everything to match your app. A lightweight, framework-native way to organize FAQs, settings, and dense content.
Install the fork with Composer, then confirm which Filament major it targets before writing any code:
composer require bobimicroweber/accordion
Read these first, in order:
composer.json in the package — it reveals the filament/filament constraint and the PHP autoload namespace. This fork may still autoload under LaraZeus\Accordion\ (matching the upstream lara-zeus/accordion repo) or under Bobimicroweber\Accordion\. Register the wrong namespace in your form class and Filament silently throws a "class not found" only at render time.src/ tree — check whether the API is Accordion::make()->schema([...]) (v4-style) or Accordion::make()->schema([...]) with Form\Components imports (v3-style). The method names are near-identical; the parent classes are not.tests/ — if none exist, treat every upgrade as a manual regression test on one form in staging.First use case: a resource form with three or more logical groups where you want a compact vertical layout without losing editability — e.g. a CustomerResource with "Personal", "Billing address", "Notification preferences". Replace a stack of Section::make(...)->columns(2) calls with an accordion of items, each containing a Grid:
use Bobimicroweber\Accordion\Components\Accordion; // verify namespace
use Bobimicroweber\Accordion\Components\AccordionItem;
public static function form(Schema $schema): Schema
{
return $schema->components([
Accordion::make('details')
->schema([
AccordionItem::make('Personal')
->schema([
TextInput::make('first_name')->required(),
TextInput::make('last_name')->required(),
])->columns(2),
AccordionItem::make('Billing')
->schema([
TextInput::make('address')->columnSpanFull(),
TextInput::make('city'),
TextInput::make('postcode'),
])->columns(2),
AccordionItem::make('Preferences')
->schema([
Toggle::make('newsletter'),
Toggle::make('sms_alerts'),
]),
]),
]);
}
Ship it behind a feature flag on one form before rolling out to the rest of the panel.
Item-per-fieldset, not item-per-field. The component's value is in collapsing groups, not reducing the height of a 12-field grid to one click. Keep 2–6 items; anything above that is a wizard, not an accordion.
Mirror your resource structure. The cleanest integration is to keep the accordion in form() and push validation rules onto the fields inside each item, so the accordion is purely presentational. Avoid putting ->relationship() or ->saveRelationshipsUsing() on the accordion itself — those belong on the inner components where Filament expects them.
Reuse as a shared schema. If the same grouping appears in create, edit, and a custom action modal, extract it:
// app/Filament/Schemas/CustomerForm.php
final class CustomerForm
{
public static function schema(): array
{
return [
Accordion::make()->schema([
AccordionItem::make('Personal')->schema([...]),
AccordionItem::make('Billing')->schema([...]),
]),
];
}
}
Then spread it: $schema->components(CustomerForm::schema()).
Pair with Grid for internal layout. Each item is a container — give it ->columns() or drop a Grid::make(3) inside so the accordion doesn't force a single-column design. This is the difference between a usable form and a long thin one.
Default-open strategy. Open the first item by default (or the item that contains required fields / the currently-focused error), and leave the rest closed. Most implementations surface a ->open() / ->collapsed(false) style method per item — verify the exact name in the source; the upstream uses ->collapsed() semantics on sections, this may differ. If no such method exists, set defaultOpen-like state via the item's ->extraAttributes(['x-bind:data-open' => 'true']) only as a last resort — Alpine state is managed by the component and fighting it is fragile.
Use it as a livewire-form drop-in. Nothing about the component ties it to resources. In a custom Livewire component using Filament\Forms\Concerns\InteractsWithForms, the same schema array works — which is handy for settings pages or multi-tenant onboarding flows where you want progressive disclosure without a wizard's "Next" button.
Pair with ->columnSpanFull(). If the accordion is placed inside a resource form's grid, it will be squeezed into a column unless it spans full width. Explicitly set the span on the accordion, not on the items.
Validation errors in collapsed items. The single most common production complaint. If a required field inside a closed item fails validation, Filament highlights a field the user cannot see. There is no framework-level guarantee this package auto-opens the offending item. Before shipping, test: submit an empty form → confirm the accordion opens the item(s) with errors. If it doesn't, hook onValidationError on the Livewire component (or override afterValidate) and force-open the items whose keys appear in $this->getErrorBag(). Cache a map of fieldName => itemKey at schema build time so the hook stays cheap.
Livewire re-renders can reset open state. If the accordion uses Alpine x-data for its open/close state and the surrounding form triggers a partial re-render (->live(), ->reactive(), dependent selects), the DOM node is replaced and the visual open state is lost even though field values persist. Symptom: user expands a section, changes a sibling field that fires ->live(), and the accordion snaps shut. Test this explicitly. If the package doesn't persist open state across renders, either keep dependent fields outside the accordion, or bind the open key to a public Livewire property via wire:model on the item.
Filament v3 vs v4 import churn. This fork's raison d'être is likely a v4 bump. If you're still on v3, you may be better off on lara-zeus/accordion (the upstream this mirrors). Check composer.json's filament/filament constraint before assuming compatibility — installing a v4-only fork into a v3 panel produces confusing type errors deep inside Filament\Schemas\Schema.
Tailwind asset compilation. Filament plugins that ship Blade views often need php artisan filament:assets (or a publish step) to get their CSS/JS into the panel's compiled bundle. If the accordion renders as an always-expanded stack, you're missing the Alpine component registration or the plugin hasn't been added to Panel::make()->plugins([...]). Check the install docs for a PanelProvider registration step — many Filament components require one even when they seem purely server-rendered.
Nesting conflicts with Section and Wizard. Do not nest an accordion inside a step, or a Section inside an accordion item with its own collapse toggle. Each layer introduces its own Alpine scope and the click handlers collide (usually by double-toggling). Flatten the hierarchy: accordion at the top, Grid/Fieldset inside.
Version pinning given the low adoption. With ~11 stars and zero dependents, this is a young fork. Pin it exactly ("bobimicroweber/accordion": "0.3.*") and be prepared to fork a bug fix locally. If you hit a blocking issue, diff against lara-zeus/accordion upstream — fixes usually land there first, and you can port them or switch packages without changing your schema (the API is intentionally a superset of the section layout it replaces).
Extension point: render hooks. If you need per-item badges ("3 required fields remaining"), the sanest approach is a custom Blade view via ->view('filament.accordion.item') that wraps the default and adds content in a named slot — rather than subclassing the item component, which ties you to its internal state properties and breaks on upgrade.
How can I help you explore Laravel packages today?