@props(['type' => 'info', 'dismissible' => false])
@php
$classes = [
'info' => 'bg-blue-100 border-blue-500 text-blue-700',
'success' => 'bg-green-100 border-green-500 text-green-700',
'warning' => 'bg-yellow-100 border-yellow-500 text-yellow-700',
'error' => 'bg-red-100 border-red-500 text-red-700',
][$type];
@endphp
<div {{ $attributes->merge(['class' => "border-l-4 p-4 {$classes}"]) }} role="alert">
<div class="flex items-center justify-between">
<div class="flex-1">
@if (isset($title))
<p class="font-bold">{{ $title }}</p>
@endif
<div>{{ $slot }}</div>
</div>
@if ($dismissible)
<button type="button" class="ml-4" onclick="this.parentElement.parentElement.remove()">
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
<path d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"/>
</svg>
</button>
@endif
</div>
</div>
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Card extends Component
{
public function __construct(
public string $title,
public ?string $footer = null,
public bool $elevated = false,
) {}
public function render()
{
return view('components.card');
}
public function cardClasses(): string
{
return $this->elevated
? 'shadow-lg'
: 'shadow';
}
}
<div {{ $attributes->merge(['class' => "bg-white rounded-lg {$cardClasses()}"]) }}>
<div class="px-6 py-4 border-b">
<h3 class="text-lg font-semibold">{{ $title }}</h3>
@isset($subtitle)
<p class="text-sm text-gray-600">{{ $subtitle }}</p>
@endisset
</div>
<div class="p-6">
{{ $slot }}
</div>
@if ($footer)
<div class="px-6 py-4 bg-gray-50 border-t rounded-b-lg">
{{ $footer }}
</div>
@endif
</div>
{{-- Anonymous component --}}
<x-alert type="success" dismissible>
<x-slot name="title">Success!</x-slot>
Your post was published successfully.
</x-alert>
{{-- Class-based component --}}
<x-card title="Recent Posts" elevated class="mb-4">
<x-slot name="subtitle">Latest blog posts</x-slot>
@foreach ($posts as $post)
<article>{{ $post->title }}</article>
@endforeach
<x-slot name="footer">
<a href="{{ route('posts.index') }}">View all posts</a>
</x-slot>
</x-card>
Blade components create reusable, self-contained UI elements with their own logic and styling. Anonymous components are simple Blade files, while class-based components have PHP backing classes. I pass data via attributes—<x-alert type='success' />. Component classes accept constructor arguments for dependency injection. Slots enable flexible content insertion, with named slots for multiple content areas. The @props directive defines component properties with defaults. Components can render conditionally or loop over data. I use @aware to access parent component data. Attributes merge automatically with $attributes, preserving classes and other HTML attributes. Components promote consistency and reduce duplication across views.