respira/docs/UI_BEFORE_AFTER_EXAMPLES.md
2025-12-08 18:54:37 +01:00

577 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UI Improvements: Before & After Examples
Visual comparison of key UI improvements with code examples.
---
## 1. Button States - Primary Action
### BEFORE
```tsx
<button
onClick={onConnect}
className="px-6 py-3 bg-blue-600 text-white rounded font-semibold text-sm hover:bg-blue-700 transition-all hover:shadow-md disabled:opacity-50 disabled:cursor-not-allowed disabled:grayscale-[0.3] cursor-pointer"
>
Connect to Machine
</button>
```
**Issues:**
- Grayscale filter on disabled state looks unprofessional
- No active/press state feedback
- No focus state for keyboard navigation
- Generic blue color, not semantic
- Rounded corners too subtle (4px)
### AFTER
```tsx
<button
onClick={onConnect}
className="
px-6 py-3
bg-primary text-white
rounded-lg font-semibold text-sm
shadow-sm
hover:bg-primary-light hover:shadow-md hover:scale-[1.02]
active:bg-primary-dark active:scale-[0.98]
focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2
disabled:bg-neutral-300 disabled:text-neutral-500 disabled:cursor-not-allowed disabled:shadow-none
transition-all duration-150 ease-in-out
cursor-pointer
"
aria-label="Connect to Brother embroidery machine via Bluetooth"
>
Connect to Machine
</button>
```
**Improvements:**
- Semantic color token (primary)
- Clear disabled state (gray, no grayscale filter)
- Press feedback (scale down on click)
- Visible focus ring for accessibility
- Slightly larger border radius (8px)
- ARIA label for screen readers
- Smooth transitions
**Visual Impact:**
```
BEFORE: [Connect to Machine] → (hover) [Connect to Machine] → (disabled) [Connect to Machine]
Normal appearance Darker blue + shadow Washed out grayscale
AFTER: [Connect to Machine] → (hover) [Connect to Machine] → (disabled) [Connect to Machine]
Blue with shadow Lighter blue, grows 2% Clean gray appearance
```
---
## 2. Color Block Status - Progress Monitor
### BEFORE
```tsx
<div className={`
p-2 rounded bg-gray-100 border-2 border-transparent transition-all
${isCompleted ? 'border-green-600 bg-green-50' : ''}
${isCurrent ? 'border-blue-600 bg-blue-50 shadow-md shadow-blue-600/20' : ''}
${isUpcoming ? 'opacity-60' : ''}
`}>
<div className="flex items-center gap-2">
<div className="w-5 h-5 rounded border-2 border-gray-300 shadow-sm flex-shrink-0"
style={{ backgroundColor: block.threadHex }}
/>
<span className="font-semibold flex-1 text-sm">
Thread {block.colorIndex + 1}
</span>
{isCompleted ? <CheckCircleIcon className="w-5 h-5 text-green-600" /> : null}
{isCurrent ? <ArrowRightIcon className="w-5 h-5 text-blue-600" /> : null}
{!isCompleted && !isCurrent ? <CircleStackIcon className="w-5 h-5 text-gray-400" /> : null}
<span className="text-xs text-gray-600">
{block.stitchCount.toLocaleString()}
</span>
</div>
{isCurrent && (
<div className="mt-1.5 h-1 bg-white rounded overflow-hidden">
<div className="h-full bg-blue-600 transition-all duration-300"
style={{ width: `${blockProgress}%` }}
/>
</div>
)}
</div>
```
**Issues:**
- Small color swatch (20px)
- Thin progress bar (4px)
- Small stitch count text (12px)
- Minimal visual distinction between states
- Upcoming blocks just fade (opacity-60)
- Tight spacing (gap-2)
### AFTER
```tsx
<div className={`
p-3 rounded-lg border-2 transition-all duration-200
${isCompleted ? 'border-success bg-success-bg/50 shadow-sm' : ''}
${isCurrent ? 'border-primary bg-primary/5 shadow-lg shadow-primary/10 ring-2 ring-primary/20 scale-[1.02]' : ''}
${!isCompleted && !isCurrent ? 'border-neutral-200 bg-neutral-50 opacity-70' : ''}
`}>
<div className="flex items-center gap-3">
<div className="w-6 h-6 rounded-md border-2 border-white shadow-md ring-1 ring-neutral-300 flex-shrink-0"
style={{ backgroundColor: block.threadHex }}
aria-label={`Thread color ${block.threadHex}`}
/>
<span className="font-semibold text-sm flex-1">
Thread {block.colorIndex + 1}
</span>
{isCompleted && <CheckCircleIcon className="w-5 h-5 text-success" aria-label="Completed" />}
{isCurrent && <ArrowRightIcon className="w-5 h-5 text-primary" aria-label="Current thread" />}
{!isCompleted && !isCurrent && <CircleStackIcon className="w-5 h-5 text-neutral-400" aria-label="Upcoming" />}
<span className="text-sm text-neutral-600 font-medium">
{block.stitchCount.toLocaleString()}
</span>
</div>
{isCurrent && (
<div className="mt-2.5 h-1.5 bg-neutral-200 rounded-full overflow-hidden">
<div className="h-full bg-primary transition-all duration-300 ease-out"
style={{ width: `${blockProgress}%` }}
role="progressbar"
aria-valuenow={blockProgress}
aria-valuemin={0}
aria-valuemax={100}
aria-label={`Thread ${block.colorIndex + 1} progress`}
/>
</div>
)}
</div>
```
**Improvements:**
- Larger color swatch (24px) - easier to see
- Thicker progress bar (6px) - clearer progress indication
- Larger stitch count (14px) - more readable
- Current block has ring + glow + slight scale
- More spacing (gap-3, p-3)
- ARIA labels for accessibility
- Semantic color tokens
- Better rounded corners on swatch
**Visual Impact:**
```
BEFORE - Upcoming: [■ Thread 1 ○ 1,234] Faded gray box, small swatch
BEFORE - Current: [■ Thread 2 → 2,456] Blue border, thin progress bar
BEFORE - Complete: [■ Thread 3 ✓ 1,890] Green border
AFTER - Upcoming: [■ Thread 1 ○ 1,234] Subtle gray, clear upcoming state
AFTER - Current: [■ Thread 2 → 2,456] Blue glow ring, prominent, thicker progress
AFTER - Complete: [■ Thread 3 ✓ 1,890] Green with subtle shadow, completed
```
---
## 3. Section Headers
### BEFORE
```tsx
<h2 className="text-xl font-semibold mb-4 pb-2 border-b-2 border-gray-300">
Pattern Preview
</h2>
```
**Issues:**
- Heavy bottom border (2px) but weak separation
- Border too dark (gray-300)
- Font weight only semibold (not bold)
- No container grouping
### AFTER
```tsx
<div className="mb-5 pb-3 border-b border-neutral-200">
<h2 className="text-xl font-bold text-neutral-900">Pattern Preview</h2>
</div>
```
**Improvements:**
- Lighter, more subtle border (1px, neutral-200)
- Bolder heading (font-bold)
- Explicit text color (neutral-900)
- More bottom padding (pb-3)
- Wrapped in container for flex control
**Visual Impact:**
```
BEFORE:
Pattern Preview
================== (thick dark line)
AFTER:
Pattern Preview
___________________ (thin subtle line)
```
---
## 4. Workflow Stepper
### BEFORE
```tsx
{/* Progress line */}
<div className="absolute top-4 left-0 h-0.5 bg-blue-400/30" ... />
<div className="absolute top-4 left-0 h-0.5 bg-blue-100 ..." ... />
{/* Step circles */}
<div className={`
w-8 h-8 rounded-full flex items-center justify-center font-bold text-xs
${isComplete ? 'bg-green-500 border-green-500 text-white' : ''}
${isCurrent ? 'bg-blue-600 border-blue-600 text-white scale-110' : ''}
${isUpcoming ? 'bg-blue-700 border-blue-400/30 text-blue-200' : ''}
`}>
{isComplete ? <CheckCircleIcon className="w-5 h-5" /> : step.id}
</div>
{/* Labels */}
<div className={`text-xs font-semibold ${isCurrent ? 'text-white' : isComplete ? 'text-blue-100' : 'text-blue-300'}`}>
{step.label}
</div>
```
**Issues:**
- Thin progress line (0.5px) - barely visible
- Small step circles (32px)
- Tiny text (12px)
- Poor contrast for upcoming steps (blue-300 on blue-700)
### AFTER
```tsx
{/* Progress line - thicker, more visible */}
<div className="absolute top-5 left-0 h-1 bg-blue-900/20" ... />
<div className="absolute top-5 left-0 h-1 bg-blue-100 ..." ... />
{/* Step circles - larger */}
<div className={`
w-10 h-10 rounded-full flex items-center justify-center font-bold text-sm border-2
${isComplete ? 'bg-success border-success text-white' : ''}
${isCurrent ? 'bg-primary border-primary text-white scale-110 shadow-lg shadow-primary/30' : ''}
${isUpcoming ? 'bg-blue-700 border-blue-400/30 text-blue-100' : ''}
`}>
{isComplete ? <CheckCircleIcon className="w-6 h-6" /> : step.id}
</div>
{/* Labels - larger, better contrast */}
<div className={`text-sm font-bold tracking-wide ${isCurrent ? 'text-white' : isComplete ? 'text-blue-50' : 'text-blue-200'}`}>
{step.label}
</div>
```
**Improvements:**
- Thicker progress line (4px vs 2px)
- Larger circles (40px vs 32px)
- Bigger text (14px vs 12px)
- Better contrast for text (blue-100/50 instead of 300/200)
- Shadow on current step
- Semantic color tokens
- Letter spacing for readability
**Visual Impact:**
```
BEFORE: ①---②---③---④---⑤---⑥---⑦ (small, thin line, small labels)
AFTER: ①━━━②━━━③━━━④━━━⑤━━━⑥━━━⑦ (larger, bold line, bigger labels)
```
---
## 5. Machine Connection - Status Badge
### BEFORE
```tsx
<span className={`flex items-center gap-2 px-3 py-1.5 rounded-lg font-semibold text-sm ${statusBadgeColors[stateVisual.color]}`}>
<span className="text-base leading-none">{stateVisual.icon}</span>
<span>{machineStatusName}</span>
</span>
```
**Issues:**
- No border (looks flat)
- Minimal padding
- No explicit inline-flex
### AFTER
```tsx
<span className={`
inline-flex items-center gap-2
px-3.5 py-2
rounded-lg
font-semibold text-sm
border border-current/20
${statusBadgeColors[stateVisual.color]}
`}>
<span className="text-base leading-none">{stateVisual.icon}</span>
<span>{machineStatusName}</span>
</span>
```
**Improvements:**
- Subtle border using current color (adds depth)
- Slightly more padding (3.5 vs 3, py-2 vs 1.5)
- Explicit inline-flex for better alignment
**Visual Impact:**
```
BEFORE: [🔄 Sewing] Flat badge, no border
AFTER: [🔄 Sewing] Badge with subtle outline, more prominent
```
---
## 6. Pattern Canvas - Overlays
### BEFORE
```tsx
{/* Thread Legend */}
<div className="absolute top-2.5 left-2.5 bg-white/95 backdrop-blur-sm p-3 rounded-lg shadow-lg z-10 max-w-[150px]">
<h4 className="m-0 mb-2 text-[13px] font-semibold text-gray-900 border-b border-gray-300 pb-1.5">
Threads
</h4>
{/* ... */}
</div>
{/* Zoom Controls */}
<div className="absolute bottom-5 right-5 flex gap-2 items-center bg-white/95 backdrop-blur-sm px-3 py-2 rounded-lg shadow-lg z-10">
<button className="w-8 h-8 p-1 border border-gray-300 ...">
<PlusIcon className="w-5 h-5" />
</button>
{/* ... */}
</div>
```
**Issues:**
- Inconsistent border radius (rounded-lg vs none)
- No border on overlays
- Small touch targets (32px buttons)
- Mixed font sizes (13px)
### AFTER
```tsx
{/* Thread Legend - unified styling */}
<div className="absolute top-3 left-3 bg-white/98 backdrop-blur-sm p-4 rounded-xl shadow-lg border border-neutral-200 z-10 max-w-[180px]">
<h4 className="text-sm font-bold text-neutral-900 mb-3">Threads</h4>
{pesData.threads.map((thread, index) => (
<div key={index} className="flex items-center gap-2.5 mb-2 last:mb-0">
<div className="w-6 h-6 rounded-md border-2 border-white shadow-sm ring-1 ring-neutral-300"
style={{ backgroundColor: thread.hex }}
/>
<span className="text-sm text-neutral-900 font-medium">Thread {index + 1}</span>
</div>
))}
</div>
{/* Zoom Controls - larger touch targets */}
<div className="absolute bottom-5 right-5 flex items-center gap-1 bg-white/98 backdrop-blur-sm px-2 py-2 rounded-xl shadow-lg border border-neutral-200 z-10">
<button className="w-10 h-10 flex items-center justify-center border border-neutral-300 rounded-lg ..."
aria-label="Zoom in">
<PlusIcon className="w-5 h-5" />
</button>
<div className="w-px h-6 bg-neutral-200 mx-1"></div>
<span className="px-3 text-sm font-semibold text-neutral-900">{zoom}%</span>
<div className="w-px h-6 bg-neutral-200 mx-1"></div>
<button className="w-10 h-10 ..." aria-label="Zoom out">
<MinusIcon className="w-5 h-5" />
</button>
<button className="w-10 h-10 ..." aria-label="Reset zoom">
<ArrowPathIcon className="w-5 h-5" />
</button>
</div>
```
**Improvements:**
- Unified overlay style (rounded-xl, border, neutral colors)
- Larger touch targets (40px vs 32px)
- Visual separators between controls
- Consistent font sizes (text-sm)
- ARIA labels for accessibility
- Better thread swatch styling (with ring)
**Visual Impact:**
```
BEFORE:
┌───────────┐ [+] 100% [-] [↻]
│ Threads │
│ ■ Thread 1│
└───────────┘
AFTER:
╔═══════════╗ [+] │ 100% │ [-] [↻]
║ Threads ║
║ ■ Thread 1║
╚═══════════╝
(rounder, border) (larger, separated)
```
---
## 7. FileUpload - Pattern Information
### BEFORE
```tsx
<div className="bg-gray-50 p-4 rounded-lg space-y-3">
<div className="flex justify-between">
<span className="font-medium text-gray-700">File Name:</span>
<span className="font-semibold text-gray-900">{displayFileName}</span>
</div>
<div className="flex justify-between">
<span className="font-medium text-gray-700">Pattern Size:</span>
<span className="font-semibold text-gray-900">{size}</span>
</div>
{/* ... */}
</div>
```
**Issues:**
- All in one gray box (low hierarchy)
- Labels and values on same line (can overflow)
- Tight spacing
### AFTER
```tsx
<div className="grid grid-cols-2 gap-3">
<div className="bg-white p-3 rounded-lg border border-neutral-200 shadow-sm">
<div className="text-xs font-medium text-neutral-500 mb-1.5 uppercase tracking-wide">File Name</div>
<div className="font-semibold text-sm text-neutral-900 truncate" title={displayFileName}>
{displayFileName}
</div>
</div>
<div className="bg-white p-3 rounded-lg border border-neutral-200 shadow-sm">
<div className="text-xs font-medium text-neutral-500 mb-1.5 uppercase tracking-wide">Size</div>
<div className="font-semibold text-sm text-neutral-900">{size} mm</div>
</div>
<div className="bg-white p-3 rounded-lg border border-neutral-200 shadow-sm">
<div className="text-xs font-medium text-neutral-500 mb-1.5 uppercase tracking-wide">Colors</div>
<div className="font-semibold text-sm text-neutral-900">{pesData.colorCount}</div>
</div>
<div className="bg-white p-3 rounded-lg border border-neutral-200 shadow-sm">
<div className="text-xs font-medium text-neutral-500 mb-1.5 uppercase tracking-wide">Stitches</div>
<div className="font-semibold text-sm text-neutral-900">{pesData.stitchCount.toLocaleString()}</div>
</div>
</div>
```
**Improvements:**
- 2×2 grid layout - better scannability
- Individual cards for each stat
- Clear label/value hierarchy
- Uppercase labels with tracking
- Truncation for long filenames
- Better visual separation
**Visual Impact:**
```
BEFORE:
┌─────────────────────────────────┐
│ File Name: pattern.pes │
│ Size: 100 × 50 mm │
│ Colors: 5 │
│ Stitches: 12,345 │
└─────────────────────────────────┘
AFTER:
┌──────────────┐ ┌──────────────┐
│ FILE NAME │ │ SIZE │
│ pattern.pes │ │ 100 × 50 mm │
└──────────────┘ └──────────────┘
┌──────────────┐ ┌──────────────┐
│ COLORS │ │ STITCHES │
│ 5 │ │ 12,345 │
└──────────────┘ └──────────────┘
```
---
## 8. Progress Bar - Unified Style
### BEFORE (Upload)
```tsx
<div className="h-3 bg-gray-300 rounded-md overflow-hidden shadow-inner">
<div className="h-full bg-gradient-to-r from-blue-600 to-blue-700 transition-all duration-300 ease-out relative overflow-hidden after:absolute after:inset-0 after:bg-gradient-to-r after:from-transparent after:via-white/30 after:to-transparent after:animate-[shimmer_2s_infinite]"
style={{ width: `${uploadProgress}%` }}
/>
</div>
```
**Issues:**
- Only upload has shimmer effect
- Sewing progress bar is plain
- Different bar heights in different places
- Non-semantic colors
### AFTER (Unified)
```tsx
{/* Reusable progress bar component */}
<div className="h-2.5 bg-neutral-200 rounded-full overflow-hidden shadow-inner">
<div className="h-full bg-gradient-to-r from-primary to-primary-light transition-all duration-300 ease-out relative overflow-hidden"
style={{ width: `${progress}%` }}
role="progressbar"
aria-valuenow={progress}
aria-valuemin={0}
aria-valuemax={100}
aria-label={ariaLabel}
>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/30 to-transparent animate-[shimmer_2s_infinite]" />
</div>
</div>
```
**Improvements:**
- Consistent height (10px/2.5)
- Shimmer on all progress bars
- Semantic colors (primary)
- ARIA attributes
- Rounded ends (rounded-full)
- Same gradient style everywhere
---
## Summary of Key Visual Changes
| Element | Before | After | Impact |
|---------|--------|-------|--------|
| **Buttons** | Grayscale disabled, no press feedback | Clean gray disabled, scale press | Professional, accessible |
| **Colors** | Mixed blues (blue-600, blue-700, cyan-600) | Semantic tokens (primary, success) | Consistent, meaningful |
| **Typography** | 10-12px text common | 12-14px minimum | More readable |
| **Spacing** | Varied (gap-2 to gap-6) | Standardized (2/3/4/6) | Cleaner layout |
| **Touch Targets** | 32px buttons | 44px minimum | Better mobile UX |
| **Borders** | Heavy (2px) or none | Subtle (1px) everywhere | Cohesive design |
| **Focus States** | Missing on many elements | Ring on all interactive | Accessible |
| **Shadows** | Inconsistent use | Strategic depth | Better hierarchy |
| **Color Blocks** | Minimal distinction | Strong visual hierarchy | Clear progress |
| **Overlays** | Mixed styles | Unified rounded-xl + border | Professional |
---
## Color Token Reference
```css
Primary (actions): #2563eb (blue-600)
Success (complete): #16a34a (green-600)
Warning (wait): #d97706 (amber-600)
Danger (errors): #dc2626 (red-600)
Info (active): #0891b2 (cyan-600)
Neutral text: #111827 (gray-900)
Secondary text: #4b5563 (gray-600)
Borders: #d1d5db (gray-300)
Backgrounds: #f9fafb (gray-50)
```
---
## Implementation Order
1. Create design tokens file
2. Update all button classes
3. Fix typography sizes
4. Standardize spacing
5. Add accessibility attributes
6. Polish details (shadows, borders)
7. Test all states (hover, active, focus, disabled)
Total time: ~2.5 hours