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

Blade Eva Icons Laravel Package

hasnayeen/blade-eva-icons

Laravel Blade components for the Eva Icons set. Render crisp, scalable SVG icons in your views with simple Blade tags, customizing size, color, and CSS classes. Ships with the full Eva Icons library, so you can drop consistent, open-source icons into any Laravel app without copying SVGs by hand.

View on GitHub
Deep Wiki
Context7

Getting Started

One command, no publish step, no service provider registration:

composer require hasnayeen/blade-eva-icons

v2.2.0 is a Laravel 13 compatibility release — the API is unchanged, so every guide and Stack Overflow snippet you find for 2.x still applies. If you're on Laravel 13, pin ^2.2; on older frameworks ^2.2 is still fine and avoids a re-pin later.

Where to look first: the vendor view directory, not the docs. Component names are derived mechanically from filenames, and the README's icon list is the only authoritative mapping:

ls vendor/hasnayeen/blade-eva-icons/resources/views | head -40
ls vendor/hasnayeen/blade-eva-icons/resources/views | grep activity

Eva ships roughly 480 icons in two variants (outline and fill), and the variant suffix is part of the component name. Open one file if you need to see the raw <svg> root — it's a single path-based SVG with no width/height attributes.

First use case: don't call the package directly from feature views. Spend the first ten minutes creating one wrapper component and route everything through it — that's the decision you'll thank yourself for in six months when you swap icon sets or need a non-Eva glyph. See the wrapper below.

Minimal smoke test in any existing view:

<x-eva-icons-activity-outline class="w-6 h-6 text-indigo-600" />

If that renders nothing, you almost certainly dropped the -outline suffix (see Gotchas).

Implementation Patterns

Wrap once, use everywhere. The eva-icons- prefix leaking into hundreds of Blade files turns an icon-set swap into a grep-and-replace audit. One indirection removes that:

{{-- resources/views/components/ui/icon.blade.php --}}
@props(['name', 'variant' => 'outline', 'size' => 5])

<x-dynamic-component
    :component="'eva-icons-' . $name . '-' . $variant"
    {{ $attributes->merge(['class' => "w-{$size} h-{$size} shrink-0"]) }}
    aria-hidden="true"
/>

Call sites become <x-ui.icon name="activity" size="6" class="text-gray-400" />. Note shrink-0 — it prevents the collapse you get in flex rows without intrinsic dimensions.

Variant switching belongs in props, not call sites. Sidebar nav is the canonical case: outline for inactive items, fill for the active one.

<x-ui.icon :name="$item['icon']" :variant="$active ? 'fill' : 'outline'" />

This is the reason to wrap — otherwise every nav item has two component names branching on state, and the diff for a design tweak touches every link.

Prefer -fill at small sizes. Eva's outline strokes get thin and muddy below roughly 20px. Practical rule: outline for decorative and nav-scale icons, fill for status dots, badges, table cells, and anything rendered at w-4 or below.

Colour with currentColor, never with fill props. Eva icons are paths, so Tailwind text-* utilities on the wrapper drive the colour. That means hover:text-*, group-hover:, and dark: variants come free from your existing utilities — passing fill="#ef4444" breaks all three at once.

Map status to icons, don't inline conditionals. Repeated ternary chains inside table rows are the main readability cost of icon-heavy UIs:

@php
$statusIcon = match ($status) {
    'success' => ['checkmark-circle-2', 'text-green-600'],
    'error'   => ['alert-circle', 'text-red-600'],
    default   => ['info', 'text-gray-500'],
};
@endphp

<x-ui.icon :name="$statusIcon[0]" variant="fill" :class="$statusIcon[1]" />

Hoist that map into a helper or enum method once it appears in more than two views.

Accessibility is the default, not an afterthought. Inline SVGs carry no accessible name. aria-hidden="true" on the wrapper handles decorative icons; for icon-only buttons, the label goes on the button:

<button type="button" aria-label="Delete project" class="...">
    <x-ui.icon name="trash-2" size="4" />
</button>

Compile the views on deploy. Each icon is a Blade view; php artisan view:cache after composer install is what makes repeated rendering cheap. Add php artisan view:clear to your rollback path.

Prototyping payoff. Because there's no npm/Vite footprint and no sprite pipeline, this is the fastest way to get real icons into an internal tool, admin panel, or MVP. Reach for it when icon fidelity is low-stakes; reach for a design-system SVG pipeline when it isn't.

Gotchas and Tips

The variant suffix is mandatory. <x-eva-icons-activity /> resolves to nothing — it's activity-outline or activity-fill. This is the number one cause of "component not found" in this package. Note that some third-party write-ups show an <x-eva-icon name="..." /> form; treat the vendor view filenames as ground truth and let your wrapper absorb the difference.

No default dimensions on the SVG root. An icon in a flex row without explicit sizing will stretch or collapse unpredictably. Always land w-* h-* or explicit width/height — centralising it in the wrapper is the entire justification for the wrapper.

Attribute merging is where classes go wrong. $attributes->merge() on the inner component lets caller classes win over defaults safely. Mixing an outer class prop with an inner merge() can produce duplicate or conflicting utilities that look fine until a hover state stops firing. Use merge() for defaults-plus-overrides, $attributes->class() when you only want to append conditional classes.

Repeated icons repeat markup. There's no deduplication — a 100-row table with a status icon ships 100 inline SVGs. Gzip absorbs most of it, but if a page's HTML weight jumps noticeably, that's the cause, not a bug. Paginate or virtualise before you optimise the icons.

Stale view cache is the debugging trap. After composer update, a cached compiled view can mask a renamed or missing icon. Symptom: renders locally, empty string in production. Run php artisan view:clear before you start reading package source.

Laravel 13 requires 2.2.0. ^2.1 fails dependency resolution on Laravel 13. The change is a composer constraint only — no API breaks, no deprecations, nothing to migrate — so pinning ^2.2 on Laravel 10/11/12 as well is free and eliminates a future upgrade ticket.

There is no config file. No alias table, no name remapping, no per-icon overrides. Your <x-ui.icon> wrapper is the extension point. When you need a non-Eva glyph (brand marks, product logos), register a normal Blade component and fall through to it:

@if ($name === 'github')
    <x-icons.github {{ $attributes }} />
@else
    <x-dynamic-component :component="'eva-icons-'.$name.'-'.$variant" ... />
@endif

The upstream icon set is effectively frozen. Eva Icons is in maintenance mode; this package will get compatibility patches, not new glyphs. Don't promise a design team that a missing icon will arrive later — plan to vendor custom SVGs yourself.

Test the accessible outcome, not the path data. assertSee('aria-label="Delete project"', false) survives package updates; assertSee('<svg') doesn't, because the markup belongs to the package and can change on any minor. If you must assert an icon rendered, target the class your wrapper adds.

No JavaScript, no client-side runtime. Icons are server-rendered at request time. That's a feature for Blade apps and a hard blocker for SPA front ends — use the native eva-icons npm package there instead.

Contributor/maintenance context. v2.2.0 is a single-framework-constraint PR from a first-time contributor. Nothing to migrate, no config changes. Treat the package as stable commodity infrastructure with an exit path: if you later need tree-shaken per-icon delivery or custom iconography, migrating to blade-ui-kit/blade-icons with local SVG sets is contained to your wrapper if you built it on day one.

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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log