Skip to main content
Chapter 4 Blade Templating and Frontend Integration

Blade Components and Slots

18 min read Lesson 15 / 28

Reusable UI with Blade Components

Blade components let you build reusable UI elements with encapsulated logic and clean interfaces — similar to React or Vue components.

Anonymous Components

Create a file in resources/views/components/:

{{-- resources/views/components/alert.blade.php --}}
@props([
    'type' => 'info',
    'dismissible' => false,
])

@php
    $classes = match($type) {
        'success' => 'bg-green-100 text-green-800 border-green-300',
        'error' => 'bg-red-100 text-red-800 border-red-300',
        'warning' => 'bg-yellow-100 text-yellow-800 border-yellow-300',
        default => 'bg-blue-100 text-blue-800 border-blue-300',
    };
@endphp

<div {{ $attributes->merge(['class' => "p-4 rounded-lg border {$classes}"]) }}>
    {{ $slot }}
    @if($dismissible)
        <button onclick="this.parentElement.remove()">✕</button>
    @endif
</div>

Usage:

<x-alert type="success">Post published successfully!</x-alert>
<x-alert type="error" dismissible>Something went wrong.</x-alert>
<x-alert type="warning" class="mt-4">Please review your input.</x-alert>

Named Slots

{{-- resources/views/components/card.blade.php --}}
<div class="bg-white rounded-xl shadow-sm overflow-hidden">
    @isset($header)
        <div class="px-6 py-4 border-b">{{ $header }}</div>
    @endisset

    <div class="p-6">{{ $slot }}</div>

    @isset($footer)
        <div class="px-6 py-4 bg-gray-50 border-t">{{ $footer }}</div>
    @endisset
</div>
<x-card>
    <x-slot:header>
        <h2 class="text-lg font-semibold">User Profile</h2>
    </x-slot:header>

    <p>Main content goes here.</p>

    <x-slot:footer>
        <button class="btn-primary">Save Changes</button>
    </x-slot:footer>
</x-card>

Class-Based Components

For components with complex logic:

php artisan make:component PostCard
class PostCard extends Component
{
    public function __construct(
        public Post $post,
        public bool $showExcerpt = true,
    ) {}

    public function readingTime(): int
    {
        return ceil(str_word_count($this->post->body) / 200);
    }

    public function render(): View
    {
        return view('components.post-card');
    }
}

Components make your Blade templates composable and maintainable at scale.