codeat3/blade-bytesize-icons
codeat3/blade-bytesize-icons provides ready-to-use Blade components for the Bytesize SVG icon library, letting Laravel developers render clean, scalable icons in views with simple tags, customize attributes, and avoid manually embedding SVG markup.
Install
composer require codeat3/blade-bytesize-icons
That's the whole setup. No service provider registration, no vendor:publish, no npm step, no asset pipeline change. It pulls in blade-ui-kit/blade-icons as the rendering engine and registers the Bytesize SVG set under the bytesize prefix.
Where to look first
The ground truth for icon names is the shipped SVG directory, not the README:
ls vendor/codeat3/blade-bytesize-icons/resources/svg | less
Names follow the upstream Bytesize set exactly, suffixed by the native size — check-16, check-24, check-32, arrow-bottom-16, ellipsis-horizontal-24. Cross-reference against the Bytesize gallery when you need a glyph you can't name. If you want to see how the prefix is wired up, the package's service provider is a dozen lines and worth a 30-second read.
First use case
The lowest-risk first move is replacing hand-pasted <svg> blobs in one existing layout — typically a nav bar or a form button:
<button type="submit" class="inline-flex items-center gap-2 …">
<x-bytesize-check-16 class="size-4" />
Save changes
</button>
Icons are inline SVG inheriting currentColor, so a text-* class on the parent (or on the icon) colors them. Confirm the render in a browser, then widen usage.
Direct component usage — fine for one-offs and layout chrome. Tailwind classes drive everything:
<x-bytesize-search-16 class="size-4 text-gray-400" />
<x-bytesize-close-24 class="size-6 hover:text-red-600" stroke-width="1.5" />
Arbitrary HTML attributes land on the root <svg>, so stroke-width, id, x-on:click, and aria-* all pass straight through.
Wrapper component from day one — the single highest-value pattern here. Never let x-bytesize-* appear in feature templates:
{{-- resources/views/components/app/icon.blade.php --}}
@props(['name', 'size' => 16])
<x-dynamic-component
:component="'bytesize-' . $name . '-' . $size"
{{ $attributes->merge(['aria-hidden' => 'true', 'focusable' => 'false']) }}
/>
Used as <x-app.icon name="check" :size="24" class="size-6" />. This gives you one place for accessibility defaults, one place to swap icon sets later, and a natural home for a name→glyph map when design renames things. Alternatively, for purely dynamic rendering, the Blade Icons directive is the cleanest path:
@svg('bytesize-' . $status->icon . '-16', 'size-4 shrink-0')
Data-driven icons — status badges, nav arrays, config-driven menus. Resolve the name in a small enum or config map, never by string-concatenating user input (a bad name throws Unable to locate a class or view for component [...] at render time, which is a 500 in production):
enum OrderStatus: string {
case Paid = 'check';
case Pending = 'clock';
case Refunded = 'reload';
public function icon(): string { return "bytesize-{$this->value}-16"; }
}
Composing into your own UI components — pass an icon name into <x-button> and render it inside, so button variants keep consistent icon sizing and spacing. This is where a package like this earns its keep: iconography becomes a prop, not a copy-paste.
Production caching — Blade Icons scans the SVG directory on every request unless cached. Add it to the deploy script:
php artisan icons:cache
and to your local/CI reset path (php artisan icons:clear) after a Composer update that changes the icon set. With three size variants per glyph this set registers a lot of components, so the cache is worth having.
Testing — one render assertion prevents an upstream rename from silently degrading your UI:
public function test_icon_component_renders(): void
{
$this->blade('<x-app.icon name="check" />')
->assertSee('<svg', false)
->assertSee('bytesize-check-16', false); // or assert the view/class name appears
}
Keep the assertion loose (root <svg>, expected class) rather than snapshotting the full markup — upstream SVG path data changes between releases and will make a strict snapshot flaky.
The name must be exact, including the size suffix. A typo doesn't degrade gracefully; it throws a component-resolution exception that surfaces as a 500. When debugging, ls the vendor SVG directory before assuming a caching bug.
Colors come from currentColor, and these are line icons. text-blue-600 works; fill="blue" on a stroke-based glyph does nothing. If an icon looks invisible, check the inherited text color first — a white icon on a white card is the classic afternoon-waster. Stroke weight is tuned with stroke-width, which inherits from the root <svg>.
Size suffix versus CSS size. -16/-24/-32 are drawn on different grids. Scaling -16 up to size-8 is possible but strokes go chunky and geometry gets blurry. Pick the nearest native size and scale modestly; use size-* (or w-*/h-*) for layout control, not as a substitute for picking the right variant.
class handling can surprise you. Because these are Blade Icons components, a class you pass is merged into the root <svg>, and blade-icons' own config (config/blade-icons.php) can set a global default class. If an icon renders at an unexpected size, check whether a project-wide default class is fighting your per-use class rather than assuming the package is broken.
Accessibility is not baked in. There's no <title>, no role="img", no aria-hidden by default. Decorative icons should get aria-hidden="true" (the wrapper above does this globally); meaningful standalone icons need role="img" plus aria-label="…" — an aria-label on an <svg> without role="img" is unreliably announced. If you need to inject <title> or restructure the inner markup, you can't do it through attributes; vendor the SVG into your own set or wrap it.
Production cache staleness. icons:cache writes to bootstrap/cache. After upgrading the package or adding an icon set, forgetting icons:clear means new icons 404 in staging while working perfectly on the developer's machine. Put the clear step in the same commit as the constraint bump.
Composer constraint coupling. 1.7.0 is a Laravel 13 compatibility release. Verify with composer why codeat3/blade-bytesize-icons and by inspecting the illuminate/support constraint: if it widened to allow your current major, you're fine; if it hard-pivoted to ^13, don't bump it on a Laravel 10–12 app. Also never run a blind composer update across a whole codeat3/blade-* family — several of these packages share blade-ui-kit/blade-icons, and resolving them independently during an unrelated framework bump is how a cosmetic dependency causes an incident. Pin ^1.7 and let the solver confirm.
Emails and PDFs. Inline SVG is stripped by Gmail/Outlook and rendered inconsistently by dompdf. For mail templates, substitute a PNG or host the icon as an image; don't assume the Blade component will survive the transport.
Inertia/Vue/React is out of scope. These components only exist server-side. If part of the app renders client-side, you still need the raw SVGs in the front-end build — extract them from the vendor directory rather than duplicating hand-drawn copies.
Icon density is a payload decision. Inline SVGs aren't shared between instances, so a per-row action icon in a 200-row table adds 200 copies of path data to the HTML. Fine for nav and forms; on dense tables or performance-budgeted public pages, consider a sprite sheet or rendering the icon in a cached partial. Decide at design time, not after a Lighthouse regression.
Extension points, in order of preference: override presentation with Tailwind/stroke-width attributes → wrap in <x-app.icon> so a future swap is a one-file change → register your own icon set via config/blade-icons.php for genuinely custom glyphs → fork as a last resort. Never edit anything under vendor/; the next composer install erases it.
How can I help you explore Laravel packages today?