Blade components let you extract a reusable piece of markup — a button, a card, an alert box — into its own file, called like an HTML tag, with data passed in as attributes.
Creating a component
php artisan make:component Alert
This generates two files: app/View/Components/Alert.php (the class, if class-backed) and resources/views/components/alert.blade.php (the markup).
Passing data in
// app/View/Components/Alert.php
class Alert extends Component
{
public function __construct(public string $type = 'info') {}
public function render(): View
{
return view('components.alert');
}
}
{{-- resources/views/components/alert.blade.php --}}
<div class="alert alert-{{ $type }}">
{{ $slot }}
</div>
Using it
<x-alert type="success">
Your changes have been saved.
</x-alert>
$slot captures whatever content is placed between the opening and closing tags — the same pattern as a native HTML element's children.
Anonymous components — no class needed
For simpler components that don't need constructor logic, a Blade file alone (no PHP class) works, using @props to declare accepted attributes with defaults:
{{-- resources/views/components/badge.blade.php --}}
@props(['color' => 'gray'])
<span class="badge badge-{{ $color }}">{{ $slot }}</span>
Anonymous components are the better default for markup-only reuse — reach for a class-backed component specifically when you need actual PHP logic (computed values, method calls) behind the component, not just prop pass-through.
Named slots for multi-part components
<x-card>
<x-slot:header>Order #{{ $order->id }}</x-slot:header>
Order details go here.
</x-card>
Named slots let a component accept multiple distinct content areas (a header and a body, for example), not just one undifferentiated block of slot content.