Visual enhancements: - Create design tokens system with semantic colors (primary, success, warning, danger, info, neutral) - Enhanced button states with hover shadow, active press feedback, and focus rings - Improved WorkflowStepper with larger circles, gradient progress bar, and green completion indicators - Enhanced color blocks with larger swatches (w-8 h-8), better shadows, and animated current indicator - Reorganized ProgressMonitor layout - progress/controls on left, color blocks on right - Moved disconnect button to header as small, compact button Accessibility improvements: - Added comprehensive ARIA labels to all interactive elements - Implemented proper focus states with color-matched rings - Added role attributes for navigation and progress elements - Enhanced screen reader support with descriptive labels - All buttons now meet 44px touch target requirements Button improvements across all components: - Standardized to rounded-lg for softer appearance - Added hover:shadow-lg for depth perception - Added active:scale-[0.98] for tactile feedback - Clean disabled states without grayscale filter - Keyboard navigation with visible focus rings - Consistent transition timing (150ms) Typography: - Maintained minimum 12px text size throughout - Proper hierarchy with defined heading sizes - Improved readability with consistent weights Documentation: - Created comprehensive UI design analysis - Implementation guides and checklists - Before/after examples - Design tokens reference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
26 KiB
Component Implementation Checklist
Step-by-step guide to implementing UI improvements in each component.
Setup (Do First)
1. Create Design Tokens
File: C:\Users\micro\Documents\dev\respira-web\src\styles\design-tokens.css
@theme {
/* Primary - Blue */
--color-primary: #2563eb;
--color-primary-light: #3b82f6;
--color-primary-dark: #1d4ed8;
/* Secondary - Slate */
--color-secondary: #64748b;
--color-secondary-light: #94a3b8;
/* Success - Green */
--color-success: #16a34a;
--color-success-bg: #dcfce7;
/* Warning - Amber */
--color-warning: #d97706;
--color-warning-bg: #fef3c7;
/* Danger - Red */
--color-danger: #dc2626;
--color-danger-bg: #fee2e2;
/* Info - Cyan */
--color-info: #0891b2;
--color-info-bg: #cffafe;
/* Neutral */
--color-neutral-50: #f9fafb;
--color-neutral-100: #f3f4f6;
--color-neutral-200: #e5e7eb;
--color-neutral-300: #d1d5db;
--color-neutral-600: #4b5563;
--color-neutral-900: #111827;
}
- Create file
- Add all color tokens
2. Update App.css
File: C:\Users\micro\Documents\dev\respira-web\src\App.css
@import "tailwindcss";
@import "./styles/design-tokens.css";
/* Custom animations for shimmer effect */
@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
- Import design tokens
- Verify shimmer animation exists
Component Updates
App.tsx
File: C:\Users\micro\Documents\dev\respira-web\src\App.tsx
Changes:
- Header background gradient
- Grid gap spacing
- Error message styling
Line 90 - Header gradient:
// BEFORE
<header className="bg-gradient-to-r from-blue-600 to-blue-700 px-8 py-3 shadow-lg">
// AFTER
<header className="bg-gradient-to-r from-primary to-primary-dark px-8 py-3 shadow-lg">
Line 111-118 - Error messages:
// BEFORE
<div className="bg-red-100 text-red-900 px-6 py-4 rounded-lg border-l-4 border-red-600 mb-6 shadow-md">
// AFTER
<div className="bg-danger-bg text-red-900 px-6 py-4 rounded-lg border-l-4 border-danger mb-6 shadow-md">
<strong>Error:</strong> {machine.error}
</div>
Line 120-123 - Info message:
// BEFORE
<div className="bg-blue-100 text-blue-900 px-6 py-4 rounded-lg border-l-4 border-blue-600 mb-6 shadow-md">
// AFTER
<div className="bg-info-bg text-cyan-900 px-6 py-4 rounded-lg border-l-4 border-info mb-6 shadow-md">
Initializing Python environment...
</div>
Line 126 - Grid gap:
// BEFORE
<div className="grid grid-cols-1 lg:grid-cols-[400px_1fr] gap-6">
// AFTER
<div className="grid grid-cols-1 lg:grid-cols-[400px_1fr] gap-8">
- Update header background
- Update error styling
- Update info message styling
- Increase grid gap
- Test responsive layout
WorkflowStepper.tsx
File: C:\Users\micro\Documents\dev\respira-web\src\components\WorkflowStepper.tsx
Changes:
- Progress line thickness
- Step circle size
- Text size and contrast
- Semantic colors
Line 64-73 - Progress lines:
// BEFORE
<div className="absolute top-4 left-0 right-0 h-0.5 bg-blue-400/30" ... />
<div className="absolute top-4 left-0 h-0.5 bg-blue-100 ..." ... />
// AFTER
<div className="absolute top-5 left-0 right-0 h-1 bg-blue-900/20" style={{ left: '20px', right: '20px' }} />
<div className="absolute top-5 left-0 h-1 bg-blue-100 transition-all duration-500"
style={{
left: '20px',
width: `calc(${((currentStep - 1) / (steps.length - 1)) * 100}% - 20px)`
}}
/>
Line 85-98 - Step circles:
// BEFORE
<div className={`
w-8 h-8 rounded-full flex items-center justify-center font-bold text-xs transition-all duration-300 border-2
${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' : ''}
`}>
// AFTER
<div className={`
w-10 h-10 rounded-full flex items-center justify-center font-bold text-sm transition-all duration-300 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" /> {/* was w-5 h-5 */}
) : (
step.id
)}
</div>
Line 101-105 - Step labels:
// BEFORE
<div className={`text-xs font-semibold ${isCurrent ? 'text-white' : isComplete ? 'text-blue-100' : 'text-blue-300'}`}>
// AFTER
<div className={`text-sm font-bold tracking-wide ${isCurrent ? 'text-white' : isComplete ? 'text-blue-50' : 'text-blue-200'}`}>
{step.label}
</div>
- Update progress line (h-1, top-5)
- Increase circle size (w-10 h-10)
- Use semantic colors (success, primary)
- Increase text size (text-sm)
- Improve contrast (blue-100 vs blue-300)
- Add shadow to current step
- Enlarge check icon
MachineConnection.tsx
File: C:\Users\micro\Documents\dev\respira-web\src\components\MachineConnection.tsx
Changes:
- Button styling (Connect, Disconnect)
- Status badge border
- Auto-refresh indicator
- Error/info boxes
- Semantic colors
Line 78-81 - Connect button:
// BEFORE
<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">
// AFTER
<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>
Line 68-73 - Auto-refresh indicator:
// BEFORE
<span className="flex items-center gap-2 text-xs text-gray-500">
<span className="w-2 h-2 bg-blue-500 rounded-full animate-pulse"></span>
Auto-refreshing
</span>
// AFTER
<span className="flex items-center gap-2 px-3 py-1.5 bg-blue-50 rounded-full text-xs font-medium text-blue-700 border border-blue-200">
<span className="w-2 h-2 bg-blue-500 rounded-full animate-pulse"></span>
Auto-refreshing
</span>
Line 116-120 - Status badge:
// BEFORE
<span className={`flex items-center gap-2 px-3 py-1.5 rounded-lg font-semibold text-sm ${statusBadgeColors[stateVisual.color]}`}>
// AFTER
<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>
Line 141-144 - Disconnect button:
// BEFORE
<button onClick={handleDisconnectClick} className="w-full px-6 py-3 bg-red-600 text-white rounded font-semibold text-sm hover:bg-red-700 transition-all hover:shadow-md cursor-pointer">
// AFTER
<button onClick={handleDisconnectClick} className="
w-full px-6 py-3
bg-danger text-white
rounded-lg font-semibold text-sm
shadow-sm
hover:bg-red-700 hover:shadow-md hover:scale-[1.02]
active:bg-red-800 active:scale-[0.98]
focus:outline-none focus:ring-2 focus:ring-danger focus:ring-offset-2
transition-all duration-150
cursor-pointer
">
Disconnect
</button>
Line 88-95 - Informational message:
// BEFORE
<div className="mb-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
// AFTER
<div className="mb-4 p-4 bg-info-bg border border-cyan-200 rounded-lg">
- Update Connect button (primary colors, states)
- Update Disconnect button (danger color, states)
- Add border to status badge
- Enhance auto-refresh indicator
- Use semantic colors throughout
- Add ARIA labels
- Remove grayscale filters
FileUpload.tsx
File: C:\Users\micro\Documents\dev\respira-web\src\components\FileUpload.tsx
Changes:
- Choose File button styling
- Upload button styling
- Pattern information grid
- Progress bar
Line 106-108 - Choose File label:
// BEFORE
<label htmlFor="file-input" className={`inline-block px-6 py-3 bg-gray-600 text-white rounded font-semibold text-sm transition-all ${!pyodideReady || isLoading || patternUploaded ? 'opacity-50 cursor-not-allowed grayscale-[0.3]' : 'cursor-pointer hover:bg-gray-700 hover:shadow-md'}`}>
// AFTER
<label htmlFor="file-input" className={`
inline-block px-6 py-3
${!pyodideReady || isLoading || patternUploaded ? 'bg-neutral-300 text-neutral-500 cursor-not-allowed' : 'bg-secondary text-white hover:bg-secondary-light hover:shadow-md cursor-pointer'}
rounded-lg font-semibold text-sm
shadow-sm
transition-all duration-150
`}>
{isLoading ? 'Loading...' : !pyodideReady ? 'Initializing...' : patternUploaded ? 'Pattern Locked' : 'Choose PES File'}
</label>
Line 113-133 - Pattern information (replace with grid):
// BEFORE
<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>
{/* ... more rows ... */}
</div>
// AFTER
<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">Pattern Size</div>
<div className="font-semibold text-sm text-neutral-900">
{((pesData.bounds.maxX - pesData.bounds.minX) / 10).toFixed(1)} x{' '}
{((pesData.bounds.maxY - pesData.bounds.minY) / 10).toFixed(1)} 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">Thread 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">Total Stitches</div>
<div className="font-semibold text-sm text-neutral-900">{pesData.stitchCount.toLocaleString()}</div>
</div>
</div>
Line 138-146 - Upload button:
// BEFORE
<button onClick={handleUpload} disabled={!isConnected || uploadProgress > 0} className="mt-4 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">
// AFTER
<button onClick={handleUpload} disabled={!isConnected || uploadProgress > 0} className="
mt-4 px-6 py-3
bg-primary text-white
rounded-lg font-semibold text-sm
shadow-sm
hover:bg-primary-light hover:shadow-md
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
cursor-pointer
">
{uploadProgress > 0 ? `Uploading... ${uploadProgress.toFixed(0)}%` : 'Upload to Machine'}
</button>
Line 155-161 - Progress bar:
// BEFORE
<div className="h-3 bg-gray-300 rounded-md overflow-hidden my-4 shadow-inner">
<div className="h-full bg-gradient-to-r from-blue-600 to-blue-700 ..." style={{ width: `${uploadProgress}%` }} />
</div>
// AFTER
<div className="h-2.5 bg-neutral-200 rounded-full overflow-hidden my-4 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: `${uploadProgress}%` }}
role="progressbar"
aria-valuenow={uploadProgress}
aria-valuemin={0}
aria-valuemax={100}
aria-label="Upload progress"
>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/30 to-transparent animate-[shimmer_2s_infinite]" />
</div>
</div>
- Update Choose File button
- Replace pattern info with grid layout
- Update Upload button
- Enhance progress bar
- Use semantic colors
- Add ARIA attributes
- Remove grayscale filter
ProgressMonitor.tsx
File: C:\Users\micro\Documents\dev\respira-web\src\components\ProgressMonitor.tsx
Changes:
- Grid gap
- Color block design
- Button styling
- Progress bar
- Semantic colors
Line 116 - Grid gap:
// BEFORE
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
// AFTER
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
Line 143 - Color block container gap:
// BEFORE
<div className="flex flex-col gap-2">
// AFTER
<div className="flex flex-col gap-3">
Line 157-191 - Color blocks (major update):
// BEFORE
<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' : 'opacity-60'
}`}>
// AFTER
<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}
/>
</div>
)}
</div>
Line 207-209 - Sewing progress bar:
// BEFORE
<div className="h-3 bg-gray-300 rounded-md overflow-hidden shadow-inner relative mb-2">
<div className="h-full bg-gradient-to-r from-blue-600 to-blue-700 ..." />
</div>
// AFTER
<div className="h-2.5 bg-neutral-200 rounded-full overflow-hidden shadow-inner mb-2">
<div
className="h-full bg-gradient-to-r from-primary to-primary-light transition-all duration-300 ease-out relative overflow-hidden"
style={{ width: `${progressPercent}%` }}
role="progressbar"
aria-valuenow={progressPercent}
aria-valuemin={0}
aria-valuemax={100}
aria-label="Sewing progress"
>
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/30 to-transparent animate-[shimmer_2s_infinite]" />
</div>
</div>
Line 256-259 - Resume button:
// BEFORE
<button onClick={onResumeSewing} className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded font-semibold text-sm hover:bg-blue-700 transition-all hover:shadow-md cursor-pointer">
// AFTER
<button onClick={onResumeSewing} className="
flex items-center gap-2
px-4 py-2
bg-primary text-white
rounded-lg font-semibold text-sm
shadow-sm
hover:bg-primary-light hover:shadow-md
active:bg-primary-dark active:scale-[0.98]
focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2
transition-all duration-150
cursor-pointer
">
<PlayIcon className="w-4 h-4" />
Resume Sewing
</button>
Line 264-267 - Start Sewing button:
// Similar update as Resume button
Line 271-274 - Start Mask Trace button:
// BEFORE
<button onClick={onStartMaskTrace} className="px-4 py-2 bg-gray-600 text-white rounded font-semibold text-sm hover:bg-gray-700 ...">
// AFTER
<button onClick={onStartMaskTrace} className="
px-4 py-2
bg-secondary text-white
rounded-lg font-semibold text-sm
shadow-sm
hover:bg-secondary-light hover:shadow-md
active:scale-[0.98]
focus:outline-none focus:ring-2 focus:ring-secondary focus:ring-offset-2
transition-all duration-150
cursor-pointer
">
{isMaskTraceComplete ? 'Trace Again' : 'Start Mask Trace'}
</button>
Line 278-281 - Delete button:
// BEFORE
<button onClick={onDeletePattern} className="px-4 py-2 bg-red-600 text-white rounded font-semibold text-sm hover:bg-red-700 ...">
// AFTER
<button onClick={onDeletePattern} className="
px-4 py-2
bg-danger text-white
rounded-lg font-semibold text-sm
shadow-sm
hover:bg-red-700 hover:shadow-md
active:bg-red-800 active:scale-[0.98]
focus:outline-none focus:ring-2 focus:ring-danger focus:ring-offset-2
transition-all duration-150
ml-auto
cursor-pointer
">
Delete Pattern
</button>
- Increase grid gap
- Update color block design (larger swatches, better states)
- Add ARIA labels to color blocks
- Enhance progress bar with shimmer
- Update all button styles
- Use semantic colors
- Remove grayscale filters
PatternCanvas.tsx
File: C:\Users\micro\Documents\dev\respira-web\src\components\PatternCanvas.tsx
Changes:
- Overlay styling unification
- Zoom button sizing
- Thread legend improvement
Line 270-281 - Thread Legend:
// BEFORE
<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>
// AFTER
<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-md ring-1 ring-neutral-300 flex-shrink-0"
style={{ backgroundColor: thread.hex }}
/>
<span className="text-sm text-neutral-900 font-medium">Thread {index + 1}</span>
</div>
))}
</div>
Line 284-287 - Pattern Dimensions:
// BEFORE
<div className="absolute bottom-[165px] right-5 bg-white/95 backdrop-blur-sm px-4 py-2 rounded-lg shadow-lg z-[11] ...">
// AFTER
<div className="absolute bottom-[165px] right-5 bg-white/98 backdrop-blur-sm px-4 py-2 rounded-xl shadow-lg border border-neutral-200 z-[11] ...">
Line 290-298 - Pattern Offset:
// BEFORE
<div className="absolute bottom-20 right-5 bg-white/95 backdrop-blur-sm p-2.5 px-3.5 rounded-lg shadow-lg z-[11] ...">
// AFTER
<div className="absolute bottom-20 right-5 bg-white/98 backdrop-blur-sm p-3 rounded-xl shadow-lg border border-neutral-200 z-[11] ...">
Line 301-311 - Zoom Controls:
// BEFORE
<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 bg-white rounded ...">
// AFTER
<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
bg-white border border-neutral-300
rounded-lg
text-neutral-700
hover:bg-primary hover:text-white hover:border-primary
active:bg-primary-dark active:scale-95
focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2
transition-all duration-150
cursor-pointer
" onClick={handleZoomIn} aria-label="Zoom in on pattern preview" title="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 select-none">{Math.round(stageScale * 100)}%</span>
<div className="w-px h-6 bg-neutral-200 mx-1"></div>
<button ... aria-label="Zoom out from pattern preview" title="Zoom Out">
<MinusIcon className="w-5 h-5" />
</button>
<button ... aria-label="Reset zoom to fit pattern" title="Reset Zoom">
<ArrowPathIcon className="w-5 h-5" />
</button>
</div>
- Update all overlays (rounded-xl, border)
- Increase zoom button size (w-10 h-10)
- Add separators between zoom controls
- Larger thread swatches (w-6 h-6)
- Add ARIA labels to buttons
- Use semantic colors
- Improve contrast
NextStepGuide.tsx
File: C:\Users\micro\Documents\dev\respira-web\src\components\NextStepGuide.tsx
Changes:
- Icon size
- Semantic colors
- Border styling
Line 31-53 - Informational messages:
// BEFORE
<div className="bg-blue-50 border-l-4 border-blue-600 p-6 rounded-lg shadow-md">
<div className="flex items-start gap-4">
<InformationCircleIcon className="w-8 h-8 text-blue-600 flex-shrink-0 mt-1" />
// AFTER
<div className="bg-info-bg border-l-4 border-info p-6 rounded-lg shadow-md">
<div className="flex items-start gap-4">
<InformationCircleIcon className="w-10 h-10 text-info flex-shrink-0 mt-1" />
Line 59-87 - Error messages:
// BEFORE
<div className="bg-red-50 border-l-4 border-red-600 p-6 rounded-lg shadow-md">
<div className="flex items-start gap-4">
<ExclamationTriangleIcon className="w-8 h-8 text-red-600 flex-shrink-0 mt-1" />
// AFTER
<div className="bg-danger-bg border-l-4 border-danger p-6 rounded-lg shadow-md">
<div className="flex items-start gap-4">
<ExclamationTriangleIcon className="w-10 h-10 text-danger flex-shrink-0 mt-1" />
Apply similar changes to all state messages (lines 92-299)
- Increase icon size (w-10 h-10)
- Use semantic colors (info, danger, warning, success)
- Ensure consistent styling across all states
- Verify border colors match semantic tokens
Testing Checklist
After completing all component updates, test:
Visual Tests
- All buttons have consistent rounded-lg corners
- All buttons show hover state (color change, shadow)
- All buttons show active state (scale down)
- Disabled buttons are gray, not grayscale filtered
- Colors are consistent (no stray blue-600/700)
- Spacing looks balanced
- Section headers stand out clearly
Interaction Tests
- Tab through interface - all interactive elements show focus ring
- Click buttons - feel responsive with scale feedback
- Hover buttons - smooth color transitions
- Touch on mobile - 44px touch targets work well
- Zoom controls - easy to tap, clear feedback
Accessibility Tests
- Screen reader announces progress bars correctly
- Button ARIA labels are present and clear
- Color contrast meets WCAG AA (4.5:1 text, 3:1 UI)
- Focus states visible on all elements
- Status conveyed by more than color alone
Responsive Tests
- Mobile: Single column layout works
- Tablet: Grid layout switches correctly
- Desktop: Full two-column layout
- WorkflowStepper readable on all sizes
- Color blocks scroll on mobile
State Tests
- Not connected: NextStepGuide shows step 1
- Connected: Components appear correctly
- Pattern loaded: Preview displays
- Uploading: Progress bar animates with shimmer
- Sewing: Color blocks highlight correctly
- Complete: Success states show green
Estimated Time per Component
| Component | Time | Complexity |
|---|---|---|
| Setup (tokens) | 10 min | Low |
| App.tsx | 10 min | Low |
| WorkflowStepper | 15 min | Medium |
| MachineConnection | 20 min | Medium |
| FileUpload | 25 min | High |
| ProgressMonitor | 35 min | High |
| PatternCanvas | 20 min | Medium |
| NextStepGuide | 15 min | Low |
| Total | ~2.5 hours |
Quick Win Order
If you have limited time, implement in this order for maximum impact:
- Setup + App.tsx (20 min) - Foundation
- MachineConnection buttons (10 min) - Most visible
- ProgressMonitor color blocks (20 min) - High impact
- WorkflowStepper (15 min) - Always visible when connected
- FileUpload pattern grid (15 min) - Clear improvement
- PatternCanvas zoom controls (10 min) - Frequently used
- All other buttons (15 min) - Consistency
- Polish and test (20 min) - Final touches
1.5 hour version: Do steps 1-4 2 hour version: Do steps 1-6 Full version: All steps
Common Pitfalls to Avoid
- Don't mix old and new colors - Replace all instances at once per component
- Don't forget ARIA labels - Add to all icon buttons
- Don't skip focus states - Critical for accessibility
- Don't use grayscale filter - Use neutral-300 background instead
- Don't make text too small - Minimum 12px (text-xs)
- Don't forget active states - Add scale-[0.98] to buttons
- Don't skip testing - Test all states before moving to next component
Success Criteria
You'll know the update is successful when:
- No blue-600/700 classes remain (except as fallbacks)
- No grayscale filters on disabled buttons
- All buttons have focus:ring-2
- All progress bars have shimmer effect
- Color blocks visually distinct (completed/current/upcoming)
- Touch targets minimum 44px
- Consistent rounded-lg on all buttons
- Semantic color tokens used throughout
- ARIA labels on all icon buttons
- Interface feels more polished and professional
Good luck with the implementation! Refer to UI_DESIGN_ANALYSIS.md for detailed rationale and QUICK_UI_IMPROVEMENTS.md for condensed code snippets.