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

Filament Icon Select Column Laravel Package

guava/filament-icon-select-column

A Filament column for picking icons directly from your admin tables. Show an icon picker per row, choose from a configurable icon set, and save the selection to your model. Simple to install and drop into any Filament resource for quick visual editing.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm the version pairing before anything else. This package's major version is not an independent variable — it is derived from your Filament major. 3.x targets Filament v4 only; 2.x targets v3. Run composer show filament/filament first. If you are on v3, stop here and schedule this alongside the Filament v4 upgrade, not before it.

composer require guava/filament-icon-select-column:~3.0.1

Pin ~3.0.1. Do not use ^3.0 (that permits 3.0.0, which shipped with closeOnSelection silently broken) and do not install while the resolver is still free to pick a fresh minor.

Where to look first. The documentation surface for this package is thin — a description and release notes rather than a full README. The fastest orientation is the source itself: it is essentially one column class. Read that class before writing any code, specifically for:

  • the options() signature and whether it accepts an enum class, an enum instance array, or only a value→icon map;
  • whether closeOnSelection() exists as a fluent method and what it defaults to;
  • which size/color/alignment/tooltip methods are actually present, and their accepted argument types.

Ten minutes in the class beats twenty minutes guessing at fluent method names from the marketing description.

First use case. Take an existing resource where an icon is currently stored as a free-text field (the classic "people paste heroicon-o-foo and get blanks" ticket) and swap the table column:

use Guava\FilamentIconSelectColumn\Tables\Columns\IconSelectColumn;

public static function table(Table $table): Table
{
    return $table
        ->columns([
            IconSelectColumn::make('icon')
                ->options([
                    'heroicon-o-check' => 'heroicon-o-check',
                    'heroicon-o-x-mark' => 'heroicon-o-x-mark',
                ])
                ->closeOnSelection(),
        ]);
}

Then verify three things in the browser, in this order: the stored value renders as an icon (not raw text), clicking the cell opens a dropdown, and choosing an option both persists and closes the dropdown. That third check is the one the 3.0.1 patch exists to restore — verify it explicitly rather than assuming it works.

Implementation Patterns

Keep the options map in one place. The column's options must agree exactly with whatever the form's picker uses, or the table will render blanks for values the form happily lets editors save. Put the map in a static method on the enum or a small config class and pass the same source to both:

// app/Enums/CategoryIcon.php
public static function options(): array
{
    return [
        'heroicon-o-tag'      => 'Tag',
        'heroicon-o-bolt'     => 'Priority',
        'heroicon-o-archive'  => 'Archived',
    ];
}
// form
IconSelect::make('icon')->options(CategoryIcon::options())
// table
IconSelectColumn::make('icon')->options(CategoryIcon::options())->closeOnSelection()

If your column is backed by an enum with a cast, make sure the array keys match the cast's serialized value ($case->value), not the case name — a mismatch is the single most common cause of "the column renders nothing."

Distinguish display-only columns from editable ones. Most icon columns should be read-only in a list: an accidental click on a dense table is a data change. Decide per resource whether edit-in-cell is the point or a hazard. If the column class exposes a disabled/read-only modifier, use it; if not, restrict editing through resource authorization (canEdit) rather than leaving it open on every row.

Reuse via a small factory. Once three resources share the same column, wrap it:

public static function iconColumn(string $name = 'icon'): IconSelectColumn
{
    return IconSelectColumn::make($name)
        ->options(CategoryIcon::options())
        ->size(ColumnSize::Small)
        ->closeOnSelection();
}

This is where the buy-vs-build argument actually pays off — not the first column, but the fourth, when consistency is the thing you're buying.

Pair with a filter, not search. Icons are not meaningfully searchable as text. Add a SelectFilter over the same options map so operators can narrow the table by the underlying value; leave searchable() off the column.

Same registration inside relation managers. $table->columns() in a relation manager's table takes the column identically. Test both contexts — the v4 rewrite touched render paths, and the modal-vs-full-page table distinction is exactly where regressions hide.

Tune for density. Use tooltips or labels when the icon alone is ambiguous (status columns where two symbols look similar at 16px); keep icon-only with a tooltip when the column is one of twelve. Reserve color for genuine semantics — color-as-decoration trains operators to ignore it.

Gotchas and Tips

The failure mode is silent. Nothing throws when a stored value doesn't map to an option — you get an empty cell. There is no log line, no exception, no CI signal. When debugging, dd() the raw attribute value on the record and compare it byte-for-byte against your options keys before you touch anything else in the column.

Icon provider strings are not interchangeable. Heroicons (heroicon-o-check), Blade Icons (fas-user), and custom SVG sets use different naming conventions and different resolution paths. Store the exact identifier the provider expects, and if your set is remotely sourced or generated by an asset pipeline, validate the picker against the real provider before committing — the selection UX assumes a static, known option list.

Rebuild assets after install and after every Filament bump. A stale Filament asset build convincingly mimics a broken column. php artisan filament:assets plus your front-end build, before you file a bug.

Treat 3.0.x as stabilizing, not stable. The v4 rewrite shipped without behavior parity and needed a patch to restore closeOnSelection. Assume undisclosed gaps remain in keyboard navigation and search/filter integration. Write one smoke test that asserts selection closes the dropdown — in both a full-page table and a modal — and keep it. That test is your only protection, because observability cannot see this class of bug.

Pin and group your upgrades. Add the package to Renovate/Dependabot, group it with Filament core and other Filament plugins so coupled upgrades get reviewed in a single PR, and gate minors behind human review while patches flow. Record the pinned version and the "Filament major ↔ package major are one change" rule somewhere the next engineer will find it.

No migrations, no config, no runtime cost. There is nothing to publish, no service provider to configure, no data model impact. That also means there are no extension points to lean on — if you need behavior the class doesn't offer, subclass it or drop to a custom column view rather than hunting for a config flag.

Have the exit ready. Single maintainer, zero dependents, no SLA, no accessibility or security artifacts. The mitigation is that the fallback — a hand-written Filament column over your icon provider — is measured in days. Keep your usage thin and conventional (options array, one shared map, no clever subclassing) so that reversing the decision stays a one-line removal.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager