[For Intermediate Users] Guide to Creating Reusable UI Parts with Blade Components
What You’ll Learn in This Article
- The basic structure and creation steps of Blade components
- Flexible design using Props and Slots
- Examples of color palettes considerate of color vision and ARIA roles
- Practical sample code and directory structure
- Accessibility checklist for improving usability
Target Audience
- Intermediate Laravel users who want to improve view maintainability
- Front‐end engineers aiming to deliver consistent UI in team development
- Developers who want to master accessible, reusable component design
Accessibility Level: ★★★★☆
Covers contrast‐ratio verification, ARIA attribute examples, and keyboard support
Introduction: Why You Need Blade Components
In large Laravel projects, you’ll often rewrite the same buttons, cards, and modals.
This view redundancy increases maintenance costs and bugs.
By using Blade components, you can define a UI part once and reuse it everywhere,
dramatically boosting development efficiency and code readability.
- Consistency: Prevent design drift, unify brand image
- Maintainability: Fixes in one place apply everywhere
- Readability: Simplified views that teammates easily understand
1. Component Directory Structure and Basic Files
Start with organizing your components under resources/views/components
(Laravel 9+ recommended):
resources/
└── views/
└── components/
├── button.blade.php
├── card.blade.php
├── form/
│ └── input.blade.php
└── layout/
└── app.blade.php
- components/: Generic parts (buttons, cards)
- components/form/: Form-related parts (inputs, labeled groups)
- components/layout/: Layout parts (headers, footers)
Organizing by folder keeps your growing component library easy to navigate.
2. Props & Slots Basics: Parameter Passing and Flexibility
2.1 Receiving Values via Props
{{-- resources/views/components/button.blade.php --}}
@props([
'type' => 'primary',
'url' => '#',
'label' => 'Button',
])
@php
$baseClass = 'px-4 py-2 rounded ';
$colors = [
'primary' => 'bg-blue-600 text-white hover:bg-blue-700',
'secondary' => 'bg-gray-200 text-gray-800 hover:bg-gray-300',
];
@endphp
<a href="{{ $url }}"
{{ $attributes->merge(['class' => $baseClass . ($colors[$type] ?? $colors['primary'])]) }}>
{{ $label }}
</a>
- Declare parameters with
@props
- Use
$attributes->merge()
to pass through extra classes or ARIA attributes
2.2 Flexible Content with Slots
{{-- resources/views/components/card.blade.php --}}
<div {{ $attributes->merge(['class'=>'border rounded-lg shadow-sm p-4']) }}>
@if (isset($header))
<div class="border-b mb-3">
{{ $header }}
</div>
@endif
<div class="mb-3">
{{ $slot }}
</div>
@if (isset($footer))
<div class="border-t pt-2 text-right">
{{ $footer }}
</div>
@endif
</div>
- Anything wrapped in
<x-card>…</x-card>
goes into{{ $slot }}
- You can pass
header
andfooter
slots via attributes
3. Color Palette & Contrast for Color Vision
Ensure WCAG 2.1 AA contrast ratio (≥4.5:1) for better accessibility:
Color Name | HEX | Contrast vs. White |
---|---|---|
Blue 600 | #2563EB |
6.8:1 |
Gray 200 | #E5E7EB |
12.5:1 |
Green 600 | #059669 |
7.2:1 |
- Use online tools to verify and adjust
- Guarantee distinguishability for buttons, links, and text
For dark mode, test inverted colors and use @media (prefers-color-scheme)
for ARIA support.
4. ARIA Roles, Keyboard Support & Screen-Reader Handling
4.1 ARIA Role Example
{{-- Inside a modal component --}}
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h2 id="modal-title">{{ $title }}</h2>
{{ $slot }}
</div>
role="dialog"
: Announce as a modalaria-modal="true"
: Disable background contentaria-labelledby
: Link to the title element
4.2 Keyboard Considerations
- Focus Trap: Loop Tab navigation within the modal
- Escape Key: Handle
@keydown.escape
to close - Ensure usability beyond visuals ♡
5. Practical Sample: Reusable Form Input Component
{{-- resources/views/components/form/input.blade.php --}}
@props([
'id',
'label',
'type' => 'text',
'name' => $id,
'value' => old($id, ''),
'required' => false,
])
<div class="mb-4">
<label for="{{ $id }}" class="block text-gray-700 mb-1">
{{ $label }}
@if ($required)
<span aria-hidden="true" class="text-red-500">*</span>
@endif
</label>
<input id="{{ $id }}"
type="{{ $type }}"
name="{{ $name }}"
value="{{ $value }}"
@if($required) required @endif
{{ $attributes->merge(['class'=>'w-full border rounded px-3 py-2']) }}
aria-required="{{ $required }}"
aria-describedby="{{ $id }}-error">
@error($name)
<p id="{{ $id }}-error" class="text-red-600 mt-1" role="alert">
{{ $message }}
</p>
@enderror
</div>
required
flag automatically adds the asterisk and ARIA attributesaria-describedby
links error messages
6. Summary & Instant Checklist
- Organize your directory structure for clarity
- Use Props & Slots for flexible, type-safe components
- Verify contrast ratios for color-vision accessibility
- Implement ARIA roles & keyboard support for full accessibility
- Library-ify common components and share across your team
By following these steps, you’ll build secure, accessible UI parts suitable for team development.
Start integrating Blade components today and experience the power of Laravel!