From 7723b302ea84f644fb65d089ba313c52bfeecb81 Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Sun, 15 Mar 2026 00:41:11 +0530 Subject: [PATCH] style: improve CSS organization and add state components CSS improvements: - Remove duplicate CSS reset from styles-modern.css - Add focus-visible styles for sidebar icons - Add error/loading state components (skeleton, spinner, messages) - Add success, warning, info message components - Add dark theme support for new components Code quality: - Replace inline error style with CSS class in renderer.js Amit Haridas --- src/renderer.js | 2 +- src/styles-modern.css | 8 +-- src/styles-sidebar.css | 5 ++ src/styles.css | 159 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 8 deletions(-) diff --git a/src/renderer.js b/src/renderer.js index 833b8b5..e28dd6d 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -381,7 +381,7 @@ class TabManager { try { // Check if libraries are available if (!marked || !DOMPurify) { - preview.innerHTML = '

Error: Required libraries (marked/DOMPurify) not loaded. Check internet connection.

'; + preview.innerHTML = '
⚠️
Libraries Not Loaded
Required libraries (marked/DOMPurify) could not be loaded. Please check your installation.
'; return; } const html = marked.parse(tab.content); diff --git a/src/styles-modern.css b/src/styles-modern.css index f38a7ef..5bb51c4 100644 --- a/src/styles-modern.css +++ b/src/styles-modern.css @@ -39,13 +39,7 @@ --transition-ease: cubic-bezier(0.4, 0, 0.2, 1); } -/* Reset & Base */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - +/* Base styles - Reset is in styles.css */ body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; overflow: hidden; diff --git a/src/styles-sidebar.css b/src/styles-sidebar.css index c32aad6..6b3f36a 100644 --- a/src/styles-sidebar.css +++ b/src/styles-sidebar.css @@ -57,6 +57,11 @@ box-shadow: inset 3px 0 0 var(--primary-dark, #5661b3); } +.sidebar-icon:focus-visible { + outline: 2px solid var(--primary-dark, #5661b3); + outline-offset: 2px; +} + .sidebar-panel { width: 280px; background: var(--gray-50, #f9fafb); diff --git a/src/styles.css b/src/styles.css index acd1123..9f48055 100644 --- a/src/styles.css +++ b/src/styles.css @@ -277,6 +277,165 @@ body { line-height: 1.6; } +/* ============================================ + Error & Loading State Components + ============================================ */ + +/* Preview Error State */ +.preview-error { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 40px 20px; + color: #dc3545; + text-align: center; + min-height: 200px; +} + +.preview-error-icon { + font-size: 48px; + margin-bottom: 16px; + opacity: 0.8; +} + +.preview-error-title { + font-size: 18px; + font-weight: 600; + margin-bottom: 8px; +} + +.preview-error-message { + font-size: 14px; + color: #666; + max-width: 400px; + line-height: 1.5; +} + +/* Loading State */ +.loading-spinner { + display: inline-block; + width: 20px; + height: 20px; + border: 2px solid var(--gray-200, #e5e7eb); + border-top-color: var(--primary-dark, #5661b3); + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +.loading-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(255, 255, 255, 0.8); + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + gap: 12px; + z-index: 100; +} + +.loading-text { + font-size: 14px; + color: var(--gray-600, #4b5563); +} + +/* Skeleton Loading */ +.skeleton { + background: linear-gradient(90deg, var(--gray-100, #f3f4f6) 25%, var(--gray-200, #e5e7eb) 50%, var(--gray-100, #f3f4f6) 75%); + background-size: 200% 100%; + animation: shimmer 1.5s infinite; + border-radius: 4px; +} + +@keyframes shimmer { + 0% { background-position: 200% 0; } + 100% { background-position: -200% 0; } +} + +.skeleton-text { + height: 14px; + margin-bottom: 8px; +} + +.skeleton-text:last-child { + width: 60%; +} + +/* Success State */ +.success-message { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 16px; + background: #d1fae5; + color: #065f46; + border-radius: 6px; + font-size: 14px; +} + +.success-message svg { + width: 18px; + height: 18px; + flex-shrink: 0; +} + +/* Warning State */ +.warning-message { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 16px; + background: #fef3c7; + color: #92400e; + border-radius: 6px; + font-size: 14px; +} + +.warning-message svg { + width: 18px; + height: 18px; + flex-shrink: 0; +} + +/* Info State */ +.info-message { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 16px; + background: #dbeafe; + color: #1e40af; + border-radius: 6px; + font-size: 14px; +} + +.info-message svg { + width: 18px; + height: 18px; + flex-shrink: 0; +} + +/* Dark theme adjustments for states */ +body[class*="dark"] .preview-error-message { + color: #9ca3af; +} + +body[class*="dark"] .loading-overlay { + background: rgba(0, 0, 0, 0.8); +} + +body[class*="dark"] .loading-text { + color: #9ca3af; +} + /* Bottom Panel (REPL Output) */ .bottom-panel { display: flex; flex-direction: column; border-top: 1px solid var(--gray-200, #e5e7eb); flex-shrink: 0; } .bottom-panel.collapsed { height: 0; overflow: hidden; border: none; }