Visual polish: theme-aware colors, collapsible cards, skeletons, hover consistency
Templates only, no backend changes: - Fixed the real bug: JS-generated status/loading text and a few component styles used hardcoded hex (#007acc, #999/#666, #28a745, #ff6b6b) instead of the CSS variables the theme system already provides, so they didn't track the user's chosen theme/accent - most visible on Light or any named theme other than the default. Added --success/--error to all 5 templates' :root blocks and replaced every non-:root occurrence. Left the .lesson-type badge colors and generic UI chrome grays alone (intentional, not theme-dependent). Verified live by switching to Nord and Light themes. - Dashboard cards (Library Stats, Next Up, Pick Back Up, Recently Added, Continue Watching, Recently Viewed) are now collapsible, state remembered per device via localStorage - the no-course dashboard had grown to 7 stacked cards. - Course page's three action buttons get consistent compact sizing and icons instead of a plain stack. - Library browser and transcript search show shimmering skeleton rows instead of bare "Loading..."/"Searching..." text while a fetch is in flight. - Hover treatment made consistent: transcript results get the same lift .lesson-item already had, heatmap cells get a GitHub-style hover scale-up, and Notes Hub links get a background-chip hover. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+21
-19
@@ -22,6 +22,8 @@
|
||||
--font-size-base: 16px;
|
||||
--container-max-width: 1600px;
|
||||
--radius: 8px;
|
||||
--success: #28a745;
|
||||
--error: #ff6b6b;
|
||||
}
|
||||
[data-theme="light"] {
|
||||
--bg-primary: #f2f2f2;
|
||||
@@ -279,7 +281,7 @@
|
||||
.curate-row-status {
|
||||
flex-basis: 100%;
|
||||
font-size: 0.8em;
|
||||
color: #ff6b6b;
|
||||
color: var(--error);
|
||||
}
|
||||
.bulk-rename-row {
|
||||
display: flex;
|
||||
@@ -307,7 +309,7 @@
|
||||
}
|
||||
#save-status {
|
||||
font-size: 0.9em;
|
||||
color: #28a745;
|
||||
color: var(--success);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
@@ -658,7 +660,7 @@
|
||||
renderCurateLevel(data, container);
|
||||
})
|
||||
.catch(() => {
|
||||
container.innerHTML = '<p style="color:#ff6b6b;">Could not reach the library scanner.</p>';
|
||||
container.innerHTML = '<p style="color:var(--error);">Could not reach the library scanner.</p>';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -834,7 +836,7 @@
|
||||
const preview = document.getElementById('bulk-rename-preview');
|
||||
preview.innerHTML = '';
|
||||
if (!pattern) {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Enter text to find first.';
|
||||
return;
|
||||
}
|
||||
@@ -847,7 +849,7 @@
|
||||
renderBulkRenamePreview();
|
||||
})
|
||||
.catch(() => {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Could not reach the server.';
|
||||
});
|
||||
}
|
||||
@@ -898,7 +900,7 @@
|
||||
const failed = results.filter(r => !r.success);
|
||||
const activeCourseReset = results.some(r => r.active_course_reset);
|
||||
|
||||
status.style.color = failed.length ? '#ff6b6b' : '#28a745';
|
||||
status.style.color = failed.length ? 'var(--error)' : 'var(--success)';
|
||||
let message = `${succeeded} renamed`;
|
||||
if (failed.length) {
|
||||
message += `, ${failed.length} failed: ` +
|
||||
@@ -919,7 +921,7 @@
|
||||
loadCurateLevel(null, document.getElementById('curate-tree'), true);
|
||||
})
|
||||
.catch(() => {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Could not reach the server.';
|
||||
});
|
||||
}
|
||||
@@ -935,16 +937,16 @@
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
status.style.color = '#28a745';
|
||||
status.style.color = 'var(--success)';
|
||||
status.textContent = '✓ Saved — reload the main page to see it take effect';
|
||||
showSaved();
|
||||
} else {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = data.error || 'Could not save';
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Could not reach the server';
|
||||
});
|
||||
}
|
||||
@@ -955,7 +957,7 @@
|
||||
const coursePath = input.value.trim();
|
||||
|
||||
if (!coursePath) {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Please enter a course path.';
|
||||
return;
|
||||
}
|
||||
@@ -971,16 +973,16 @@
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
status.style.color = '#28a745';
|
||||
status.style.color = 'var(--success)';
|
||||
status.textContent = `✓ Loaded "${data.course_name}" — redirecting...`;
|
||||
setTimeout(() => { window.location.href = '/'; }, 1000);
|
||||
} else {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = data.error || 'Could not load course';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Could not reach the server';
|
||||
});
|
||||
}
|
||||
@@ -1055,17 +1057,17 @@
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
status.style.color = '#28a745';
|
||||
status.style.color = 'var(--success)';
|
||||
status.textContent = 'Saved.';
|
||||
document.getElementById('outline-token').value = '';
|
||||
loadOutlineConfig();
|
||||
} else {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = data.error || 'Could not save.';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Could not reach the server.';
|
||||
});
|
||||
}
|
||||
@@ -1077,11 +1079,11 @@
|
||||
fetch('/api/outline/test')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
status.style.color = data.success ? '#28a745' : '#ff6b6b';
|
||||
status.style.color = data.success ? 'var(--success)' : 'var(--error)';
|
||||
status.textContent = data.success ? 'Connected.' : (data.error || 'Connection failed.');
|
||||
})
|
||||
.catch(() => {
|
||||
status.style.color = '#ff6b6b';
|
||||
status.style.color = 'var(--error)';
|
||||
status.textContent = 'Could not reach the server.';
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user