Support optional captions

This commit is contained in:
Andy Smith
2025-08-04 13:05:39 -05:00
parent 4c505aeb23
commit 34f926ffca
4 changed files with 44 additions and 16 deletions
+29 -12
View File
@@ -1,6 +1,7 @@
@layer components {
.lightbox {
--dialog-duration: 350ms;
--lightbox-padding: 3vmin;
background-color: transparent;
block-size: 100dvh;
@@ -11,7 +12,8 @@
max-height: unset;
max-width: unset;
overflow: hidden;
padding: var(--block-space-half) var(--inline-space);
padding: var(--lightbox-padding);
text-align: center;
&::backdrop {
-webkit-backdrop-filter: blur(16px);
@@ -19,13 +21,6 @@
background-color: oklch(var(--lch-black) / 50%);
}
img {
animation: slide-down var(--dialog-duration);
animation-fill-mode: forwards;
display: block;
margin: auto;
}
/* Closed state */
&,
&::backdrop {
@@ -43,7 +38,7 @@
opacity: 0;
}
img {
.lightbox__figure {
animation: slide-up var(--dialog-duration);
}
}
@@ -54,10 +49,32 @@
position: absolute;
}
.lightbox__figure {
align-self: stretch;
animation-fill-mode: forwards;
animation: slide-down var(--dialog-duration);
display: flex;
flex-direction: column;
gap: var(--lightbox-padding);
margin: 0 auto;
max-block-size: 100%;
img {
object-fit: contain;
}
}
.lightbox__caption {
color: var(--color-ink-inverted);
&:empty {
display: none;
}
}
.lightbox__image {
grid-area: 1/1;
max-inline-size: calc(100dvw - (var(--inline-space) * 2));
max-block-size: calc(100dvh - (var(--block-space) * 2));
flex: 1;
min-block-size: 0;
}
/* Prevent body from scrolling when lightbox is open */
@@ -1,7 +1,7 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "image", "dialog", "zoomedImage" ]
static targets = [ "caption", "image", "dialog", "zoomedImage" ]
connect() {
this.dialogTarget.addEventListener('transitionend', this.handleTransitionEnd.bind(this))
@@ -25,10 +25,18 @@ export default class extends Controller {
reset() {
this.zoomedImageTarget.src = ""
this.captionTarget.innerText = ""
this.dispatch('closed')
}
#set(target) {
this.zoomedImageTarget.src = target.href
const imageSrc = target.href
const caption = target.dataset.lightboxCaptionValue
this.zoomedImageTarget.src = imageSrc
if (caption) {
this.captionTarget.innerText = caption
}
}
}
@@ -4,4 +4,3 @@
<span class="for-screen-reader">Zoom background image</span>
<% end %>
<% end %>
+5 -1
View File
@@ -1,6 +1,10 @@
<%= tag.dialog class:"lightbox", aria: { label: "Image Viewer (Press escape to close)" },
data: { controller: "dialog", dialog_target: "dialog", dialog_modal_value: "true", lightbox_target: "dialog" } do %>
<img src="" class="lightbox__image" data-lightbox-target="zoomedImage" />
<figure class="lightbox__figure">
<img src="" class="lightbox__image" data-lightbox-target="zoomedImage" />
<figcaption class="lightbox__caption" data-lightbox-target="caption"></figcaption>
</figure>
<div class="lightbox__btn">
<button class="btn fill-white" title="Close (esc)" data-action="dialog#close keydown.esc->dialog#close:stop" data-controller="hotkey">