From 2d33eb40ab837e17be1fe8c18131de5e76c37cf1 Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Sat, 6 Dec 2025 20:12:46 +0100 Subject: [PATCH] Implement comprehensive dark mode support and improve pattern visibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dark Mode Implementation: - Add Tailwind config with darkMode: 'media' for system preference detection - Update all 9 components with 200+ dark mode variants - Semantic color backgrounds with semi-transparent overlays in dark mode - Proper text contrast (gray-900/gray-100) for readability - Enhanced borders, shadows, and focus rings for dark backgrounds Component Dark Mode Updates: - App.tsx: Header gradient, error banners, empty states - MachineConnection: Status badges with proper dark variants for all states - FileUpload: Pattern info cards, thread swatches, upload progress - PatternCanvas: Canvas background, overlays, zoom controls - ProgressMonitor: Color blocks, progress bars, state indicators with colored icons - NextStepGuide: All status boxes (blue/yellow/cyan/green/red) - WorkflowStepper: Progress indicators and step states - ConfirmDialog: Modal overlays and dialog backgrounds - KonvaComponents: Grid lines and origin markers Pattern Visibility Improvements: - Pattern shows full opacity (1.0) when unlocked for easy positioning - Pattern shows reduced opacity (0.75) for unstitched areas when locked/uploading - Helps distinguish completed vs pending stitches during sewing - Pattern locks during upload to prevent accidental repositioning - Canvas dragging disabled when pattern is uploading or uploaded Status Indicator Enhancements: - Machine status badges: All states (idle/active/waiting/complete/error) have dark variants - Progress monitor state icons: Colored icons (blue/yellow/green/red) in both modes - Color blocks: Proper backgrounds and borders for completed/current/pending states - All semantic colors maintain visibility and meaning in dark mode Canvas Lock Behavior: - Pattern locked during upload (uploadProgress > 0 && < 100) - Pattern locked after upload (patternUploaded = true) - Lock indicator shows amber background with lock icon - Cursor changes prevent confusion about draggability - Full opacity during positioning, transparency during progress tracking 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/App.tsx | 49 +++++----- src/components/ConfirmDialog.tsx | 18 ++-- src/components/FileUpload.tsx | 62 ++++++------ src/components/KonvaComponents.tsx | 22 +++-- src/components/MachineConnection.tsx | 58 ++++++------ src/components/NextStepGuide.tsx | 136 +++++++++++++-------------- src/components/PatternCanvas.tsx | 54 ++++++----- src/components/ProgressMonitor.tsx | 98 +++++++++---------- src/components/WorkflowStepper.tsx | 12 +-- tailwind.config.js | 12 +++ 10 files changed, 272 insertions(+), 249 deletions(-) create mode 100644 tailwind.config.js diff --git a/src/App.tsx b/src/App.tsx index 5a2dff3..0ab6967 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -87,8 +87,8 @@ function App() { }, [machine.machineStatus, machine.patternInfo, machine.isConnected]); return ( -
-
+
+

SKiTCH Controller

@@ -109,9 +109,9 @@ function App() {
{/* Global errors */} {machine.error && ( -
+
- +
@@ -121,9 +121,9 @@ function App() {
)} {pyodideError && ( -
+
- +
@@ -133,9 +133,9 @@ function App() {
)} {!pyodideReady && !pyodideError && ( -
+
- + @@ -199,44 +199,45 @@ function App() { initialPatternOffset={patternOffset} onPatternOffsetChange={handlePatternOffsetChange} patternUploaded={patternUploaded} + isUploading={machine.uploadProgress > 0 && machine.uploadProgress < 100} /> ) : ( -
-

Pattern Preview

-
+
+

Pattern Preview

+
{/* Decorative background pattern */} -
-
-
-
+
+
+
+
- + -
- +
+
-

No Pattern Loaded

-

+

No Pattern Loaded

+

Connect to your machine and choose a PES embroidery file to see your design preview

-
+
-
+
Drag to Position
-
+
Zoom & Pan
-
+
Real-time Preview
diff --git a/src/components/ConfirmDialog.tsx b/src/components/ConfirmDialog.tsx index bad1fa0..4035acd 100644 --- a/src/components/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog.tsx @@ -38,24 +38,24 @@ export function ConfirmDialog({ if (!isOpen) return null; return ( -
+
e.stopPropagation()} role="dialog" aria-labelledby="dialog-title" aria-describedby="dialog-message" > -
-

{title}

+
+

{title}

-

{message}

+

{message}

-
+
- {Math.round(stageScale * 100)}% - -
diff --git a/src/components/ProgressMonitor.tsx b/src/components/ProgressMonitor.tsx index 0f6c12f..418d42b 100644 --- a/src/components/ProgressMonitor.tsx +++ b/src/components/ProgressMonitor.tsx @@ -97,41 +97,41 @@ export function ProgressMonitor({ ); const stateIndicatorColors = { - idle: 'bg-blue-50 border-l-blue-600', - info: 'bg-blue-50 border-l-blue-600', - active: 'bg-yellow-50 border-l-yellow-500', - waiting: 'bg-yellow-50 border-l-yellow-500', - warning: 'bg-yellow-50 border-l-yellow-500', - complete: 'bg-green-50 border-l-green-600', - success: 'bg-green-50 border-l-green-600', - interrupted: 'bg-red-50 border-l-red-600', - error: 'bg-red-50 border-l-red-600', - danger: 'bg-red-50 border-l-red-600', + idle: 'bg-blue-50 dark:bg-blue-900/20 border-l-blue-600', + info: 'bg-blue-50 dark:bg-blue-900/20 border-l-blue-600', + active: 'bg-yellow-50 dark:bg-yellow-900/20 border-l-yellow-500', + waiting: 'bg-yellow-50 dark:bg-yellow-900/20 border-l-yellow-500', + warning: 'bg-yellow-50 dark:bg-yellow-900/20 border-l-yellow-500', + complete: 'bg-green-50 dark:bg-green-900/20 border-l-green-600', + success: 'bg-green-50 dark:bg-green-900/20 border-l-green-600', + interrupted: 'bg-red-50 dark:bg-red-900/20 border-l-red-600', + error: 'bg-red-50 dark:bg-red-900/20 border-l-red-600', + danger: 'bg-red-50 dark:bg-red-900/20 border-l-red-600', }; return ( -
-

Sewing Progress

+
+

Sewing Progress

{/* Left Column - Pattern Info & Progress */}
{patternInfo && ( -
+
- Total Stitches - {patternInfo.totalStitches.toLocaleString()} + Total Stitches + {patternInfo.totalStitches.toLocaleString()}
- Est. Time - + Est. Time + {Math.floor(patternInfo.totalTime / 60)}:{String(patternInfo.totalTime % 60).padStart(2, '0')}
- Speed - {patternInfo.speed} spm + Speed + {patternInfo.speed} spm
@@ -140,23 +140,23 @@ export function ProgressMonitor({ {sewingProgress && (
- Progress - {progressPercent.toFixed(1)}% + Progress + {progressPercent.toFixed(1)}%
-
-
+
+
-
+
- Current Stitch - + Current Stitch + {sewingProgress.currentStitch.toLocaleString()} / {patternInfo?.totalStitches.toLocaleString() || 0}
- Time Elapsed - + Time Elapsed + {Math.floor(sewingProgress.currentTime / 60)}:{String(sewingProgress.currentTime % 60).padStart(2, '0')}
@@ -167,12 +167,12 @@ export function ProgressMonitor({ {/* State Visual Indicator */} {patternInfo && (() => { const iconMap = { - ready: , - active: , - waiting: , - complete: , - interrupted: , - error: + ready: , + active: , + waiting: , + complete: , + interrupted: , + error: }; return ( @@ -181,8 +181,8 @@ export function ProgressMonitor({ {iconMap[stateVisual.iconName]}
-
{stateVisual.label}
-
{stateVisual.description}
+
{stateVisual.label}
+
{stateVisual.description}
); @@ -194,7 +194,7 @@ export function ProgressMonitor({ {canResumeSewing(machineStatus) && (