mallardduck/blade-lucide-icons
Blade Lucide Icons lets you use any Lucide icon in Laravel Blade views as simple components like , with support for classes, inline styles, and raw SVG assets. Built on Blade Icons with configurable defaults and caching, requiring PHP 8.1+ and Laravel 8+.
Install via Composer (this release is the 2.x line — package v2.0.31, bundling Lucide icons 1.59.0):
composer require mallardduck/blade-lucide-icons --update
First Use Case: Replace a generic icon in your Blade view with a Lucide icon:
<!-- Before -->
<i class="fa fa-user"></i>
<!-- After -->
<x-lucide-user />
Key Starting Points:
lucide-user → <x-lucide-user />, lucide-user-check → <x-lucide-user-check />).php artisan vendor:publish --provider="BladeUI\Icons\BladeIconsServiceProvider" --tag="blade-icons-config"
Then set 'cache' => true in config/blade-icons.php.composer update, clear caches, done. From 1.x it's a major version jump (1.26.x → 2.0.x): budget a full cache clear and a visual smoke test of icons in critical views before shipping.Pattern: Use Lucide icons as Blade components with dynamic attributes:
<!-- Basic usage -->
<x-lucide-home class="text-blue-500 w-6 h-6" />
<!-- Attribute pass-through (width, height, stroke-width, aria-*) -->
<x-lucide-settings class="w-5 h-5" stroke-width="1.5" />
Workflow:
lucide.dev, then confirm the component resolves (php artisan view:cache will surface unknown components early).text-gray-400 hover:text-gray-600).w-* h-* over hardcoded width/height so icons scale consistently; the component respects attributes passed in.Pattern: Wrap icons in your own component when there's conditional logic:
{{-- resources/views/components/status-icon.blade.php --}}
@props(['status'])
<x-dynamic-component
:component="$status === 'active' ? 'lucide-check-circle' : 'lucide-x-circle'"
{{ $attributes->merge(['class' => 'w-4 h-4']) }}
/>
Use Case: Standardise status indicators, nav items, and buttons. Using <x-dynamic-component> (rather than string-concatenating <x-lucide-{{ ... }} />) is safer and lets you merge attributes.
Pattern: Publish the SVGs and use them where Blade components don't exist (JS, email bodies, PDFs):
php artisan vendor:publish --tag=blade-lucide-icons --force
<img src="{{ asset('vendor/blade-lucide-icons/activity.svg') }}" alt="Activity" width="24" height="24" />
Tip: Re-publish after every package update so the on-disk SVGs match Lucide 1.59.0 — otherwise emails/PDFs render stale artwork (and miss the 5 new icons).
Pattern: Publish the package config to set a default class and caching:
php artisan vendor:publish --tag=blade-lucide-icons-config
// config/blade-lucide-icons.php
return [
'class' => 'w-5 h-5 text-gray-500',
];
Result: All icons inherit w-5 h-5 text-gray-500 unless overridden per-usage. Keep this file in source control so upgrades don't silently overwrite your defaults.
Pattern: Drive icon names from data (database, CMS, enum):
@foreach($items as $item)
<x-dynamic-component :component="'lucide-'.$item->icon" class="w-4 h-4 mr-2" />
{{ $item->name }}
@endforeach
Tip: Store bare names (user, activity) in the DB, not lucide--prefixed strings. Validate them against an allow-list in a form request so bad data doesn't blow up rendering — x-dynamic-component throws on a missing component, whereas a plain <x-lucide-foo /> fails at compile time.
Caching After Upgrade:
composer update, run:
php artisan view:clear && php artisan config:clear && php artisan cache:clear
Icon Name Mismatches:
<x-lucide-userr />) or using an icon that was renamed/removed upstream in a Lucide major release.lucide.dev; rely on IDE completion via barryvdh/laravel-ide-helper or a Blade component index. Add a smoke test that renders every icon you reference.Silent Visual Drift on Patch Bumps:
SVG Asset Paths:
asset('vendor/blade-lucide-icons/...'). Note the publish path is package-relative — confirm the actual folder name in public/vendor/ after publishing.Build Pipeline:
php artisan vendor:publish --tag=blade-lucide-icons --force to your deploy script, or switch static contexts to inline SVG output.Missing Icons:
<svg> tags. No <svg> → the component name didn't resolve (typo or icon not in the set).Styling Not Applying:
stroke="currentColor" and no fill. Colour via text-* classes, not fill-*.text-{{ $color }}-500). Use full class names in a lookup map, or safelist them.Performance:
'cache' => true in config/blade-icons.php for production.@once-wrap inline SVGs or rely on the icon cache — inline SVG output inflates HTML payloads fast.Accessibility Regression:
aria-hidden="true"; meaningful ones need role="img" plus a <title> or a visually hidden label. Easy to lose when batch-replacing icons.Custom / Private Icons:
// config/blade-icons.php
'sets' => [
'default' => ['path' => 'resources/svg', 'prefix' => 'icon'],
'lucide' => ['path' => 'vendor/mallardduck/blade-lucide-icons/resources/svg', 'prefix' => 'lucide'],
],
Aliases / Compatibility Shims:
config/blade-icons.php) so views keep working without a find-and-replace across the codebase. Do this before deleting anything on a major bump.Dark Mode:
currentColor:
<x-lucide-moon class="text-gray-700 dark:text-yellow-300" />
Sizing Consistency:
w-4 h-4, w-5 h-5, w-6 h-6) in a component or config default, and never pass raw width/height inline — it keeps icon metrics uniform across the app.Tracking New Icons:
Pinning and Upgrade Cadence:
mallardduck/blade-lucide-icons to a caret range, run composer update on your schedule, and always follow with the cache-clear + re-publish steps above.Keeping the Assessment Honest:
composer.lock, not to marketing copy — and re-check this document whenever the package crosses a major boundary or a release flags modified icons.How can I help you explore Laravel packages today?