Experiment figcaption for *multiple* media's

This commit is contained in:
Lim Chee Aun 2023-10-02 12:21:26 +08:00
parent 9f6236762d
commit 348efe0069
3 changed files with 132 additions and 35 deletions

View file

@ -29,7 +29,7 @@ audio = Audio track
const dataAltLabel = 'ALT'; const dataAltLabel = 'ALT';
const AltBadge = (props) => { const AltBadge = (props) => {
const { alt, lang, ...rest } = props; const { alt, lang, index, ...rest } = props;
if (!alt || !alt.trim()) return null; if (!alt || !alt.trim()) return null;
return ( return (
<button <button
@ -47,6 +47,7 @@ const AltBadge = (props) => {
title="Media description" title="Media description"
> >
{dataAltLabel} {dataAltLabel}
{!!index && <sup>{index}</sup>}
</button> </button>
); );
}; };
@ -60,6 +61,7 @@ function Media({
showOriginal, showOriginal,
autoAnimate, autoAnimate,
showCaption, showCaption,
altIndex,
onClick = () => {}, onClick = () => {},
}) { }) {
const { const {
@ -304,7 +306,9 @@ function Media({
} }
}} }}
/> />
{!showInlineDesc && <AltBadge alt={description} lang={lang} />} {!showInlineDesc && (
<AltBadge alt={description} lang={lang} index={altIndex} />
)}
</> </>
)} )}
</Parent> </Parent>
@ -433,11 +437,13 @@ function Media({
<div class="media-play"> <div class="media-play">
<Icon icon="play" size="xl" /> <Icon icon="play" size="xl" />
</div> </div>
{!showInlineDesc && <AltBadge alt={description} lang={lang} />} {!showInlineDesc && (
<AltBadge alt={description} lang={lang} index={altIndex} />
)}
</> </>
)} )}
{!showOriginal && !showInlineDesc && ( {!showOriginal && !showInlineDesc && (
<AltBadge alt={description} lang={lang} /> <AltBadge alt={description} lang={lang} index={altIndex} />
)} )}
</Parent> </Parent>
</Figure> </Figure>
@ -470,7 +476,9 @@ function Media({
<div class="media-play"> <div class="media-play">
<Icon icon="play" size="xl" /> <Icon icon="play" size="xl" />
</div> </div>
{!showInlineDesc && <AltBadge alt={description} lang={lang} />} {!showInlineDesc && (
<AltBadge alt={description} lang={lang} index={altIndex} />
)}
</> </>
)} )}
</Parent> </Parent>

View file

@ -460,7 +460,7 @@
.status .status
.content-container.has-spoiler:not(.show-spoiler) .content-container.has-spoiler:not(.show-spoiler)
.spoiler .spoiler
~ *:not(.media-container, .card), ~ *:not(.media-container, .card, .media-figure-multiple),
.status .status
.content-container.has-spoiler:not(.show-spoiler) .content-container.has-spoiler:not(.show-spoiler)
.spoiler .spoiler
@ -469,7 +469,7 @@
.status .status
.content-container.has-spoiler:not(.show-spoiler) .content-container.has-spoiler:not(.show-spoiler)
.spoiler .spoiler
~ .media-container ~ :is(.media-container, .media-figure-multiple)
figcaption { figcaption {
filter: blur(5px) invert(0.5); filter: blur(5px) invert(0.5);
image-rendering: crisp-edges; image-rendering: crisp-edges;
@ -483,7 +483,7 @@
.status .status
.content-container.has-spoiler:not(.show-spoiler) .content-container.has-spoiler:not(.show-spoiler)
.spoiler .spoiler
~ .media-container ~ :is(.media-container, .media-figure-multiple)
.media .media
> *, > *,
.status .status
@ -1008,6 +1008,37 @@ body:has(#modal-container .carousel) .status .media img:hover {
white-space: normal; white-space: normal;
} }
.media-figure-multiple {
margin: 0;
padding: 0;
figcaption {
padding: 4px;
font-size: 90%;
color: var(--text-insignificant-color);
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
& > * {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&:hover {
color: var(--text-color);
cursor: pointer;
}
}
sup {
opacity: 0.75;
font-variant-numeric: tabular-nums;
}
}
}
.carousel-item { .carousel-item {
position: relative; position: relative;
} }
@ -1687,6 +1718,13 @@ a.card:is(:hover, :focus):visited {
padding: 4px; padding: 4px;
opacity: 0.65; opacity: 0.65;
sup {
vertical-align: super;
font-weight: normal;
line-height: 0;
padding-left: 2px;
}
&.clickable { &.clickable {
opacity: 0.75; opacity: 0.75;
border-width: 2px; border-width: 2px;

View file

@ -1265,6 +1265,38 @@ function Status({
</button> </button>
)} )}
{!!mediaAttachments.length && ( {!!mediaAttachments.length && (
<MultipleMediaFigure
lang={language}
enabled={
mediaAttachments.length > 1 &&
mediaAttachments.some((media) => !!media.description)
}
captionChildren={() => {
return mediaAttachments.map(
(media, i) =>
!!media.description && (
<div
key={media.id}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
states.showMediaAlt = {
alt: media.description,
lang: language,
};
}}
title={
media.description
? `Media ${i + 1}: ${media.description}`
: undefined
}
>
<sup>{i + 1}</sup> {media.description}
</div>
),
);
}}
>
<div <div
ref={mediaContainerRef} ref={mediaContainerRef}
class={`media-container media-eq${mediaAttachments.length} ${ class={`media-container media-eq${mediaAttachments.length} ${
@ -1280,6 +1312,11 @@ function Status({
autoAnimate={isSizeLarge} autoAnimate={isSizeLarge}
showCaption={mediaAttachments.length === 1} showCaption={mediaAttachments.length === 1}
lang={language} lang={language}
altIndex={
mediaAttachments.length > 1 &&
!!media.description &&
i + 1
}
to={`/${instance}/s/${id}?${ to={`/${instance}/s/${id}?${
withinContext ? 'media' : 'media-only' withinContext ? 'media' : 'media-only'
}=${i + 1}`} }=${i + 1}`}
@ -1293,6 +1330,7 @@ function Status({
/> />
))} ))}
</div> </div>
</MultipleMediaFigure>
)} )}
{!!card && {!!card &&
card?.url !== status.url && card?.url !== status.url &&
@ -1489,6 +1527,19 @@ function Status({
); );
} }
function MultipleMediaFigure(props) {
const { enabled, children, lang, captionChildren } = props;
if (!enabled || !captionChildren) return children;
return (
<figure class="media-figure-multiple">
{children}
<figcaption lang={lang} dir="auto">
{captionChildren?.()}
</figcaption>
</figure>
);
}
function Card({ card, instance }) { function Card({ card, instance }) {
const snapStates = useSnapshot(states); const snapStates = useSnapshot(states);
const { const {