chore: milder birthday memory text (#32163)

chore: milder birthday memory text (#32124)

* chore: better birthday memories style

* chore: flame animation

* multicolor cake

(cherry picked from commit 22a5af0ee90179ba57cae11b60fdcb926282b338)

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
immich-push-o-matic[bot]
2026-10-06 13:32:50 +00:00
committed by GitHub
co-authored by Alex
parent 3eec251596
commit bc87d064de
2 changed files with 47 additions and 6 deletions
@@ -2,7 +2,7 @@
import type { ComponentProps } from 'svelte';
import { Confetti } from 'svelte-confetti';
const props: ComponentProps<typeof Confetti> = $props();
const { amount = 50, ...props }: ComponentProps<typeof Confetti> = $props();
const colorArray = [
'var(--color-logo-red)',
@@ -11,6 +11,12 @@
'var(--color-logo-blue)',
'var(--color-logo-green)',
];
// lib supports one shape per instance
const shapes = [{ rounded: false }, { rounded: true }];
const amountPerShape = $derived(Math.round(amount / shapes.length));
</script>
<Confetti {colorArray} disableForReducedMotion {...props} />
{#each shapes as shape, i (i)}
<Confetti {colorArray} disableForReducedMotion amount={amountPerShape} {...shape} {...props} />
{/each}
@@ -16,10 +16,12 @@
const isBirthday = $derived(item.type === MemoryType.Birthday);
let confettiCount = $state(0);
const [flamePath, bottomLayerPath, topLayerPath] = mdiCakeVariant.split(/(?=M)/, 3);
</script>
<a
class="relative me-2 inline-block aspect-3/4 h-54 rounded-xl shadow-sm last:me-0 max-md:h-37.5 md:me-4 md:aspect-4/3 xl:aspect-video {className}"
class="group relative me-2 inline-block aspect-3/4 h-54 rounded-xl shadow-sm last:me-0 max-md:h-37.5 md:me-4 md:aspect-4/3 xl:aspect-video {className}"
href={item.href}
onmouseenter={() => isBirthday && confettiCount++}
>
@@ -32,10 +34,25 @@
<div
class="absolute inset-s-0 top-0 size-full rounded-xl bg-linear-to-t from-black/40 via-transparent to-transparent transition-all hover:bg-black/20"
></div>
<p class="absolute inset-s-4 bottom-2 flex items-center gap-2 text-lg text-white max-md:text-sm">
<p
class="absolute inset-s-4 inset-e-4 bottom-2 flex items-center gap-2 text-lg whitespace-normal text-white max-md:text-sm"
>
{#if isBirthday}
<span class="relative">
<Icon data-icon-birthday icon={mdiCakeVariant} size="1.25em" />
<Icon
data-icon-birthday
icon={bottomLayerPath}
size="1.25em"
class="block transition-colors group-hover:text-logo-blue"
/>
<Icon icon={topLayerPath} size="1.25em" class="absolute inset-0 transition-colors group-hover:text-logo-pink" />
<span class="flame absolute inset-0">
<Icon
icon={flamePath}
size="1.25em"
class="block transition-[color,filter] group-hover:text-logo-yellow group-hover:drop-shadow-[0_0_4px_var(--color-logo-yellow)]"
/>
</span>
{#key confettiCount}
{#if confettiCount > 0}
<span class="absolute inset-s-1/2 top-1/2">
@@ -51,9 +68,27 @@
{/if}
{/key}
</span>
<span class="min-w-0 truncate rounded-sm bg-logo-yellow px-1.5 py-0.5 text-black">{item.title}</span>
<span class="min-w-0 wrap-break-word">{item.title}</span>
{:else}
{item.title}
{/if}
</p>
</a>
<style>
.flame {
transform-origin: 50% 25%;
}
@media (prefers-reduced-motion: no-preference) {
a:hover .flame {
animation: flicker 150ms ease-in-out infinite alternate;
}
}
@keyframes flicker {
to {
transform: scale(0.9, 1.1);
}
}
</style>