7.9 KiB
7.9 KiB
Story 9.5: Component Styling - Forms
Epic Reference
Epic 9: Design & Branding Implementation
User Story
As a user, I want consistent, accessible form styling, So that data entry is intuitive and error states are clear.
Dependencies
- Story 9.1 (Color System) - Must be completed first; provides Tailwind color aliases used below
- Story 9.2 (Typography System) - Font weights for labels
Color Reference (from Story 9.1)
For quick reference, this story uses these colors defined in the Tailwind theme:
gold(#D4AF37) - Focus states, checkbox accentscharcoal(#2C3E50) - Default borders, label textdanger(#E74C3C) - Error statescream(#F9F7F4) - Input backgrounds (if needed)
Acceptance Criteria
Input Fields
- Border: Charcoal Gray (
border-charcoal/30) - Focus: Gold border with subtle ring (
focus:border-gold focus:ring-gold/20) - Border-radius: 6px (
rounded-md) - Padding: 12px 16px (
px-4 py-3)
Textareas
- Same styling as inputs
- Minimum height: 120px (
min-h-[120px])
Select Dropdowns
- Custom styled using Flux UI (not native browser)
- Consistent border/focus styling with inputs
Checkboxes & Radios
- Custom styled with gold accent when checked
- Clear visual distinction between checked/unchecked states
Labels
- SemiBold weight (
font-semibold) - Required indicator (*) in danger color
Error States
- Red border (
border-danger) - Error message displayed below field
- Error ring on focus (
focus:ring-danger/20)
RTL Support
- Labels align to the right in RTL mode
- Input text direction follows locale
- Error messages align correctly
- Padding swaps appropriately (use
ps-4 pe-4instead ofpx-4if needed)
Files to Create/Modify
Primary Files
resources/css/app.css- Add form component utility classes
Flux UI Integration
Flux UI Free includes these form components that need styling customization:
flux:input- Text inputsflux:textarea- Multiline textflux:select- Dropdown selectsflux:checkbox- Checkboxesflux:radio- Radio buttonsflux:field- Field wrapper with label/error support
Existing Forms to Audit
Review and update existing forms in:
resources/views/livewire/- Any Volt components with forms- Authentication views (login, register, password reset)
- Contact/booking forms
Technical Implementation
CSS Classes (add to resources/css/app.css)
/* Form field styling */
.input-field {
@apply w-full border border-charcoal/30 rounded-md px-4 py-3
focus:border-gold focus:ring-2 focus:ring-gold/20
transition-colors outline-none bg-white;
}
.input-error {
@apply border-danger focus:border-danger focus:ring-danger/20;
}
.form-label {
@apply block text-sm font-semibold text-charcoal mb-2;
}
.form-label-required::after {
content: ' *';
@apply text-danger;
}
.error-message {
@apply text-sm text-danger mt-1;
}
/* Textarea specific */
.textarea-field {
@apply input-field min-h-[120px] resize-y;
}
/* Custom checkbox */
.checkbox-custom {
@apply w-5 h-5 rounded border-charcoal/30 text-gold
focus:ring-gold focus:ring-offset-0;
}
/* Custom radio */
.radio-custom {
@apply w-5 h-5 border-charcoal/30 text-gold
focus:ring-gold focus:ring-offset-0;
}
Flux UI Component Usage Examples
{{-- Basic input with label --}}
<flux:field>
<flux:label class="form-label">Email</flux:label>
<flux:input type="email" wire:model="email" class="input-field" />
</flux:field>
{{-- Required field with error --}}
<flux:field>
<flux:label class="form-label form-label-required">Name</flux:label>
<flux:input
wire:model="name"
class="input-field @error('name') input-error @enderror"
/>
@error('name')
<span class="error-message">{{ $message }}</span>
@enderror
</flux:field>
{{-- Textarea --}}
<flux:field>
<flux:label class="form-label">Message</flux:label>
<flux:textarea wire:model="message" class="textarea-field" />
</flux:field>
{{-- Select dropdown --}}
<flux:field>
<flux:label class="form-label">Category</flux:label>
<flux:select wire:model="category" class="input-field">
<flux:select.option value="">Select...</flux:select.option>
<flux:select.option value="legal">Legal</flux:select.option>
<flux:select.option value="general">General</flux:select.option>
</flux:select>
</flux:field>
{{-- Checkbox with gold accent --}}
<flux:field>
<flux:checkbox wire:model="agree" class="checkbox-custom" />
<flux:label class="form-label inline ms-2">I agree to the terms</flux:label>
</flux:field>
{{-- Radio group --}}
<flux:field>
<flux:label class="form-label form-label-required">Preferred Contact</flux:label>
<div class="flex gap-4 mt-2">
<label class="flex items-center gap-2">
<flux:radio wire:model="contact" value="email" class="radio-custom" />
<span>Email</span>
</label>
<label class="flex items-center gap-2">
<flux:radio wire:model="contact" value="phone" class="radio-custom" />
<span>Phone</span>
</label>
</div>
</flux:field>
RTL Considerations
- Use logical properties where possible (
ps-,pe-,ms-,me-instead ofpl-,pr-,ml-,mr-) - Flux components should handle RTL automatically with
dir="rtl"on the HTML element - Test label positioning in Arabic locale
Testing Requirements
Manual Testing Checklist
-
Visual Inspection (both locales)
- Switch to Arabic - verify RTL alignment
- Switch to English - verify LTR alignment
- All form elements match design specs
-
Interactive States
- Click into each field type - verify gold focus ring appears
- Tab through form - verify focus order is logical
- Submit with errors - verify error styling appears
-
Accessibility
- Labels are associated with inputs (clicking label focuses input)
- Error messages are announced to screen readers
- Focus indicators are clearly visible
Automated Tests
Create feature test for form styling verification:
// tests/Feature/FormStylingTest.php
test('form fields render with correct classes', function () {
// Test that forms include the expected CSS classes
$this->get('/contact')
->assertSee('input-field')
->assertSee('form-label');
});
test('form error states display correctly', function () {
// Submit form with invalid data and check error styling
Livewire::test('contact-form')
->set('email', 'invalid')
->call('submit')
->assertSee('input-error')
->assertSee('error-message');
});
Browser Testing (RTL Verification)
// tests/Browser/FormRtlTest.php
it('displays form labels on the right in RTL mode', function () {
visit('/ar/contact')
->assertPresent('[dir="rtl"]')
->assertVisible('.form-label');
// Visual inspection for alignment
});
Definition of Done
- CSS classes added to
resources/css/app.css - Input styling matches specs (border, focus, padding, radius)
- Textarea styling consistent with inputs, min-height 120px
- Select dropdowns styled consistently (not native)
- Checkboxes show gold accent when checked
- Radio buttons show gold accent when selected
- Labels are semibold with required indicator working
- Error states show red border and message below
- RTL alignment verified in Arabic locale
- LTR alignment verified in English locale
- Existing forms updated to use new classes
- Feature tests pass
- Code formatted with Pint
Estimation
Complexity: Medium | Effort: 3-4 hours
Dev Notes
- Check Flux UI docs for any built-in theming options before adding custom CSS
- If Flux components don't accept className props well, may need to use CSS selectors targeting Flux's rendered HTML
- Run
npm run buildafter CSS changes to see updates