codeat3/blade-ant-design-icons
Blade Ant Design Icons brings Ant Design's icon set directly into your Laravel Blade views. Render any icon with a simple Blade component, customize size, color, and classes, and keep markup clean and readable.
One command, no publish step, no config file:
composer require codeat3/blade-ant-design-icons:^1.10
Pin ^1.10 rather than a loose constraint — 1.10.0 is the release that carries the Laravel 13 compatibility bump, and 1.9.x is not constrained against it. Package discovery registers the components automatically; there is nothing to add to config/app.php and no vendor:publish tag worth running on a first pass.
Look here first, not at the README. The docs advertise <x-ant-design-icon name="home" />, but the shipped convention is a flattened tag. Confirm the truth in ten seconds:
ls vendor/codeat3/blade-ant-design-icons/resources/views/components | head -30
That directory listing is your icon inventory and your naming spec. Expect something like antdesign-home.blade.php, which renders as <x-antdesign-home />, with theme variants flattened into the name (home-filled, home-two-tone) rather than exposed as a theme prop.
First use case. Take one existing view with a pasted-in <svg> blob — a nav item, a delete button in a table row — and replace it:
<x-antdesign-delete class="w-4 h-4 text-red-600" />
Then immediately clear views, because stale compiled component views are the number one false "the package is broken" report:
php artisan view:clear
The sub-hour decision worth making on day one: don't call vendor tags from feature code. Put a project-local wrapper in front of it:
{{-- resources/views/components/icon.blade.php --}}
@props(['name', 'label' => null])
<x-dynamic-component
:component="'antdesign-' . $name"
{{ $attributes->merge(['class' => 'w-5 h-5 shrink-0']) }}
role="{{ $label ? 'img' : 'presentation' }}"
@if ($label) aria-label="{{ $label }}" @else aria-hidden="true" @endif
/>
Usage: <x-icon name="delete" class="text-red-600" />. This absorbs the documentation-vs-reality tag discrepancy once, gives you a single place to change defaults, and makes swapping the vendor a one-file edit instead of a template-wide find-and-replace.
Attribute passthrough is the whole API. These are anonymous components wrapping a static <svg>; anything you put on the tag lands on the root element via $attributes. That means sizing and colouring are pure Tailwind (or plain CSS), not package props:
<x-antdesign-setting class="w-5 h-5 text-gray-400 hover:text-gray-700" />
<x-antdesign-loading class="w-4 h-4 animate-spin" />
<x-antdesign-check-circle style="color: var(--brand-500)" />
Icon + label in a button. Let the wrapper handle accessibility so you never think about it per-call-site:
<button type="button" class="inline-flex items-center gap-2 rounded px-3 py-2">
<x-icon name="download" />
<span>Export</span>
</button>
{{-- icon-only: the label belongs on the interactive element's accessible name --}}
<button type="button" aria-label="Delete record">
<x-icon name="delete" class="text-red-600" />
</button>
Variant selection as a data concern. Rather than branching inside templates, resolve the tag name in one place — an enum or a small map — so a design change to "filled everywhere in the sidebar" is a single edit:
enum NavIcon: string
{
case Dashboard = 'appstore';
case Settings = 'setting';
case Reports = 'bar-chart';
}
<x-icon :name="NavIcon::Reports->value" />
Guard dynamic names with a manifest. <x-dynamic-component> throws at render time for an unknown tag — a hard 500, not a graceful fallback. If icon names ever come from the database, a CMS field, or user input, generate a whitelist at build time by scanning the vendor views directory and validate against it (in_array($name, $manifest, true) with a hardcoded fallback). Note that view()->exists('components.antdesign-' . $name) does not work here — components registered via an anonymous component path aren't resolvable through the components. view namespace. Use file_exists() against the vendor path or a committed manifest.
Naming discovery is an information problem, not an engineering one. Skip the README index and grep the source directory — names are flattened Ant Design identifiers, so loading-3-quarters style numeric segments exist and guessing is unreliable:
ls vendor/codeat3/blade-ant-design-icons/resources/views/components \
| grep -i arrow | sed 's/^antdesign-//; s/\.blade\.php$//'
Deployment. Keep php artisan view:cache in your deploy pipeline as you already do — components compile to plain PHP and are served from the cache — but capture the artifact size and CI cold-build delta before adopting, not after. Hundreds-to-thousands of extra view files is a real number, small but not zero.
Integration scope. Works in plain Blade, Livewire, and Inertia/React shells that render Blade. It does not help client-side rendered components — anything the frontend bundle draws should come from npm @ant-design/icons. Enforce that split explicitly, or you end up with two vocabularies for the same glyph and inconsistent visuals between an SSR page and a hydrated one.
<x-ant-design-icon name="home" /> is a description-level fiction; the shipped form is <x-antdesign-home />. Verify against the views directory before writing any internal documentation, and route everything through your wrapper so the discrepancy never reaches feature code or onboarding notes.php artisan view:clear after every composer update. Compiled component views are cached and survive a package version change. This is the single most common false alarm — an "icons disappeared after upgrade" ticket is almost always a stale view cache.fill="currentColor" is actually used. Outlined and filled icons almost always inherit colour. Two-tone icons carry a secondary fill, frequently a hardcoded hex, which will not respond to text-* utilities. Inspect one two-tone SVG before promising design that the secondary colour is themeable — if it isn't, either avoid two-tone in themed contexts or patch via the wrapper.blade-ui-kit/blade-icons against your own SVG directory in addition to this package — but give your own set a distinct prefix so the two vocabularies don't merge.antdesign- or unprefixed home component is a silent collision resolved by registration order. One icon source for server-rendered output.style, avoid the style="" escape hatch above and stick to classes.view:cache is where the cost lives, not requests. Anonymous components resolve lazily, so per-request startup is negligible even with a huge inventory. The measurable costs are the compiled-view artifact and CI build time — measure them, don't assume.composer why-not codeat3/blade-ant-design-icons and composer show codeat3/blade-ant-design-icons will tell you whether 1.10.0 widened illuminate/support or raised a floor that forces your framework version. That answer determines whether the icon bump and the Laravel upgrade are independent changes or a single bundled risk — and if they're bundled, land them in separate, revertible commits so a rendering regression and a framework regression stay distinguishable in production.<x-icon> component is your sole seam for default sizes, colour tokens, accessibility policy, vendor swapping, and icon-name validation. Invest the hours there rather than patching vendor files.How can I help you explore Laravel packages today?