Refactor: replace all BEM CSS with Tailwind utility classes
Remove all BEM component classes (hero__*, card__*, issue-card__*, foot__*, masthead__*, searchpop__*, lb__*) from CSS and templates. Replace with Tailwind v4 utility classes inline in HTML. Create card.html partial to avoid repeating verbose utility strings across grid templates. Rename lightbox CSS to flat lb-* and search popup to sp-*. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+35
-37
@@ -129,16 +129,16 @@
|
||||
const cats = allCats();
|
||||
const tags = allTags();
|
||||
searchPop.innerHTML = `
|
||||
<div class="searchpop__section">
|
||||
<div class="searchpop__label">Categories <small>${cats.length}</small></div>
|
||||
<div class="searchpop__chips">
|
||||
${cats.map(c => `<button class="searchpop__chip" data-jump="/categories/${encodeURIComponent(c.toLowerCase().replace(/[\s,]+/g,'-').replace(/[^a-z0-9-]/g,''))}/"> ${esc(c)}</button>`).join('')}
|
||||
<div class="sp-section">
|
||||
<div class="sp-label">Categories <small>${cats.length}</small></div>
|
||||
<div class="sp-chips">
|
||||
${cats.map(c => `<button class="sp-chip" data-jump="/categories/${encodeURIComponent(c.toLowerCase().replace(/[\s,]+/g,'-').replace(/[^a-z0-9-]/g,''))}/"> ${esc(c)}</button>`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchpop__section">
|
||||
<div class="searchpop__label">Popular tags <small>${tags.length}</small></div>
|
||||
<div class="searchpop__chips">
|
||||
${tags.map(t => `<button class="searchpop__chip" data-jump="/tags/${encodeURIComponent(t.toLowerCase().replace(/[\s,]+/g,'-').replace(/[^a-z0-9-]/g,''))}/"> # ${esc(t)}</button>`).join('')}
|
||||
<div class="sp-section">
|
||||
<div class="sp-label">Popular tags <small>${tags.length}</small></div>
|
||||
<div class="sp-chips">
|
||||
${tags.map(t => `<button class="sp-chip" data-jump="/tags/${encodeURIComponent(t.toLowerCase().replace(/[\s,]+/g,'-').replace(/[^a-z0-9-]/g,''))}/"> # ${esc(t)}</button>`).join('')}
|
||||
</div>
|
||||
</div>`;
|
||||
searchPop.dataset.open = 'true';
|
||||
@@ -147,17 +147,17 @@
|
||||
const hits = INDEX(q) || [];
|
||||
const terms = q.toLowerCase().split(/\s+/).filter(t => t.length > 1);
|
||||
if (!hits.length) {
|
||||
searchPop.innerHTML = `<div class="searchpop__section"><p style="color:var(--ink-soft);font-size:13px;font-style:italic">No plates match — try <em>gothic</em>, <em>warrior</em>, or <em>neon</em>.</p></div>`;
|
||||
searchPop.innerHTML = `<div class="sp-section"><p style="color:var(--ink-soft);font-size:13px;font-style:italic">No plates match — try <em>gothic</em>, <em>warrior</em>, or <em>neon</em>.</p></div>`;
|
||||
searchPop.dataset.open = 'true';
|
||||
return;
|
||||
}
|
||||
const shown = hits.slice(0, 6);
|
||||
searchPop.innerHTML = `
|
||||
<div class="searchpop__section">
|
||||
<div class="searchpop__label">Plates <small>${hits.length}</small></div>
|
||||
<div class="searchpop__hits">
|
||||
<div class="sp-section">
|
||||
<div class="sp-label">Plates <small>${hits.length}</small></div>
|
||||
<div class="sp-hits">
|
||||
${shown.map(p => `
|
||||
<button class="searchpop__hit" data-jump="${esc(p.url)}">
|
||||
<button class="sp-hit" data-jump="${esc(p.url)}">
|
||||
${p.thumb ? `<img src="${esc(p.thumb)}" alt="" loading="lazy" />` : '<div style="width:44px;height:66px;background:var(--paper-2)"></div>'}
|
||||
<div>
|
||||
<div class="t">${highlight(p.title, terms)}</div>
|
||||
@@ -241,14 +241,13 @@
|
||||
if (!lbTrack) return;
|
||||
lbTrack.innerHTML = lbList.map((p, i) => {
|
||||
const imgSrc = p.card || p.thumb || '';
|
||||
return `<div class="lb__slide" data-i="${i}">
|
||||
<div class="lb__frame">
|
||||
<img class="lb__img" src="${esc(imgSrc)}" alt="${esc(p.title)}" loading="lazy" />
|
||||
return `<div class="lb-slide" data-i="${i}">
|
||||
<div class="lb-frame">
|
||||
<img class="lb-img" src="${esc(imgSrc)}" alt="${esc(p.title)}" loading="lazy" />
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
lbBuilt = true;
|
||||
// Preload neighbors
|
||||
preloadNeighbors(lbIdx);
|
||||
}
|
||||
|
||||
@@ -271,7 +270,7 @@
|
||||
[-1, 0, 1, 2].forEach(d => {
|
||||
const ni = idx + d;
|
||||
if (ni < 0 || ni >= lbList.length) return;
|
||||
const slide = lbTrack.querySelector(`.lb__slide[data-i="${ni}"]`);
|
||||
const slide = lbTrack.querySelector(`.lb-slide[data-i="${ni}"]`);
|
||||
if (!slide) return;
|
||||
const img = slide.querySelector('img');
|
||||
if (img && !img.src) img.src = lbList[ni].card || lbList[ni].thumb || '';
|
||||
@@ -283,22 +282,22 @@
|
||||
const cats = (p.categories || []).join(', ');
|
||||
const tags = (p.tags || []).slice(0, 8);
|
||||
lbMeta.innerHTML = `
|
||||
<div class="lb__cat">${esc(cats)}</div>
|
||||
<h2 class="lb__title">${esc(p.title)}</h2>
|
||||
<p class="lb__desc">${esc(p.description)}</p>
|
||||
<dl class="lb__factgrid">
|
||||
<div class="lb__fact"><dt>Plate</dt><dd>№ ${esc(p.id)}</dd></div>
|
||||
<div class="lb__fact"><dt>Issue</dt><dd><a href="/issues/${esc(p.issue || '01')}/" style="color:inherit;border-bottom:1px solid currentColor">№ ${esc(p.issue || '01')}</a></dd></div>
|
||||
<div class="lb__fact"><dt>Category</dt><dd>${esc((p.categories||['—'])[0])}</dd></div>
|
||||
<div class="lb-cat">${esc(cats)}</div>
|
||||
<h2 class="lb-title">${esc(p.title)}</h2>
|
||||
<p class="lb-desc">${esc(p.description)}</p>
|
||||
<dl class="lb-facts">
|
||||
<div class="lb-fact"><dt>Plate</dt><dd>№ ${esc(p.id)}</dd></div>
|
||||
<div class="lb-fact"><dt>Issue</dt><dd><a href="/issues/${esc(p.issue || '01')}/" style="color:inherit;border-bottom:1px solid currentColor">№ ${esc(p.issue || '01')}</a></dd></div>
|
||||
<div class="lb-fact"><dt>Category</dt><dd>${esc((p.categories||['—'])[0])}</dd></div>
|
||||
</dl>
|
||||
<div class="lb__tags">${tags.map(t => {
|
||||
<div class="lb-tags">${tags.map(t => {
|
||||
const slug = t.toLowerCase().replace(/[\s,]+/g, '-').replace(/[^a-z0-9-]/g, '');
|
||||
return `<a class="lb__tag" href="/tags/${slug}/"># ${esc(t)}</a>`;
|
||||
return `<a class="lb-tag" href="/tags/${slug}/"># ${esc(t)}</a>`;
|
||||
}).join('')}</div>
|
||||
<div class="lb__share">
|
||||
<button class="lb__sh lb__sh--primary" id="lbCopy" data-url="${esc(p.url)}">
|
||||
<div class="lb-share">
|
||||
<button class="lb-sh lb-sh-primary" id="lbCopy" data-url="${esc(p.url)}">
|
||||
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.07 0l3-3a5 5 0 1 0-7.07-7.07l-1 1"/><path d="M14 11a5 5 0 0 0-7.07 0l-3 3a5 5 0 1 0 7.07 7.07l1-1"/></svg>
|
||||
<span class="lb__sh-l">Copy link</span>
|
||||
<span class="lb-sh-l">Copy link</span>
|
||||
</button>
|
||||
</div>`;
|
||||
|
||||
@@ -306,8 +305,8 @@
|
||||
const url = new URL(this.dataset.url, location.origin).href;
|
||||
navigator.clipboard.writeText(url).then(() => {
|
||||
this.classList.add('is-ok');
|
||||
this.querySelector('.lb__sh-l').textContent = 'Copied!';
|
||||
setTimeout(() => { this.classList.remove('is-ok'); this.querySelector('.lb__sh-l').textContent = 'Copy link'; }, 2000);
|
||||
this.querySelector('.lb-sh-l').textContent = 'Copied!';
|
||||
setTimeout(() => { this.classList.remove('is-ok'); this.querySelector('.lb-sh-l').textContent = 'Copy link'; }, 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -315,22 +314,22 @@
|
||||
function lbBuildThumbs() {
|
||||
if (!lbThumbs) return;
|
||||
lbThumbs.innerHTML = lbList.map((p, i) =>
|
||||
`<button class="lb__thumb" data-i="${i}" aria-current="${i === lbIdx}" aria-label="${esc(p.title)}">
|
||||
`<button class="lb-thumb" data-i="${i}" aria-current="${i === lbIdx}" aria-label="${esc(p.title)}">
|
||||
<img src="${esc(p.thumb || p.card || '')}" alt="" loading="lazy" />
|
||||
</button>`
|
||||
).join('');
|
||||
lbThumbs.addEventListener('click', e => {
|
||||
const btn = e.target.closest('.lb__thumb');
|
||||
const btn = e.target.closest('.lb-thumb');
|
||||
if (btn) goToSlide(parseInt(btn.dataset.i));
|
||||
});
|
||||
}
|
||||
|
||||
function syncThumbs() {
|
||||
if (!lbThumbs) return;
|
||||
lbThumbs.querySelectorAll('.lb__thumb').forEach((b, i) => {
|
||||
lbThumbs.querySelectorAll('.lb-thumb').forEach((b, i) => {
|
||||
b.setAttribute('aria-current', i === lbIdx ? 'true' : 'false');
|
||||
});
|
||||
const active = lbThumbs.querySelector('.lb__thumb[aria-current="true"]');
|
||||
const active = lbThumbs.querySelector('.lb-thumb[aria-current="true"]');
|
||||
if (active) active.scrollIntoView({ inline: 'center', behavior: 'smooth' });
|
||||
}
|
||||
|
||||
@@ -432,7 +431,6 @@
|
||||
syncTabs();
|
||||
|
||||
// If new page has a slug to open
|
||||
const script = doc.querySelector('script[data-open-slug]');
|
||||
const openSlug = window.__ROUX_OPEN_SLUG = doc.querySelector('[data-open-slug]')?.dataset.openSlug || null;
|
||||
if (openSlug) {
|
||||
const opened = POSTS.find(p => p.slug === openSlug);
|
||||
|
||||
Reference in New Issue
Block a user