web/PickerItem: props refactor, fade in images on load

feels really good now
This commit is contained in:
wukko 2025-05-04 15:36:13 +06:00
parent 0cecdc32a6
commit d58155426f
No known key found for this signature in database
GPG Key ID: 3E30B3F26C7B4AA2

View File

@ -10,10 +10,17 @@
import IconPhoto from "@tabler/icons-svelte/IconPhoto.svelte";
import IconGif from "@tabler/icons-svelte/IconGif.svelte";
export let item: DialogPickerItem;
export let number: number;
type Props = {
item: DialogPickerItem;
number: number;
};
let imageLoaded = false;
const { item, number }: Props = $props();
const itemType = $derived(item.type ?? "photo");
let imageLoaded = $state(false);
let hideSkeleton = $state(false);
let validUrl = false;
try {
@ -23,12 +30,19 @@
const isTunnel = validUrl && new URL(item.url).pathname === "/tunnel";
$: itemType = item.type ?? "photo";
const loaded = () => {
imageLoaded = true;
// remove the skeleton after the image is done fading in
setTimeout(() => {
hideSkeleton = true;
}, 200)
}
</script>
<button
class="picker-item"
on:click={() => {
onclick={() => {
if (validUrl) {
downloadFile({
url: item.url,
@ -52,10 +66,10 @@
src={item.thumb ?? item.url}
class:loading={!imageLoaded}
class:video-thumbnail={["video", "gif"].includes(itemType)}
on:load={() => (imageLoaded = true)}
onload={loaded}
alt="{$t(`a11y.dialog.picker.item.${itemType}`)} {number}"
/>
<Skeleton class="picker-image elevated" hidden={imageLoaded} />
<Skeleton class="picker-image elevated" hidden={hideSkeleton} />
</button>
<style>
@ -78,7 +92,6 @@
}
:global(.picker-image) {
display: block;
width: 100%;
height: 100%;
@ -87,10 +100,20 @@
object-fit: cover;
border-radius: inherit;
position: absolute;
z-index: 2;
opacity: 1;
transition: opacity 0.15s;
}
:global(.skeleton) {
z-index: 1;
}
.picker-image.loading {
display: none;
opacity: 0;
}
.picker-image.video-thumbnail {
@ -98,12 +121,12 @@
}
:global(.picker-item:active .picker-image) {
opacity: 0.7;
opacity: 0.75;
}
@media (hover: hover) {
:global(.picker-item:hover .picker-image) {
opacity: 0.7;
:global(.picker-item:hover:not(:active) .picker-image) {
opacity: 0.8;
}
}
@ -113,7 +136,7 @@
background: rgba(0, 0, 0, 0.5);
width: 24px;
height: 24px;
z-index: 9;
z-index: 3;
display: flex;
flex-direction: row;