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
This commit is contained in:
2026-03-15 00:41:11 +05:30
parent 94506ccb00
commit 7723b302ea
4 changed files with 166 additions and 8 deletions
+159
View File
@@ -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; }