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

Icons Laravel Package

artisanpack-ui/icons

An extensibility layer for registering custom SVG icon sets in Laravel, built on blade-ui-kit/blade-icons and integrates with Livewire UI Components. Configure sets via config or events, with no hardcoded icons, minimal memory use, and Font Awesome Pro support.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and publish the config

composer require artisanpack-ui/icons
php artisan vendor:publish --tag=artisanpack-package-config

This creates config/artisanpack/icons.php. Confirm you are pulling ^2.2 — earlier 2.x tags have a registration bug (see Gotchas).

2. Register at least one set. The package ships no icons at all; it only wires directories into blade-ui-kit/blade-icons. You must supply the SVGs yourself (Font Awesome Pro, Heroicons, your own brand marks, etc.):

// config/artisanpack/icons.php
return [
    'sets' => [
        'fa' => [
            'path'   => resource_path('icons/fontawesome-pro'),
            'prefix' => 'fa',
        ],
    ],
];

3. Drop the SVGs in. One file per icon, filename = icon name:

resources/icons/fontawesome-pro/home.svg
resources/icons/fontawesome-pro/user.svg

4. Render in Blade:

<x-icon-fa-home class="w-6 h-6" />
<x-icon-fa-user class="w-5 h-5 text-blue-500" />

The component name is icon-{prefix}-{filename}, and subdirectories become dash segments (solid/home.svg → <x-icon-fa-solid-home />).

Where to look first: docs/guide/installation.md → docs/guide/usage-examples.md. Only read docs/guide/extension-api.md if you are shipping a package that contributes icons to other apps. Do not follow any v1.x tutorial you find — v2.0 deleted the Icons class, the @apIcons directive, the helper functions, and the asset-serving routes entirely.

Your first real use case is almost always the same: you have an icon font (<i class="fa fa-home">) or a hardcoded PHP icon array, and you want icons as inline SVG components that Tailwind can size and color with class="w-6 h-6 text-blue-500" and that don't require a webfont request or a Font Awesome license file at runtime.

Implementation Patterns

Config registration — the default. One set per visual domain rather than one giant set. It keeps prefixes collision-free and lets you swap a library without touching templates:

'sets' => [
    'fa'    => ['path' => resource_path('icons/fontawesome-pro'), 'prefix' => 'fa'],
    'brand' => ['path' => resource_path('icons/brand'),          'prefix' => 'brand'],
    'ui'    => ['path' => resource_path('icons/ui'),             'prefix' => 'ui'],
],

Event-driven registration — for packages and reusable modules. This is the package's actual reason to exist over plain blade-icons. Register in a service provider's boot() (not register() — the hooks provider and config aren't ready):

use ArtisanPackUI\Icons\Registries\IconSetRegistration;

public function boot(): void
{
    addFilter('ap.icons.registerIconSets', function (IconSetRegistration $registry) {
        if (is_dir(__DIR__ . '/../resources/icons')) {
            $registry->addSet(__DIR__ . '/../resources/icons', 'mypackage');
        }

        return $registry;
    });
}

Always return $registry; — the filter is a pipeline and dropping the return value silently kills every subsequent subscriber.

Wrap the raw component behind your own icon component. This is the pattern that pays off day-to-day. Templates bind to a semantic name, not a library prefix, so swapping Font Awesome Pro for a free set is a one-file change:

{{-- resources/views/components/icon.blade.php --}}
@props(['name', 'set' => 'fa'])

<x-dynamic-component :component="'icon-' . $set . '-' . $name" {{ $attributes }} />
<x-icon name="home" class="w-6 h-6" />
<x-icon name="logo" set="brand" class="w-8 h-8" />

Mix with blade-icons' native sets freely. Both layers register into the same BladeUI\Icons\Factory, so <x-heroicon-o-user /> and <x-icon-fa-home /> coexist in one template. Install blade-icons sets directly for generic UI glyphs and reserve this package for licensed/custom collections.

Guard optional or licensed sets. Wrap registration in is_dir() or an env flag so a checkout without the proprietary SVGs (CI, a fresh clone, an OSS mirror) still boots:

if (config('app.has_fa_pro') && is_dir(resource_path('icons/fontawesome-pro'))) { ... }

Livewire. Nothing special required — the SVG is inlined server-side during render, so icons survive morphing. Prefer them in the Blade view over passing icon markup through component state.

Testing. Assert on rendered markup or on the component resolving, since a bad prefix/path fails at render time:

$this->get('/')->assertSee('<svg', false);
$this->blade('<x-icon-fa-home />')->assertSee('svg');

Gotchas and Tips

The hook was renamed in 2.2.0. ap.icons.register-icon-sets → ap.icons.registerIconSets. The old name is a deprecation alias: it still fires but logs at info level on every boot. If your logs are noisy with deprecation entries, that's this. Migrate the string; the alias disappears in the next major.

Never pin below 2.1.2. In earlier builds IconSetRegistration::addSet() stored only path and dropped prefix, so Factory::add() threw CannotRegisterIconSet::prefixNotDefined — and because registration happens early, this broke every <x-...> render in apps that also had owenvoke/blade-fontawesome installed. Require ^2.2.

Prefix collisions are silent-until-they-aren't. blade-fontawesome already claims fa, fas, far. If you install both, pick something like fapro for this package rather than fa. Colliding prefixes mean whichever registers last wins and icons randomly render wrong or not at all.

Config caching bakes in absolute paths. The published config uses resource_path() / base_path(), so php artisan config:cache freezes the release directory into the cache. With symlink-swapping deploys (Envoyer, Deployer) this points at a stale release. Either re-run config:cache after the symlink swap, or move path resolution into a service provider and keep only logical set names in the config file.

Missing icons throw, they don't fall back. blade-ui-kit/blade-icons raises BladeUI\Icons\Exceptions\SvgNotFound for an unknown name — there is no "render a placeholder" behavior. If a name comes from user input or CMS content, resolve it defensively (@php try { ... } @endphp or a helper that returns a default name) rather than letting a template 500.

File naming is the API. home.svg → home; arrow-left.svg → arrow-left; solid/home.svg → solid-home. Underscores, capitals, and stray dots will bite you. Keep filenames lowercase kebab-case and treat renames as breaking changes to your templates.

Clean the SVGs you drop in. Strip hardcoded width/height and fill="#000" so class="w-6 h-6 text-blue-500" actually controls size and currentColor inheritance works. Attributes passed to the component are merged onto the root <svg>, so class needs a merged (not replaced) class attribute inside the file — verify with one icon before bulk-copying 800.

Registrations happen at boot, not per-request discovery. Adding SVG files to a directory after deploy doesn't need a restart, but if you enabled any blade-icons caching layer, clear it (icons:clear, view:clear) — otherwise new files appear "missing" while cached ones render fine.

Extension points beyond addSet(). If IconSetRegistration lacks what you need (per-set default attributes, conditional sets), do it at the wrapper-component level rather than subclassing the registry — the class is small and its shape has changed twice in three minor releases.

Maturity check before betting on it. Zero stars, zero dependents, and two breaking API changes (2.0 architecture, 2.1 hooks migration) inside a year. Pin a version, read changelog/ before every composer update, and keep the fallback of plain config/blade-icons.php in mind: if you only ever need config-based sets and nothing else registers into them, this package is thin glue you could replace in one afternoon. It earns its keep only when third-party packages need to contribute icon sets without you editing config.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package