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

Tabler Icons Enum Laravel Package

lara-zeus/tabler-icons-enum

A Laravel enum for Tabler Icons that exposes every icon name as a typed PHP case. Use it to populate selects, validate icon choices, and reference Tabler icons cleanly in Filament forms or Blade views without hard-coded strings or manual lists.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and confirm the major. composer require lara-zeus/tabler-icons-enum — the 2.0.1 release line is aligned to Filament 5. If you're not on Filament 5 or you're framework-agnostic, pin the version explicitly in composer.json rather than letting Composer resolve the latest, and check composer.json in the repo for the PHP floor (backed enums → PHP 8.1+) and whether filament/filament is a hard requirement or a suggest.

  2. Find the enum first, then everything else. Open src/ and locate the single enum class (the package is essentially one file). Note three things before writing any code:

    • The FQCN — you'll type-hint and import this everywhere.
    • The case naming convention (PascalCase case names derived from kebab-case icon slugs, e.g. IconBrandTabler ↔ brand-tabler), since you'll be mapping back to ti ti-* classes.
    • The label() helper — check whether it returns a humanised name, the raw slug, or a title-cased variant; that determines whether you can use it directly in UI labels or need your own formatter.
  3. Confirm the class-name ↔ CSS-class mapping. Render one icon end-to-end in a real Blade view against the Tabler asset version you actually ship (Sprite or CSS). The enum gives you names; you still need the ti ti-* class string, either via $case->value (if backed) or a wrapper. Do this before migrating anything — it's the one assumption that, if wrong, invalidates the whole refactor.

  4. First use case: a Filament select. This is the shortest path to value and the package's stated purpose:

    use LaraZeus\TablerIconsEnum\TablerIcon; // verify FQCN in src/
    
    Select::make('icon')
        ->options(
            collect(TablerIcon::cases())
                ->mapWithKeys(fn ($c) => [$c->value => $c->label()])
                ->all()
        ),
    

    If that renders a searchable, type-safe icon picker, the spike is done. If label() is missing or unhelpful, fall straight through to your own options() helper (see below).

Implementation Patterns

Blade — replace literals with cases. The core win is that a typo becomes an error instead of a blank box:

{{-- Before --}}
<x-icon name="ti ti-brand-github" />

{{-- After --}}
<x-icon :name="'ti ' . \LaraZeus\TablerIconsEnum\TablerIcon::BrandGithub->value" />

Wrap the 'ti ti-' prefix in a single Blade component or a small helper (icon(TablerIcon $icon)) so the class-string convention lives in exactly one place, not in 400 templates. That helper is also where you'd swap the prefix if you move from CSS classes to an SVG sprite.

Validation at trust boundaries. Anywhere the icon name is user-supplied or DB-sourced, validate against the enum rather than a hardcoded list:

'icon' => ['required', Rule::enum(TablerIcon::class)],

// Or, for legacy string input:
$icon = TablerIcon::tryFrom($request->input('icon'))
    ?? throw new ValidationException(...);

Rule::enum() is the reason to prefer this over a config('icons') array — it stays correct as the enum grows, with zero maintenance.

Config and menu definitions. Menu/nav arrays that currently hold 'icon' => 'ti ti-home' can hold 'icon' => TablerIcon::Home and be resolved at render time. This is the highest-leverage change because config files are where icon strings go to die — reviewed by nobody, executed at runtime.

DB-stored icons need a migration plan, not a codemod. If a menu_items.icon or statuses.icon column holds strings, you have three options, in order of preference:

  • Keep the column as a string but add Rule::enum() on write and a cast/accessor on read — low risk, incremental.
  • Backfill to a canonical set of enum values with a data migration, then constrain at the DB level (enum column or check constraint).
  • Leave it and only enforce in the form layer — acceptable if the table is small and admin-only.

Grep first (ti ti-, tabler-, 'icon' =>) to size this before promising a timeline; DB-stored icons are reliably the long pole in these migrations.

Filament reuse — extract one options provider. You'll build the same cases() → options array for form selects, table filters, and repeater sub-forms. Put it in a single static method on a small support class (or a Filament OptionProvider if available in your version) so that when you adopt a Tabler release with new icons, one function picks them all up:

final class IconOptions
{
    public static function all(): array
    {
        return collect(TablerIcon::cases())
            ->mapWithKeys(fn (TablerIcon $i) => [$i->value => $i->label()])
            ->sort()
            ->all();
    }
}

Codemod, file by file, behind normal PRs. A single find-and-replace across the repo is tempting but unreviewable. Convert Blade partials first (visually verifiable), then config (small, testable), then Filament option arrays, then controllers. Keep the old string form working via the helper's tryFrom fallback so half-migrated code doesn't break mid-rollout.

Wrap it, don't sprinkle it. Because the package is a single-maintainer, near-zero-adoption data dependency, treat the enum as vendored data, not an API. Reference it from one or two of your own classes (App\Support\Icon, IconOptions), and have the rest of the app depend on those. Swapping to a generated enum — or to a different icon set entirely — then becomes a one-file change instead of a 200-file grep.

Gotchas and Tips

The enum version and your shipped icon assets are two independent sources of truth. This is the defect generator to watch. A case can exist in the enum but not in your installed Tabler CSS/sprite (icon renders blank, no exception), or vice versa. Mitigate with a single test that asserts every case appears in your icon manifest — parse the sprite/JSON manifest once, assertNotEmpty each. That test is worth more than the package itself.

Renames are the real breaking change, and they're silent. Tabler adds/icons between releases, but renames mean a case that still compiles and still autocompletes but now points at a deleted slug. Because the package exposes names only — no SVG data, categories, or weights — a wrong name fails at render time in the user's browser, not in CI. If an icon is load-bearing (nav, primary actions), keep a short list of "must render" icons in a feature test that hits a page and asserts the class is present.

Pin the package version alongside your Tabler version. Document the mapping (e.g. "enum 2.0.x ↔ Tabler 3.2x ↔ Filament 5") in your composer.json comment or a README note. Without a recorded mapping, the next person to composer update can move one side without the other.

Don't bundle this with a Filament major upgrade. The 2.0.1 release note is literally "Filament 5" — the package major tracks the Filament major. Upgrade Filament first, confirm panels work, then adopt this. Doing both at once makes any visual regression unattributable.

label() may not be what you want in the UI. For a Filament select, a humanised label ("Brand Github") is fine; for a picker showing thousands of icons, users search by slug ("github"). Check the helper's output and consider showing both, or using ->value as the search key with label() as display. Filament's searchable() matches on the option label, so this matters.

Thousands of cases = IDE and static-analysis tax. A flat enum of the full Tabler set is fine at runtime (opcache-resident) but slows PhpStan/PHPStorm indexing and makes the "Go to symbol" list noisy. Don't fight it — just don't be surprised, and don't let anyone add per-case methods to that enum file.

Check whether it's a backed enum before writing ->name vs ->value. Your mapping code differs, and mixing the two across a codebase ($case->name in one place, ->value in another) produces icons that work in one code path and not another. Pick one convention and put it in the helper.

No runtime metadata — plan around it. If a screen needs icon categories, previews, or search-as-you-type across SVG paths, this enum gives you nothing; you need the underlying Tabler manifest shipped as JSON (or a DB table). Use the enum for selection, the manifest for browsing.

Build-vs-buy: keep the escape hatch warm. Generating the same enum from the Tabler repo is roughly half a day to a day plus a CI check. With one star and zero dependents, the governance argument for forking into app/Support/ is stronger than for most dependencies — and the wrapper pattern above makes that a one-day, one-file change whenever you decide to. If composer.lock churn ever becomes noisy, vendor it and move on; there is nothing here worth a committee.

Verify license/attribution if you redistribute. MIT, so fork-and-patch is legally clean; keep the upstream attribution if you ship the generated enum inside a package or template you distribute.

Debugging shortcut. If an icon doesn't render, check in this order: (1) does the enum case's value match a slug in your installed Tabler version, (2) is the ti ti- prefix present exactly once (double-prefixing is a common wrapper bug), (3) is the CSS/sprite actually loaded on that route. Three checks, thirty seconds — worth putting in the team README alongside the codereview rule that icon references must be enum cases, not strings.

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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
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