Blade Components for Reusable UI

Copy-pasting the same chunk of HTML across many pages is a source of bugs and repetitive work. Blade components solve this: you define a piece of UI once, then use it anywhere like...

Blade Components for Reusable UI

Copy-pasting the same chunk of HTML across many pages is a source of bugs and repetitive work. Blade components solve this: you define a piece of UI once, then use it anywhere like a normal HTML tag. This article covers how to build genuinely reusable UI components in Laravel 10/11 — from a simple alert to flexible buttons and cards.

1. Two Kinds of Components

Laravel has two types of Blade components:

  • Class components — have a PHP class for logic (computing values, queries, etc.) plus a view file. Ideal for components that need processing.
  • Anonymous components — just a Blade file, no class. Ideal for purely presentational components like buttons or cards.

2. Creating a Class Component

Use artisan to create an alert component:

php artisan make:component Alert

This produces two files: the class app/View/Components/Alert.php and the view resources/views/components/alert.blade.php. Define properties in the constructor:

class Alert extends Component
{
    public function __construct(
        public string $type = 'info',
        public string $message = '',
    ) {}

    public function render(): View
    {
        return view('components.alert');
    }
}

Fill in the view, using the properties you just defined:

<div class="alert alert-{{ $type }}">
    {{ $message }}
</div>

Use it on any page with the x- syntax:

<x-alert type="success" message="Data saved successfully." />

3. Anonymous Components with @props

For components with no logic, just create a Blade file — no class. Create resources/views/components/card.blade.php and declare its properties with the @props directive:

@props(['title' => null])

<div class="card">
    @if ($title)
        <div class="card-header">{{ $title }}</div>
    @endif
    <div class="card-body">
        {{ $slot }}
    </div>
</div>

@props registers which attributes are "props" (with default values); the rest fall into the attribute bag we discuss later.

4. Slots: Passing HTML Content

Notice {{ $slot }} above. A slot is where the content between the component tags is rendered. Now the card component can wrap anything:

<x-card title="User Profile">
    <p>Name: Budi</p>
    <p>Email: budi@mail.com</p>
</x-card>

Named Slots

Need more than one content area? Use named slots. Define them in the component:

@props(['title' => null])

<div class="card">
    <div class="card-header">{{ $title }}</div>
    <div class="card-body">{{ $slot }}</div>
    <div class="card-footer">{{ $footer ?? '' }}</div>
</div>

Then fill them with x-slot tags:

<x-card title="Summary">
    Main content goes here.

    <x-slot:footer>
        <button>Save</button>
    </x-slot:footer>
</x-card>

5. The Attribute Bag: Forwarding HTML Attributes

What if the component's user wants to add a class or other attribute? Laravel collects every attribute not registered in @props into the $attributes variable. Use merge() so custom classes combine with the defaults:

@props(['type' => 'primary'])

<button {{ $attributes->merge(['class' => 'btn btn-'.$type]) }}>
    {{ $slot }}
</button>

Now the button component can accept extra attributes seamlessly:

<x-button type="danger" class="w-full" onclick="remove()">
    Delete
</x-button>

As a result, the w-full class and the onclick attribute automatically attach to the button tag without you declaring them. For attributes that should be overridden rather than merged, use $attributes->class([...]).

6. Class vs Anonymous: When to Use Which

  • Use anonymous components for purely presentational elements (button, card, badge, input) — they are lighter and @props is enough.
  • Use class components when you need logic: fetching data from the database, formatting values, or choosing a variant based on complex conditions. You can also add public methods callable directly in the view.

Example of a method on a class component:

public function isDanger(): bool
{
    return $this->type === 'danger';
}
@if ($isDanger())
    <strong>Warning!</strong>
@endif

Conclusion

Blade components change how you build interfaces: instead of copying HTML, you create a consistent, maintainable component library. Start with anonymous components for simple elements, graduate to class components when you need logic, use slots for content flexibility, and the attribute bag to keep components open for customization. Once built cleanly, these components speed up every new page you create.

Yudhi
Written by
Yudhi
Founder & Lead Developer, GudangCode

Yudhi is the founder of GudangCode and a Laravel developer who has built dozens of ready-to-use business information systems — from POS and HRIS to management apps. He writes guides and articles on GudangCode to help Indonesian developers run, understand, and deploy Laravel source code correctly.

LaravelPHPMySQLSistem Informasi Bisnis See all articles by Yudhi
Want the full source code & apps?

Sign up free to download ready-to-use business applications, information systems, and Laravel source code.

Sign Up Free & Download
Blade Component Laravel Programming & Laravel
Share this article
Back to Blog
📚 Free Learning Hub

Learn Coding for Free at DhieCoderWeb

Explore Laravel, PHP, JavaScript tutorials, source code, web development guides, and practical programming tips.

DhieCoderWeb
100+
Tutorials
Free
Learning
SEO
Tips
Visit Dhiecoderweb.com →

Get Full Access Now!

Join our membership and unlock exclusive access to all premium features. Fast, easy, and ready to use instantly.

Join Membership Now
Tim Support
Online
Isi data dulu untuk mulai chat:
Beri rating & testimoni sebelum menutup:
Live chat by gudangcode.com