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.

Informações da origem

Repositório
paulpas/agent-skill-router
Última atividade na origem
23 de setembro de 2026 às 17:17
Idioma detectado do SKILL.md
inglês
Estrelas
6
Forks
0

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
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"
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub