themesberg/flowbite-blade-icons
A Laravel Blade package for Flowbite Icons. Use self-closing components like with Tailwind classes or inline styles, or the @svg directive. Includes outline and solid sets, publishable config, and icon caching. Requires PHP 8.1+ and Laravel 9+.
Install and render your first icon (2 minutes).
composer require themesberg/flowbite-blade-icons
There is no setup step, service provider registration, or asset build. The package ships a pre-registered icon set through blade-ui-kit/blade-icons, so once Composer finishes you can drop an icon straight into any Blade view:
<x-fwb-o-adjustments-horizontal class="w-6 h-6 text-gray-500" />
That is the whole first use case — replace a placeholder icon or <img> tag in an existing view with a Flowbite component and inspect it in the browser. The naming convention is the only thing to memorize:
fwb-o-* → outline variantfwb-s-* → solid variantadjustments-horizontal, arrow-right, x-company, …)Where to look first.
resources/svg in the repo is the authoritative list of what actually exists. It is more reliable than guessing names from the Flowbite website, because kebab-casing and variant prefixes drift between the two.blade-ui-kit/blade-icons README — this package is a thin icon set on top of it. Everything beyond "render an SVG" (default classes, default attributes, caching, @svg options, fallbacks) is Blade Icons' API, not this package's.CHANGELOG.md / releases — small package, handful of releases; the notable one for day-to-day use is v1.2.1–v1.2.2, which moved fill/stroke to currentColor.Second command worth running immediately if you want defaults:
php artisan vendor:publish --tag=flowbite-blade-icons-config
This gives you config/flowbite-blade-icons.php for setting default classes and attributes so you aren't repeating class="w-5 h-5" on every icon. Publish it on day one rather than scattered through a codebase later.
Also worth doing on day one: decide icon sizing. These SVGs carry a viewBox but no intrinsic width/height, so an icon with no class will render at an unpredictable size. Pick a convention (w-5 h-5 for inline, w-6 h-6 for nav, w-8 h-8 for empty states) and encode the common case as a default in the config.
{{-- Navigation --}}
<a href="{{ route('dashboard') }}" class="flex items-center gap-2">
<x-fwb-o-home class="w-5 h-5" />
<span>Dashboard</span>
</a>
{{-- Conditional variant swap, no template duplication --}}
<x-fwb-{{ $active ? 's' : 'o' }}-star class="w-5 h-5 {{ $active ? 'text-yellow-400' : 'text-gray-400' }}" />
The dynamic-prefix trick (fwb-{{ $active ? 's' : 'o' }}-star) is the single most useful pattern in this package — it's how you do "filled when active, outline when not" without duplicating markup. It works because Blade resolves the component name as a string before compiling.
@svg directive for programmatic / looped renderingUse the directive when the icon name is data, not markup:
@foreach ($navItems as $item)
<a href="{{ $item['url'] }}">
@svg($item['icon'], 'w-5 h-5 text-gray-600', ['aria-hidden' => 'true'])
</a>
@endforeach
@svg($name, $class, $attributes) takes the same fully-qualified icon name (fwb-o-...). This is the escape hatch for config-driven menus, CMS-managed navigation, or a $icon column in a database. Note the second argument is a single class string, not an array.
Don't let raw x-fwb-* tags leak into 200 views. Wrap them once:
{{-- resources/views/components/icon.blade.php --}}
@props(['name', 'variant' => 'o', 'size' => 'md'])
@php
$sizes = ['sm' => 'w-4 h-4', 'md' => 'w-5 h-5', 'lg' => 'w-6 h-6', 'xl' => 'w-8 h-8'];
@endphp
<x-dynamic-component
:component="'fwb-' . $variant . '-' . $name"
{{ $attributes->merge(['class' => $sizes[$size]]) }}
aria-hidden="true"
/>
Then everywhere: <x-icon name="trash" variant="s" size="lg" class="text-red-600" />. This buys you a single place to change sizes, add aria-hidden, or swap the underlying icon library later — which matters given this package's low adoption (8 stars).
Since v1.2.1/v1.2.2 the SVGs use currentColor for fill and stroke. That means text-* utilities control icon color, not fill-* or stroke-*:
<x-fwb-o-moon class="w-5 h-5 text-gray-600 dark:text-gray-300" />
You get automatic light/dark theming with zero extra CSS, and icons inherit color from parent text by default — useful inside buttons like <button class="text-white"><x-fwb-o-plus class="w-4 h-4"/> Add</button>. Avoid explicitly setting fill="..." or stroke="..." attributes on these components; you'll fight the currentColor convention. Exception: the icon set does contain some solid glyphs where an explicit override is intentional.
Blade components can't render in a PDF generator or an email client. Publish the raw files:
php artisan vendor:publish --tag=flowbite-blade-icons --force
Files land in public/vendor/flowbite-blade-icons/o-adjustments-horizontal.svg, usable anywhere:
<img src="{{ asset('vendor/flowbite-blade-icons/o-adjustments-horizontal.svg') }}"
width="16" height="16" alt="Settings">
Re-publish with --force after upgrading the package, or your raw assets silently pin to the old icon shapes.
Blade Icons scans the filesystem for icon files on render. In a request that renders 40 icons across a layout, that's measurable overhead. Cache it:
php artisan icons:cache
Add php artisan icons:clear to your deploy script's rollback path, and regenerate the cache after composer install in every deployment — the cache is a snapshot of the filesystem, and a cached manifest from before an upgrade will reference stale icons. This is the one performance item the package's own README calls out, and it's real for icon-dense dashboards.
Assert on the rendered SVG rather than on the component name:
$response = $this->get('/dashboard');
$response->assertSee('svg', false);
$response->assertSee('viewBox', false);
For a snapshot-style check of a specific view, assertSee('<svg', false) plus a class assertion is usually enough. If your test suite asserts on exact HTML, disable icon caching in the test environment — a cached manifest built in a different working directory can produce confusing "icon not found" failures on CI.
Sizing is not baked in. These SVGs have a viewBox but no width/height. An <x-fwb-o-x/> with no class renders at an unpredictable size depending on parent CSS. Always pass w-*/h-* or set a default in the published config. This is the #1 thing that makes first-time users think the package is broken.
Color comes from text-*, not fill-*. The currentColor migration (v1.2.x) means class="fill-blue-500" does nothing. Use class="text-blue-500". If you're on an old pinned version (pre-1.2.1), some icons still have hardcoded fill values and won't theme — upgrade.
Variant prefix is mandatory and easy to forget. <x-fwb-adjustments-horizontal/> (no o-/s-) will fail. There is no default variant; o and s are both required. In dynamic component names, that string concatenation is exactly where typos hide — consider a wrapper (Pattern 3) purely to validate the variant.
Missing icon names fail loudly by default. Blade Icons throws when it can't resolve an icon rather than rendering nothing. Good for catching typos in dev, bad for a CMS-driven $icon field where editors can enter garbage. Wrap dynamic names so you get a fallback instead of a 500:
@if (view()->exists('components.fwb-o-' . $name))
<x-dynamic-component :component="'fwb-o-' . $name" class="w-5 h-5" />
@else
<x-fwb-o-question-mark-circle class="w-5 h-5" />
@endif
(Check the Blade Icons docs for its own fallback option on the icon set, which may be simpler in your version.)
The config file is Blade Icons config, not this package's config. flowbite-blade-icons.php publishes defaults for this set; the broader blade-icons.php controls global behavior (sets, prefixes, caching, fallbacks). If a config change doesn't take effect, you're probably editing the wrong file. When in doubt, check which file php artisan vendor:publish actually produced.
Clear the icon cache after every composer update. artisan icons:cache writes a filesystem manifest. Deploy ordering matters: composer install → php artisan icons:cache. Run them out of order and you ship a manifest pointing at icons that no longer exist. Also clear it in local dev after adding a new icon to a custom set (less relevant here, since the set is vendored).
Renaming a set is a breaking change across your views. If you ever override the fwb prefix through Blade Icons config to avoid collisions with another package, every <x-fwb-*> in every view must change. Given this package's small maintainer base, aliasing via your own wrapper component (Pattern 3) is cheap insurance against needing to swap the icon library entirely one day.
Don't use this for anything but static iconography. The icons are compiled into Blade at build time; there's no client-side sprite or runtime lookup. If you need icons to appear in a Vue/Inertia component or an Alpine-driven interaction, either pass the rendered SVG down as a slot/prop or use the raw published files. For icon-heavy SPA surfaces, this package stops paying for itself past the Blade layer.
Extension point worth knowing: because it's just a Blade Icons set, you can register additional local SVG directories alongside it and use the same <x-...> syntax. That's how you handle the "we need one custom brand icon Flowbite doesn't ship" case without abandoning the package — add a resources/svg/custom set in blade-icons.php rather than hand-importing SVGs into views.
Maintenance reality check. Eight stars, a handful of releases, releases that are essentially "add support for the next Laravel version" (v1.1.0 → L11, v1.2.0 → L12, v1.4.0 → L13). It's a static asset dump; the lack of churn is expected and mostly harmless. But pin your version in composer.json rather than floating on * — and be aware that a Laravel major bump may lag. The upside: because it's a thin wrapper over blade-ui-kit/blade-icons (a much more active dependency), your actual risk is in the wrapper, not the engine, and swapping to Heroicons/Lucide later is a prefix-and-name search-and-replace against Pattern 3's wrapper.
How can I help you explore Laravel packages today?