feat(biochem): skeleton loaders for async fetches

Replace plain "Загрузка..." placeholders with shimmer-animated skeletons
matching the actual layout shape:
- library: 12 placeholder cards (canvas + 2 lines)
- reactions: 6 row skeletons (stripe + title + 2 text lines)
- properties: 10 sidebar row shimmers (thumb + 2 lines)
- biochem editor: 4-5 row skeletons for saved-molecules and challenges lists

No existing skeleton classes in ls.css; added local .bc-sk-* helpers per page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-20 19:49:54 +03:00
parent d3b1cd75a0
commit 29ef974e35
4 changed files with 139 additions and 21 deletions
+36 -8
View File
@@ -63,6 +63,28 @@
.type-chip.active { background: rgba(155,93,229,.18); border-color: rgba(155,93,229,.6); color: #c084fc; }
.filter-count { font-size: 0.76rem; color: #444; margin-left: auto; white-space: nowrap; font-weight: 600; }
/* ── Shimmer skeleton ── */
@keyframes bc-shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.bc-sk {
background: linear-gradient(90deg,
rgba(255,255,255,0.04) 0%,
rgba(255,255,255,0.10) 50%,
rgba(255,255,255,0.04) 100%);
background-size: 200% 100%;
animation: bc-shimmer 1.6s infinite;
border-radius: 8px;
}
.bc-sk-line { height: 12px; margin: 5px 0; }
.bc-sk-line.sm { width: 60%; }
.bc-sk-line.md { width: 80%; }
.bc-sk-row { display: flex; gap: 12px; padding: 14px 16px; border-bottom: 1px solid rgba(255,255,255,.05);
border-radius: 12px; margin-bottom: 10px; border: 1px solid rgba(255,255,255,.06); }
.bc-sk-row .bc-sk-avatar { width: 4px; height: auto; border-radius: 4px; flex-shrink: 0; }
.bc-sk-row .bc-sk-text { flex: 1; }
/* ── Scroll area ── */
.rxn-scroll { flex: 1; overflow-y: auto; padding: 18px 20px 40px; }
.rxn-scroll::-webkit-scrollbar { width: 5px; }
@@ -330,14 +352,7 @@
<!-- Content -->
<div class="rxn-scroll" id="rxn-scroll">
<div id="rxn-list">
<div class="rxn-empty">
<svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.3">
<path d="M9 3H5a2 2 0 00-2 2v4m6-6h10a2 2 0 012 2v4M9 3v18m0 0h10a2 2 0 002-2V9M9 21H5a2 2 0 01-2-2V9m0 0h18"/>
</svg>
<p>Загрузка реакций…</p>
</div>
</div>
<div id="rxn-list"></div>
</div>
</div>
</div>
@@ -464,7 +479,20 @@ let molCache = {};
let filterType = '';
let filterTopic = '';
function bcSkReactions(n = 6) {
return Array.from({length: n}, () => `
<div class="bc-sk-row">
<div class="bc-sk bc-sk-avatar" style="width:4px;border-radius:4px"></div>
<div class="bc-sk-text">
<div class="bc-sk bc-sk-line md"></div>
<div class="bc-sk bc-sk-line sm"></div>
<div class="bc-sk bc-sk-line" style="width:70%;height:10px;margin-top:8px;opacity:.6"></div>
</div>
</div>`).join('');
}
async function init() {
document.getElementById('rxn-list').innerHTML = bcSkReactions(6);
try {
allRxns = await LS.biochemGetReactions();
document.getElementById('subtitle').textContent = `${allRxns.length} реакций в базе`;