6.8 KiB
6.8 KiB
Story 9.4: Component Styling - Buttons
Epic Reference
Epic 9: Design & Branding Implementation
Dependencies
- Story 9.1: Color System Implementation - Must be complete (this story uses the color variables defined there)
User Story
As a user, I want consistent, professional button styling, So that interactive elements are clear and visually appealing.
Context
This story implements the button styling system that will be used throughout the application. Buttons appear in:
- Forms (submit, cancel actions)
- Modals (confirm, dismiss)
- Navigation (CTAs)
- Admin dashboards (CRUD operations)
- Client booking flow
The implementation extends Flux UI's button component with brand colors rather than replacing it, ensuring we maintain Flux's built-in accessibility and functionality.
Acceptance Criteria
Primary Button
- Background: Gold (
bg-gold/ #D4AF37) - Text: Dark Navy Blue (
text-navy) - Hover: Light Gold (
hover:bg-gold-light/ #F4E4B8) - Border-radius: 6px (
rounded-md) - Padding: 12px 24px (
px-6 py-3)
Secondary Button
- Background: Transparent
- Border: 2px solid Gold (
border-2 border-gold) - Text: Gold (
text-gold) - Hover: Gold background, Navy text (
hover:bg-gold hover:text-navy)
Disabled State
- Background: #CCCCCC
- Text: #666666
- No hover effect
- Cursor: not-allowed
Danger Button
- Background: #E74C3C (
bg-danger) - Text: White
- Hover: Slightly darker (
hover:bg-danger/90)
Button Sizes
- Small:
px-4 py-2 text-sm(for compact UI areas) - Default:
px-6 py-3 text-base(standard usage) - Large:
px-8 py-4 text-lg(hero CTAs)
Features
- Loading states with Flux spinner component
- Focus states: Gold outline ring for accessibility (
focus:ring-2 focus:ring-gold focus:ring-offset-2) - Icon support: Buttons with leading/trailing icons
- Full-width variant for mobile forms
- Button groups with proper border-radius handling
Files to Create/Modify
| File | Action | Purpose |
|---|---|---|
resources/css/app.css |
Modify | Add button variant styles in @theme or as Tailwind components |
Technical Notes
Flux UI Integration Approach
Flux UI buttons accept a variant prop. We extend Flux by:
- Using Flux's
<flux:button>component as-is for structure - Applying brand colors via the
variantprop or custom CSS classes - NOT creating wrapper components unless absolutely necessary
Reference: Use search-docs tool with query "button" and package "livewire/flux" for current Flux button API.
CSS Implementation
/* resources/css/app.css - Add after @import "tailwindcss" and @theme block */
/* Primary button - Gold background */
.btn-primary {
@apply bg-gold text-navy hover:bg-gold-light rounded-md px-6 py-3 font-semibold transition-colors;
@apply focus:outline-none focus:ring-2 focus:ring-gold focus:ring-offset-2;
}
/* Secondary button - Outlined */
.btn-secondary {
@apply bg-transparent border-2 border-gold text-gold rounded-md px-6 py-3 font-semibold transition-colors;
@apply hover:bg-gold hover:text-navy;
@apply focus:outline-none focus:ring-2 focus:ring-gold focus:ring-offset-2;
}
/* Danger button */
.btn-danger {
@apply bg-danger text-white hover:bg-danger/90 rounded-md px-6 py-3 font-semibold transition-colors;
@apply focus:outline-none focus:ring-2 focus:ring-danger focus:ring-offset-2;
}
/* Disabled state - applies to all variants */
.btn-disabled,
button:disabled,
[disabled] {
@apply bg-gray-300 text-gray-500 cursor-not-allowed;
@apply hover:bg-gray-300; /* Override hover */
}
/* Size variants */
.btn-sm { @apply px-4 py-2 text-sm; }
.btn-lg { @apply px-8 py-4 text-lg; }
/* Full width for mobile */
.btn-full { @apply w-full; }
/* Loading state */
.btn-loading {
@apply relative pointer-events-none opacity-75;
}
/* Icon spacing within buttons */
.btn-icon-left { @apply flex items-center gap-2; }
.btn-icon-right { @apply flex items-center gap-2 flex-row-reverse; }
Usage Examples
{{-- Primary button with Flux --}}
<flux:button variant="primary" class="btn-primary">
{{ __('Submit') }}
</flux:button>
{{-- Secondary button --}}
<flux:button variant="ghost" class="btn-secondary">
{{ __('Cancel') }}
</flux:button>
{{-- Danger button --}}
<flux:button variant="danger" class="btn-danger">
{{ __('Delete') }}
</flux:button>
{{-- Button with icon --}}
<flux:button class="btn-primary btn-icon-left">
<flux:icon name="plus" class="w-4 h-4" />
{{ __('Add New') }}
</flux:button>
{{-- Loading state --}}
<flux:button class="btn-primary" wire:loading.class="btn-loading">
<span wire:loading.remove>{{ __('Save') }}</span>
<span wire:loading>{{ __('Saving...') }}</span>
</flux:button>
{{-- Full width on mobile --}}
<flux:button class="btn-primary btn-full sm:w-auto">
{{ __('Book Consultation') }}
</flux:button>
Edge Cases to Handle
- Icon-only buttons: Ensure adequate touch target (44px minimum)
- Long button text: Text should not overflow; consider truncation or wrapping
- RTL layout: Icons should flip position appropriately (use logical
start/endif needed) - Button groups: First/last buttons need adjusted border-radius
Testing Requirements
Test Approach
- Visual testing: Verify all button states render correctly
- Accessibility testing: Validate focus states and contrast ratios
- RTL testing: Confirm buttons display correctly in Arabic mode
Test Scenarios
// tests/Feature/Components/ButtonStylingTest.php
test('primary button has correct styling classes', function () {
$this->get('/')
->assertSee('btn-primary');
});
test('disabled button prevents interaction', function () {
// Verify disabled state renders with correct cursor and no hover
});
test('buttons are keyboard accessible', function () {
// Verify focus states are visible
});
test('buttons render correctly in RTL mode', function () {
// Set locale to Arabic and verify button layout
});
Accessibility Checklist
- Focus indicator visible (gold ring)
- Color contrast meets WCAG AA (4.5:1 for text)
- Touch targets minimum 44x44px on mobile
- Disabled state communicated to screen readers
Definition of Done
- Primary button styled per acceptance criteria
- Secondary button styled per acceptance criteria
- Danger button styled per acceptance criteria
- Disabled states work correctly
- Loading states work with Flux spinner
- Focus states visible and accessible
- Size variants (sm, default, lg) implemented
- Icon buttons work correctly
- Full-width variant works on mobile
- RTL layout tested
- Tests pass
- Code formatted with Pint
Estimation
Complexity: Medium | Effort: 3 hours