Finished the Sveltification
Some checks failed
ci/woodpecker/pr/ci Pipeline failed

This commit is contained in:
2026-02-15 23:01:16 -03:00
parent 99cb89d1e8
commit 4f863e5686
17 changed files with 683 additions and 517 deletions

View File

@@ -0,0 +1,140 @@
<script lang="ts">
import type { MediaItem } from '$lib/media';
interface Props {
item: MediaItem | null;
onClose: () => void;
}
let { item, onClose }: Props = $props();
let ref = $state<HTMLDialogElement | null>(null);
$effect(() => {
if (ref && item) {
document.body.style.overflow = 'hidden';
ref.showModal();
} else {
document.body.style.overflow = 'auto';
ref?.close();
}
});
</script>
<dialog
class="lightbox"
aria-hidden="true"
onclose={onClose}
closedby="any"
aria-describedby="lb-caption"
bind:this={ref}
>
{#if item}
<header>
<button
class="lb-close"
aria-label="Close"
onclick={() => ref?.close()}
onkeydown={(e) => {
if (e.key === 'Enter') ref?.close();
}}>&times;</button
>
</header>
<div class="lb-content">
{#if item?.type === 'video'}
<video
src={`/assets/media/videos/${item?.name}.mp4`}
controls
autoplay
>
<track
kind="captions"
src={`/assets/media/videos/${item?.name}-captions.vtt`}
default
/>
</video>
{:else}
<picture>
{#each [{ bp: 'desktop', minWidth: 1024 }, { bp: 'tablet', minWidth: 768 }, { bp: 'mobile', minWidth: 0 }] as breakpoint}
<source
media="(min-width:{breakpoint.minWidth}px)"
srcset={item?.type === 'image'
? `/assets/media/${breakpoint.bp}/${item?.name}@1x.webp 1x, /assets/media/${breakpoint.bp}/${item?.name}.webp 2x`
: `/assets/media/${breakpoint.bp}/${item?.name}_still@1x.webp 1x, /assets/media/${breakpoint.bp}/${item?.name}_still.webp 2x`}
/>
{/each}
<img
src="/assets/media/thumbnail/{item?.name}.webp"
alt={item?.alt.replace(/['']/g, '')}
/>
</picture>
{/if}
</div>
<p id="lb-caption" class="lb-caption">{item?.caption}</p>
{/if}
</dialog>
<style>
.lightbox {
align-items: stretch;
background: var(--surface-elevated);
border: none;
border-radius: 8px;
box-shadow: var(--lightbox-shadow);
display: flex;
flex-direction: column;
gap: 0.5rem;
justify-content: center;
max-width: 90vw;
padding: 0.5rem 1rem;
opacity: 0;
transition: opacity 0.3s;
&::backdrop {
background: var(--lightbox-backdrop);
}
&[open] {
opacity: 1;
}
& img,
& video {
max-width: 90vw;
max-height: 80vh;
border-radius: 8px;
}
}
header {
display: flex;
justify-content: flex-end;
padding: 0.25rem 0.25rem 0 0;
}
.lb-close {
background: none;
border: none;
font-size: 2rem;
color: var(--fg);
}
.lb-content {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
& img {
max-width: 90vw;
max-height: 80vh;
}
}
.lb-caption {
color: var(--fg);
margin-top: 0.5rem;
text-align: center;
max-width: 90vw;
}
</style>