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

Infolists Laravel Package

filament/infolists

Filament Infolists provides a rich set of read-only display components for Laravel admin panels—text, badges, images, icons, key-value entries, and more—making it easy to build clear resource view pages and detail screens with Filament's familiar, elegant API.

View on GitHub
Deep Wiki
Context7

Getting Started

Infolists are Filament's read-only "display" layer: an ordered schema of entries that renders a record's data. They ship inside the filament/filament meta-package, so if you already have a panel installed you can start using them immediately — no extra composer require. For a bare Livewire app, the standalone filament/infolists package pulls in filament/schemas and filament/support.

First place to look is docs/01-overview.md (entries, state resolution, utility injection), then skim the entry list — TextEntry, ImageEntry, IconEntry, ColorEntry, KeyValueEntry, RepeatableEntry — plus the layout components (Section, Grid, Fieldset, Tabs, Split). Custom entries are covered in docs/09-custom-entries.md.

The fastest first use case is a Resource view page or a table "View" modal. On a ViewRecord page (v4/v5 signature):

use Filament\Infolists\Components\ImageEntry;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Schema;

public function infolist(Schema $schema): Schema
{
    return $schema->components([
        Section::make('Profile')->columns(2)->components([
            ImageEntry::make('avatar')
                ->circular()
                ->imageSize(40)
                ->defaultImageUrl(url('storage/avatars/default.jpg')),
            TextEntry::make('name')->weight('bold'),
            TextEntry::make('email')->copyable(),
            TextEntry::make('created_at')->dateTime('M j, Y'),
        ]),
    ]);
}

On Filament v3 the same page method receives an Infolist $infolist and you chain ->schema([...]) instead of ->components([...]). Check your major version before copy-pasting docs.

Implementation Patterns

Record-backed vs. standalone. The common case binds entries to the page's Eloquent record (TextEntry::make('name') resolves $record->name). The second case is embedding a standalone infolist in any Livewire component: add the InteractsWithSchemas trait, define infolist(Schema $schema), call ->record($this->user), and render {{ $this->infolist }} in the view. This is the pattern for "show this customer's details" cards, order summaries, and audit panels outside the admin panel.

Embedding inside forms. Infolist::make('summary')->components([...]) can live inside a form schema, which is how you build edit pages with a read-only header block. Use ->record() explicitly if the infolist is not the page's main schema.

Dot notation for relationships. TextEntry::make('author.name') and ImageEntry::make('author.avatar') just work. Prefer eager loading in getRecord()/modifyQueryUsing() rather than relying on per-entry lazy loads.

Derived state. When the value isn't a column, override it with a closure and let utility injection hand you the record:

TextEntry::make('posts_count')
    ->state(fn (User $record): int => $record->posts()->count())
    ->badge();

The same injection applies to nearly any configuration method: ->color(fn ($state) => ...), ->url(fn (Post $record) => route('posts.show', $record)), ->visible(fn ($record) => $record->isPublished()). Parameter names matter — $record, $state, $component, $livewire, $operation are resolved by name.

Formatting pipeline. formatStateUsing() → dateTime()/money()/limit()/listWithLineBreaks()/bulleted() → presentation (badge(), color(), icon(), weight(), size(), copyable(), tooltip(), suffixAction()). For enums, implement HasLabel/HasColor/HasIcon on the enum and Filament picks them up automatically.

Layout. Section is your card; Grid::make(3) plus columnSpan() / columnSpanFull() is how you get real dashboards. Split gives a 2/3 + 1/3 layout, Tabs is good for dense records (Overview / Billing / Activity) so you don't render 60 entries at once.

Reusable custom entries. php artisan make:filament-infolist-entry AudioPlayerEntry scaffolds a class plus a Blade view. Add fluent setters that store into nullable properties and return static, and getters that call $this->evaluate() so consumers can pass closures:

protected float | Closure | null $speed = null;

public function speed(float | Closure | null $speed): static
{
    $this->speed = $speed;
    return $this;
}

public function getSpeed(): ?float
{
    return $this->evaluate($this->speed);
}

Any public method on the entry becomes a $getSpeed() helper in the view. This is the cleanest extension point for charts, embedded players, maps, and QR codes.

Server round-trips from JS. Mark a public method #[ExposedLivewireMethod], add #[Renderless] if the UI doesn't need to re-render, and call $wire.callSchemaComponentMethod(@js($getKey()), 'methodName', ...args) from Alpine. Useful for lazy-loading waveform data or previews without building a whole Livewire child component.

Gotchas and Tips

  • Entries are not Livewire components. Public properties and methods on an entry class are not magically available in the Blade view. Use $getState(), $get('otherField'), $record, $operation, $this (the Livewire component), and $entry. Every custom view must be wrapped in <x-dynamic-component :component="$getEntryWrapperView()" :entry="$entry">, otherwise label, alignment, and columnSpan silently break.
  • $get() is stale until a request happens. Reading another component's state only refreshes on the next round-trip; make the source field live() if you need reactive updates. Similarly, ->state(fn () => ...) overrides the record value and won't recompute on every keystroke.
  • Image URLs expire. Unless the disk is public / visibility('public'), Filament generates temporary URLs (S3 presigned). Don't cache rendered infolist HTML, and set disk() explicitly when you're not on FILESYSTEM_DISK=local. defaultImageUrl() covers nulls but not broken paths.
  • hidden()/visible() are cosmetic, not authorization. The record is still hydrated server-side. Gate sensitive data with policies and simply don't add the entry — don't rely on ->hidden(fn () => ! auth()->user()->isAdmin()) as your only control. The same applies to copyable() on tokens and emails.
  • Array/collection state crashes TextEntry with "Array to string conversion". Reach for listWithLineBreaks(), bulleted(), or separator(', '). Enums need formatStateUsing(fn ($state) => $state?->label()) unless the enum implements Filament's contracts.
  • N+1 in table modals. A ViewAction modal resolving ten relationship entries against 25 table rows is 250 queries. Eager load in the table query, or hoist the shared infolist into a single method both the view page and the action use.
  • Version drift is the biggest source of copy-paste bugs. v3 uses Infolist $infolist + ->schema(); v4/v5 use Schema $schema + ->components(). The docs site defaults to the latest major — check the version selector when a snippet "doesn't exist".
  • Debugging: drop a ->state(function ($record) { dd($record); }) or ->visible(fn ($state) => dd($state)) into a suspicious entry to see exactly what Filament resolved and when. For layout issues, inspect the rendered wrapper — most "my entry has no label / is full width" reports trace back to a custom view missing $getEntryWrapperView().
  • Testing: infolists render inside the Livewire component, so Livewire::test(ViewUser::class)->assertSee('[email protected]') catches most regressions. Assert on the rendered string rather than on entry configuration — fluent configuration is easy to unit test but proves nothing about what a user sees.
  • Extension points worth knowing: ->extraAttributes() for hooking CSS/JS, FilamentView::registerRenderHook() for injecting markup around sections, and view namespaces if you're distributing reusable entries as a plugin. Register custom entry views under a consistent namespace so published views don't collide with app views.
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.
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo
bernskioldmedia/laravel-harvest
bernskiold/laravel-data-scrubber
bernskiold/laravel-currency-converter
bernskiold/laravel-campaign-monitor
bernskioldmedia/laravel-autotranslate
siberfx/telegram-bot
roy-sandip/laravel-view-extended
gregsphotography/site-builder-core
roy-sandip/laravel-view
anodyne/blade-fluentui-icons
webx-ui/module-catalog-collections