Skip to main content

php-laravel-blade-accessibility

Builds accessible server-rendered PHP/Laravel applications using Blade templates with accessible form patterns, Livewire integration, aria attributes, error announcements with alerts, and tools lens-for-laravel and laravel-blade-ally.

Informations de source

Dépôt
paulpas/agent-skill-router
Dernière activité de la source
23 septembre 2026 à 17:17
Langue détectée de SKILL.md
anglais
Étoiles
7
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
php-laravel-blade-accessibility
description
Builds accessible server-rendered PHP/Laravel applications using Blade templates with accessible form patterns, Livewire integration, aria attributes, error announcements with alerts, and tools lens-for-laravel and laravel-blade-ally.
license
MIT
compatibility
opencode
metadata
{"version":"1.0.0","domain":"coding","role":"implementation","scope":"implementation","output-format":"code","content-types":["code","patterns","examples"],"triggers":"PHP, Laravel, Blade, Livewire, accessible forms, aria attributes, lens-for-laravel, laravel-blade-ally","related-skills":"semantic-html-aria-accessibility-tree, automated-a11y-testing-axe-core","archetypes":["tactical","implementation"],"anti_triggers":["React framework","Vue framework","client-side rendering only","backend database"],"response_profile":{"verbosity":"low","directive_strength":"high","abstraction_level":"operational"}}
# Laravel Blade Accessibility: Forms & Livewire Builds accessible server-rendered PHP/Laravel applications using Blade templates with proper form patterns, ARIA attributes (aria-invalid, aria-describedby), form validation with error announcements (role="alert"), and Livewire reactive patterns. Integrates lens-for-laravel and laravel-blade-ally tools for accessibility audits. Load when building Laravel forms, implementing Livewire components with ARIA, or ensuring server-rendered HTML accessibility. ## TL;DR Checklist - [ ] Use Blade form components with proper label associations - [ ] Add `aria-invalid` and `aria-describedby` to form inputs - [ ] Display validation errors with `role="alert"` for screen reader announcements - [ ] Use Livewire `wire:loading` with `aria-live="polite"` for loading states - [ ] Associate labels: `<label for="field-id">` - [ ] Group related fields with `<fieldset>` and `<legend>` - [ ] Use `lens-for-laravel` for accessibility analysis - [ ] Run `php artisan ally:analyze` (laravel-blade-ally) in CI/CD - [ ] Test forms with jest-axe for blade templates --- ## When to Use Use this skill when: - Building accessible forms in Laravel Blade - Implementing Livewire reactive components with form validation - Ensuring server-rendered HTML meets WCAG 2.1 AA - Adding ARIA attributes to form fields - Setting up accessibility testing for Laravel projects - Building validation feedback with screen reader support --- ## When NOT to Use Avoid this skill for: - React/Vue client-side rendering (use framework-specific skills) - Database design or backend logic (use data skills) - Laravel routing or controller logic beyond accessibility - CSS/styling concerns (use CSS skills) - Blade templating syntax (use Laravel docs) --- ## Core Workflow 1. **Create Form Component** — Build reusable Blade form components with labels 2. **Add ARIA Attributes** — Use aria-invalid, aria-describedby on inputs 3. **Implement Validation** — Show errors with role="alert" for announcements 4. **Integrate Livewire** — Add wire:loading, wire:target, aria-live 5. **Add Descriptions** — Link help text with aria-describedby 6. **Test with Tools** — Use lens-for-laravel and laravel-blade-ally 7. **Verify with axe** — Run automated testing on Blade output 8. **Screen Reader Test** — Manual test with VoiceOver/NVDA --- ## Implementation Patterns ### Pattern 1: Accessible Form Field Component ```blade {{-- resources/views/components/form/field.blade.php --}} @props([ 'name' => '', 'label' => '', 'type' => 'text', 'required' => false, 'error' => null, 'description' => null, 'value' => '', 'placeholder' => '', ]) @php $errorId = $name . '-error'; $descriptionId = $name . '-description'; $hasError = $error !== null; $describedBy = []; if ($description) { $describedBy[] = $descriptionId; } if ($hasError) { $describedBy[] = $errorId; } $ariaDescribedBy = count($describedBy) > 0 ? implode(' ', $describedBy) : null; @endphp <div class="form-field {{ $hasError ? 'form-field--error' : '' }}"> {{-- Label --}} <label for="{{ $name }}" class="form-field__label"> {{ $label }} @if ($required) <span aria-label="required" class="required-mark"> *</span> @endif </label> {{-- Input --}} <input id="{{ $name }}" name="{{ $name }}" type="{{ $type }}" value="{{ old($name, $value) }}" placeholder="{{ $placeholder }}" @required($required) aria-required="{{ $required ? 'true' : 'false' }}" aria-invalid="{{ $hasError ? 'true' : 'false' }}" @if ($ariaDescribedBy) aria-describedby="{{ $ariaDescribedBy }}" @endif class="form-field__input {{ $hasError ? 'form-field__input--error' : '' }}" /> {{-- Description --}} @if ($description) <p id="{{ $descriptionId }}" class="form-field__description"> {{ $description }} </p> @endif {{-- Error Message --}} @if ($hasError) <p id="{{ $errorId }}" class="form-field__error" role="alert"> {{ $error }} </p> @endif </div> ``` **Usage:** ```blade <form method="POST" action="/contact"> @csrf <x-form.field name="email" label="Email Address" type="email" required :error="$errors->first('email')" description="We'll never share your email with anyone else." /> <x-form.field name="message" label="Message" type="textarea" required :error="$errors->first('message')" /> <button type="submit">Send</button> </form> ``` ### Pattern 2: Form with Validation ```blade {{-- resources/views/contact.blade.php --}} <form method="POST" action="/contact" novalidate> @csrf {{-- Email Field --}} <div class="form-group"> <label for="email" class="form-label"> Email Address <span aria-label="required">*</span> </label> <input id="email" name="email" type="email" value="{{ old('email') }}" required aria-required="true" aria-invalid="{{ $errors->has('email') ? 'true' : 'false' }}" aria-describedby="{{ $errors->has('email') ? 'email-error' : null }}" class="form-input {{ $errors->has('email') ? 'form-input--error' : '' }}" /> @if ($errors->has('email')) <p id="email-error" class="form-error" role="alert"> {{ $errors->first('email') }} </p> @endif </div> {{-- Message Field --}} <div class="form-group"> <label for="message" class="form-label"> Message <span aria-label="required">*</span> </label> <textarea id="message" name="message" required aria-required="true" aria-invalid="{{ $errors->has('message') ? 'true' : 'false' }}" aria-describedby="{{ $errors->has('message') ? 'message-error message-hint' : 'message-hint' }}" class="form-textarea {{ $errors->has('message') ? 'form-textarea--error' : '' }}" >{{ old('message') }}</textarea> <p id="message-hint" class="form-hint"> Maximum 1000 characters </p> @if ($errors->has('message')) <p id="message-error" class="form-error" role="alert"> {{ $errors->first('message') }} </p> @endif </div> {{-- Checkbox Field --}} <div class="form-group"> <input id="terms" name="terms" type="checkbox" required aria-required="true" aria-invalid="{{ $errors->has('terms') ? 'true' : 'false' }}" aria-describedby="{{ $errors->has('terms') ? 'terms-error' : null }}" /> <label for="terms" class="form-label"> I agree to the <a href="/terms" target="_blank">terms of service</a> </label> @if ($errors->has('terms')) <p id="terms-error" class="form-error" role="alert"> {{ $errors->first('terms') }} </p> @endif </div> <button type="submit" class="btn btn-primary"> Submit </button> </form> ``` ### Pattern 3: Livewire Form Component with ARIA ```php // app/Livewire/ContactForm.php namespace App\Livewire; use Livewire\Component; class ContactForm extends Component { public string $email = ''; public string $message = ''; protected array $rules = [ 'email' => 'required|email', 'message' => 'required|min:10|max:1000', ]; protected array $messages = [ 'email.required' => 'Please enter your email address.', 'email.email' => 'Please enter a valid email address.', 'message.required' => 'Please enter a message.', 'message.min' => 'Message must be at least 10 characters.', 'message.max' => 'Message must not exceed 1000 characters.', ]; public function submit() { $this->validate(); // Send email or save to database session()->flash('success', 'Your message has been sent!'); $this->reset(); } public function render() { return view('livewire.contact-form'); } } ``` ```blade {{-- resources/views/livewire/contact-form.blade.php --}} <form wire:submit="submit" novalidate> {{-- Status Message --}} @if (session('success')) <div class="alert alert-success" role="alert" aria-live="assertive"> {{ session('success') }} </div> @endif {{-- Email Field --}} <div class="form-group"> <label for="email" class="form-label"> Email Address <span aria-label="required">*</span> </label> <input id="email" wire:model="email" type="email" required aria-required="true" aria-invalid="{{ $errors->has('email') ? 'true' : 'false' }}" aria-describedby="{{ $errors->has('email') ? 'email-error' : null }}" class="form-input {{ $errors->has('email') ? 'form-input--error' : '' }}" /> @error('email') <p id="email-error" class="form-error" role="alert"> {{ $message }} </p> @enderror </div> {{-- Message Field --}} <div class="form-group"> <label for="message" class="form-label"> Message <span aria-label="required">*</span> </label> <textarea id="message" wire:model="message" required aria-required="true"
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub