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

tomatophp/filament-icons

Filament Icons adds an icon picker, icon table column, and icon provider to FilamentPHP. Install via Composer, cache icons with filament-icons:install, then use IconPicker and IconColumn in forms and tables, including custom icons.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. This package is Filament-only. v5 line requires filament/filament ^5.0 (Livewire 4), Laravel 12/13 and PHP 8.3/8.4. If your panel is on Filament v4, you must stay on the v4 branch — the majors are not interchangeable. Check your panel's composer.json before anything else.

Install and warm the cache.

composer require tomatophp/filament-icons
php artisan filament-icons:install

The install command is not optional. It populates the cached icon registry that the picker reads from. Skip it and you get an empty selector, not an error.

Where to look first, in order:

  1. TomatoPHP\FilamentIcons\Components\IconPicker and IconColumn — these are the two classes you'll use 95% of the time; read their method signatures to see what's chainable.
  2. TomatoPHP\FilamentIcons\Facades\FilamentIcons — the registry service (register, asset, template, icons, replace, save). This is the extension point and the source of truth for what values are valid.
  3. The two artisan commands (filament-icons:install, filament-icons:clear) — your cache lifecycle.
  4. lang/ — the picker ships translations; if your panel is localized, confirm your locale exists (pt_BR was contributed, others may not be).
  5. Published config/views — only after the defaults disappoint you.

First use case — attach an icon to a resource. Add the column, then the form field:

// database migration
$table->string('icon')->nullable()->default('heroicon-o-academic-cap');
use TomatoPHP\FilamentIcons\Components\IconPicker;
use TomatoPHP\FilamentIcons\Components\IconColumn;

public static function form(Form $form): Form
{
    return $form->schema([
        IconPicker::make('icon')
            ->label('Icon')
            ->default('heroicon-o-academic-cap'),
    ]);
}

public static function table(Table $table): Table
{
    return $table->columns([
        IconColumn::make('icon')->label('Icon'),
    ]);
}

Store the icon identifier as a plain string; nothing else about your model changes. That's the whole integration — there's no trait, no migration publishing, no service provider registration required for the built-in Heroicons set.

Implementation Patterns

Picker + column as an inseparable pair. Anywhere you put IconPicker, put IconColumn on the corresponding table. The picker's value is opaque to users in a table row — a raw heroicon-o-academic-cap string in a text column is noise. The pair is the idiom.

Validate against the registry on write. The package does not enforce that a stored value is a real, registered icon. Do it yourself so a typo or a removed icon doesn't render as a blank cell:

use TomatoPHP\FilamentIcons\Facades\FilamentIcons;

IconPicker::make('icon')
    ->rules([
        Rule::in(collect(FilamentIcons::getIcons())->pluck('value')->all()),
    ])

(Confirm the exact accessor on the facade in your installed version — the shape changed in v4 when the Sushi model was dropped for native Cache.)

Custom icon library — register it in a provider, commit it, then refresh the cache.

use TomatoPHP\FilamentIcons\Facades\FilamentIcons;

public function boot(): void
{
    FilamentIcons::register('boxicons')
        ->asset('https://unpkg.com/[email protected]/css/boxicons.min.css')
        ->template('<i class="{ ICON }"></i>', 'text-xl', 'text-sm')
        ->icons(['bx bx-accessibility', 'bx bx-adjust'])
        ->replace(['bx ', 'bxs-', 'bxl-', 'bx-'])
        ->save();
}

Three things to internalize here:

  • ->asset() injects a stylesheet. For production, vendor or self-host that CSS rather than trusting a CDN URL — it's a runtime dependency on someone else's uptime and content.
  • ->template() is trusted code that gets rendered into your Blade output. Treat every new template as a small security review item, not a copy-paste.
  • ->replace() strips provider prefixes when matching/searching. Get this wrong and search returns nothing for icons you clearly registered.

Then, always in this order:

php artisan filament-icons:clear
php artisan filament-icons:install

Make cache warming a deploy step, not a manual one. Add php artisan filament-icons:install to your deploy script after config:cache and before traffic shifts. On multi-node or blue/green setups, run it on every node — the registry is a cache, and a cold node renders a cold picker.

Guard the provider registration. boot() runs on every request; save() writes to cache. Depending on version this is cheap or not, but the safe pattern is to only register when the cache is cold — check for the cached entry first and bail early. This also prevents a redeploy from silently overwriting a registry you refreshed out-of-band.

Multi-panel discipline. If you run several panels, pin the package version per panel in that panel's composer.json and never share an icon config across Filament majors. A v4 panel and a v5 panel in the same monorepo is a legitimate setup, but you need separate lockfiles or explicit per-package constraints.

Table rendering fallback. For records with null or legacy free-text icons, don't let the column render nothing. Use a state formatter or placeholder() so you can spot bad data in the table instead of hunting for invisible cells:

IconColumn::make('icon')
    ->placeholder('—')

Publish late, not early. vendor:publish --tag="filament-icons-views" and --tag="filament-icons-config" fork the package's internals into your repo. Only do it when you genuinely need to change markup or defaults — otherwise you've taken on maintenance of files you didn't write.

Gotchas and Tips

Blank picker = missing cache. The single most common failure. If IconPicker renders an empty or spinner-forever list, run php artisan filament-icons:install. Don't debug the component first.

Icon shows in the picker but not the column (or vice versa). These read the registry through different code paths. If you recently added a provider and only refreshed one side, clear and reinstall — don't assume a partial refresh worked.

The 50-option limit. A memory-optimization change in v1.1.2 truncated picker results, and v1.1.4 fixed icons "not listed in limited by 50 options" not appearing. If you're pinned to an old version and can't find icons that clearly exist, you're hitting this. Upgrade rather than working around it.

->native(false) matters. A community fix added this because native HTML select rendering broke the picker's markup. If the picker looks like an unstyled dropdown or icons render as raw text, check whether the native select is being forced.

Empty values in IconColumn were a bug in early releases (v1.0.1). If you're on something ancient, upgrade; if you're current and still seeing gaps, the value is probably null or malformed — validate on write as above.

Search vs. memory. The icon set can be large (Heroicons plus anything you register). Search is client-facing but the registry is server-cached; adding a thousand icons will affect page payload. Register what you'll actually use, not entire icon libraries wholesale.

Stored values are strings with no contract. There's no enum, no foreign key, no schema. An icon renamed or removed by a provider upgrade leaves dead data in your DB. Decide now what your fallback render is, and consider a periodic audit query for values not present in the registry.

Prefix stripping is the search index. If ->replace() doesn't cover every prefix variant your provider emits (bx, bxs-, bxl-, bx- in the Boxicons case), users will search for "accessibility" and get nothing. Test search with the substring a human would actually type, not the full class name.

Debugging the registry directly. When in doubt, drop into php artisan tinker and inspect what the facade actually holds — compare that list against what your picker shows. That immediately tells you whether the problem is registration, caching, or rendering.

Low adoption, no SLA. 39 stars, zero reported dependents, MIT. Pin the exact version in composer.json, keep the integration surface narrow (picker + column only), and have a fork plan. The exit cost is genuinely low — two components and a registry — so don't build features on top of the package's internals; build them beside it.

Upgrade cadence is tied to Filament. A Filament major bump forces a coordinated Filament + Livewire + this package upgrade. Schedule it with your Filament upgrade, not as an independent chore, and check the branch (v5 vs v4) before running composer update.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core