Add lightbox for all preview images (component, grid cell, PDF thumbs)
Click any thumbnail to open full-size in overlay. Click backdrop or press Escape to close. PDF thumbs now clickable too. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -179,13 +179,20 @@ function build_image_grid(grid_el, images, on_delete) {
|
|||||||
grid_el.replaceChildren(...images.map(img_id => {
|
grid_el.replaceChildren(...images.map(img_id => {
|
||||||
const thumb = clone('t-image-thumb');
|
const thumb = clone('t-image-thumb');
|
||||||
const link = qs(thumb, '.thumb-link');
|
const link = qs(thumb, '.thumb-link');
|
||||||
link.href = `/img/${img_id}`;
|
link.href = '#';
|
||||||
|
link.addEventListener('click', (e) => { e.preventDefault(); open_lightbox(`/img/${img_id}`); });
|
||||||
qs(thumb, '.thumb-img').src = `/img/${img_id}`;
|
qs(thumb, '.thumb-img').src = `/img/${img_id}`;
|
||||||
qs(thumb, '.thumb-delete').addEventListener('click', () => on_delete(img_id));
|
qs(thumb, '.thumb-delete').addEventListener('click', () => on_delete(img_id));
|
||||||
return thumb;
|
return thumb;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function open_lightbox(src) {
|
||||||
|
const lb = document.getElementById('lightbox');
|
||||||
|
document.getElementById('lightbox-img').src = src;
|
||||||
|
lb.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Render: Components section (split pane)
|
// Render: Components section (split pane)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -355,6 +362,8 @@ function render_detail_panel() {
|
|||||||
thumb.className = 'pdf-thumb';
|
thumb.className = 'pdf-thumb';
|
||||||
thumb.src = `/pdf/${pdf.thumb_filename}`;
|
thumb.src = `/pdf/${pdf.thumb_filename}`;
|
||||||
thumb.alt = '';
|
thumb.alt = '';
|
||||||
|
thumb.style.cursor = 'zoom-in';
|
||||||
|
thumb.addEventListener('click', () => open_lightbox(`/pdf/${pdf.thumb_filename}`));
|
||||||
row.appendChild(thumb);
|
row.appendChild(thumb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,9 +446,8 @@ function build_detail_inv_entry(entry) {
|
|||||||
if (cell_filename) {
|
if (cell_filename) {
|
||||||
const thumb = document.createElement('a');
|
const thumb = document.createElement('a');
|
||||||
thumb.className = 'thumb-link cell-thumb-link';
|
thumb.className = 'thumb-link cell-thumb-link';
|
||||||
thumb.href = `/img/${cell_filename}`;
|
thumb.href = '#';
|
||||||
thumb.target = '_blank';
|
thumb.addEventListener('click', (e) => { e.preventDefault(); open_lightbox(`/img/${cell_filename}`); });
|
||||||
thumb.rel = 'noopener';
|
|
||||||
const img = document.createElement('img');
|
const img = document.createElement('img');
|
||||||
img.className = 'thumb-img';
|
img.className = 'thumb-img';
|
||||||
img.src = `/img/${cell_filename}`;
|
img.src = `/img/${cell_filename}`;
|
||||||
@@ -1376,6 +1384,8 @@ function render_file_picker_list() {
|
|||||||
thumb.className = 'fp-thumb';
|
thumb.className = 'fp-thumb';
|
||||||
thumb.src = `/pdf/${pdf.thumb_filename}`;
|
thumb.src = `/pdf/${pdf.thumb_filename}`;
|
||||||
thumb.alt = '';
|
thumb.alt = '';
|
||||||
|
thumb.style.cursor = 'zoom-in';
|
||||||
|
thumb.addEventListener('click', () => open_lightbox(`/pdf/${pdf.thumb_filename}`));
|
||||||
row.appendChild(thumb);
|
row.appendChild(thumb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1940,6 +1950,11 @@ async function init() {
|
|||||||
btn.addEventListener('click', () => navigate('/' + btn.dataset.section));
|
btn.addEventListener('click', () => navigate('/' + btn.dataset.section));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Lightbox
|
||||||
|
const lightbox = document.getElementById('lightbox');
|
||||||
|
lightbox.addEventListener('click', () => { lightbox.hidden = true; });
|
||||||
|
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') lightbox.hidden = true; });
|
||||||
|
|
||||||
// Maintenance menu
|
// Maintenance menu
|
||||||
const maint_toggle = document.getElementById('maint-toggle');
|
const maint_toggle = document.getElementById('maint-toggle');
|
||||||
const maint_dropdown = document.getElementById('maint-dropdown');
|
const maint_dropdown = document.getElementById('maint-dropdown');
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main id="main"></main>
|
<main id="main"></main>
|
||||||
|
<div id="lightbox" hidden>
|
||||||
|
<img id="lightbox-img" alt="">
|
||||||
|
</div>
|
||||||
<script type="module" src="/app.mjs"></script>
|
<script type="module" src="/app.mjs"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -148,6 +148,31 @@ nav {
|
|||||||
background: var(--surface-raised);
|
background: var(--surface-raised);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===== LIGHTBOX ===== */
|
||||||
|
|
||||||
|
#lightbox {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0,0,0,0.85);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
cursor: zoom-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lightbox[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lightbox-img {
|
||||||
|
max-width: 90vw;
|
||||||
|
max-height: 90vh;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 8px 40px rgba(0,0,0,0.6);
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== MAIN ===== */
|
/* ===== MAIN ===== */
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
|
|||||||
Reference in New Issue
Block a user