libra/docs/stories/story-9.5-component-styling...

14 KiB

Story 9.5: Component Styling - Forms

Note: The color values in this story were implemented with the original Navy+Gold palette. These colors were updated in Epic 10 (Brand Color Refresh) to the new Charcoal+Warm Gray palette. See docs/brand.md for current color specifications.

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 accents
  • charcoal (#2C3E50) - Default borders, label text
  • danger (#E74C3C) - Error states
  • cream (#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-4 instead of px-4 if 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 inputs
  • flux:textarea - Multiline text
  • flux:select - Dropdown selects
  • flux:checkbox - Checkboxes
  • flux:radio - Radio buttons
  • flux: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 of pl-, 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

  1. Visual Inspection (both locales)

    • Switch to Arabic - verify RTL alignment
    • Switch to English - verify LTR alignment
    • All form elements match design specs
  2. 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
  3. 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 build after CSS changes to see updates

Dev Agent Record

Status

Ready for Review

Agent Model Used

Claude Opus 4.5

File List

Modified:

  • resources/css/app.css - Added form styling system CSS classes and Flux UI component styling
  • resources/views/livewire/admin/clients/individual/create.blade.php - Updated labels with required class
  • resources/views/livewire/admin/clients/individual/edit.blade.php - Updated labels with required class
  • resources/views/livewire/admin/clients/company/create.blade.php - Updated labels with required class
  • resources/views/livewire/admin/clients/company/edit.blade.php - Updated labels with required class
  • resources/views/livewire/admin/posts/create.blade.php - Updated labels with required class
  • resources/views/livewire/admin/posts/edit.blade.php - Updated labels with required class
  • resources/views/livewire/admin/timelines/create.blade.php - Updated labels with required class
  • resources/views/livewire/client/consultations/book.blade.php - Updated problem summary label with required class

Created:

  • tests/Feature/FormStylingTest.php - Feature tests for form styling verification

Change Log

  1. Added comprehensive form styling system to resources/css/app.css:

    • Utility classes: .input-field, .textarea-field, .select-field, .form-label, .error-message, .checkbox-custom, .radio-custom
    • Flux UI component targeting via data attributes ([data-flux-label], [data-flux-field], [data-flux-error], etc.)
    • Required indicator styling with .required::after pseudo-element
    • RTL support for labels, error messages, and form fields
    • Error state styling with danger color border and ring
  2. Updated existing forms to use consistent required indicator pattern:

    • Replaced manual " *" text with class="required" on <flux:label> components
    • Updated admin client forms (individual and company create/edit)
    • Updated admin posts forms (create/edit)
    • Updated admin timeline create form
    • Updated client booking form
  3. Created feature tests validating:

    • Forms render with required class on labels
    • CSS contains all expected form styling classes
    • Flux UI styling selectors are present
    • RTL support is included
    • Required indicator styling is defined

Completion Notes

  • Form styling implemented using both utility classes for custom forms and Flux UI data attribute selectors
  • The required class approach provides cleaner, more maintainable required field indicators via CSS ::after pseudo-element
  • All 12 form styling tests pass
  • Code formatted with Pint

QA Results

Review Date: 2026-01-03

Reviewed By: Quinn (Test Architect)

Code Quality Assessment

Excellent implementation. The form styling system is well-architected with a dual approach: utility classes for custom forms (.input-field, .textarea-field, .form-label, etc.) and Flux UI data attribute selectors for integrated component styling. The CSS is logically organized with clear section comments separating Flux UI component styling from the utility class system.

Key strengths:

  • Clean separation between Flux UI targeting ([data-flux-*] selectors) and utility classes
  • Comprehensive error state handling including focus ring color changes
  • Proper RTL support using [dir="rtl"] selectors
  • Required indicator via CSS ::after pseudo-element is elegant and maintainable

Refactoring Performed

No refactoring required. The implementation is clean and follows project conventions.

Compliance Check

  • Coding Standards: ✓ All code follows Pint formatting
  • Project Structure: ✓ CSS added to correct location, tests in Feature directory
  • Testing Strategy: ✓ Tests verify CSS presence and form rendering
  • All ACs Met: ✓ All 12 acceptance criteria verified (see trace below)

Acceptance Criteria Verification

AC Description Status Evidence
1 Input border: charcoal/30 border-charcoal/30 in CSS lines 92, 330
2 Input focus: gold border+ring focus:border-gold focus:ring-2 focus:ring-gold/20 lines 96-102, 331-332
3 Input border-radius: 6px rounded-md in CSS lines 92, 330
4 Input padding: 12px 16px px-4 py-3 in CSS line 330
5 Textarea: same + min-height 120px min-h-[120px] resize-y lines 105-107, 364-368
6 Select: Flux UI styled [data-flux-select-button] selectors lines 91, 100
7 Checkbox: gold accent checked text-gold focus:ring-gold lines 110-113, 378-381
8 Radio: gold accent selected text-gold focus:ring-gold lines 116-119, 384-387
9 Labels: semibold weight font-semibold lines 83, 342
10 Required: * in danger color .required::after with text-danger lines 346-355
11 Error: red border + message border-danger and error styling lines 122-139, 335-338
12 RTL support [dir="rtl"] selectors lines 142-154, 396-410

Improvements Checklist

  • Verified all CSS classes match story specifications
  • Verified Flux UI component styling via data attributes
  • Verified RTL support implementation
  • Verified error state styling
  • Verified required indicator on updated form files
  • Verified all 12 tests pass

Security Review

No security concerns. The CSS layer does not handle user input directly. Form inputs are properly escaped via Flux components and Livewire's built-in XSS protection.

Performance Considerations

No performance concerns. The CSS uses Tailwind's @apply directive which compiles to optimized CSS output. The selectors are specific but not overly complex, ensuring good rendering performance.

Files Modified During Review

None. No modifications required.

Gate Status

Gate: PASS → docs/qa/gates/9.5-component-styling-forms.yml

Ready for Done - All acceptance criteria met, tests passing, code quality excellent.