diff --git a/package.json b/package.json index 96e7eec..7e9ddad 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,9 @@ "@radix-ui/colors": "^3.0.0", "@spotify/web-api-ts-sdk": "^1.1.2", "@supabase/supabase-js": "^2.38.4", + "@types/canvas-confetti": "^1.6.3", "@vercel/analytics": "^1.1.1", + "canvas-confetti": "^1.9.1", "dayjs": "^1.11.10", "satori": "^0.10.9", "sharp": "^0.32.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9cb0305..f457e11 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,9 +14,15 @@ dependencies: '@supabase/supabase-js': specifier: ^2.38.4 version: 2.38.4 + '@types/canvas-confetti': + specifier: ^1.6.3 + version: 1.6.3 '@vercel/analytics': specifier: ^1.1.1 version: 1.1.1 + canvas-confetti: + specifier: ^1.9.1 + version: 1.9.1 dayjs: specifier: ^1.11.10 version: 1.11.10 @@ -732,6 +738,10 @@ packages: tslib: 2.6.2 dev: true + /@types/canvas-confetti@1.6.3: + resolution: {integrity: sha512-yKVMDzWJ6g0s8TDI3VERfLMCOh0oHqZUnfK+o3VVjR2mFsLynUgb2lR+3IRaEJMza3BKbV9pkoirmM23YhKozA==} + dev: false + /@types/chai-subset@1.3.5: resolution: {integrity: sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==} dependencies: @@ -1183,6 +1193,10 @@ packages: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} dev: false + /canvas-confetti@1.9.1: + resolution: {integrity: sha512-jieDCn9OnPgFu5q+rbOGUmIGOjzgOnecW1/6KH07kAFAMwOczcTc4clde9pdyUPIAd/2wxZ8C5u7mBAcOpGK8Q==} + dev: false + /chai@4.3.10: resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} engines: {node: '>=4'} diff --git a/src/lib/components/SongSelect.svelte b/src/lib/components/SongSelect.svelte index 11afa2e..88099bf 100644 --- a/src/lib/components/SongSelect.svelte +++ b/src/lib/components/SongSelect.svelte @@ -4,7 +4,6 @@ import { createCombobox, melt } from '@melt-ui/svelte'; import ErrorMessage from './ErrorMessage.svelte'; import SearchIcon from '~icons/ri/search-line'; - import type { MouseEventHandler } from 'svelte/elements'; import { scale } from 'svelte/transition'; export let name: string; diff --git a/src/routes/cover/[slug]/+page.svelte b/src/routes/cover/[slug]/+page.svelte index 436191d..00870e8 100644 --- a/src/routes/cover/[slug]/+page.svelte +++ b/src/routes/cover/[slug]/+page.svelte @@ -5,10 +5,64 @@ import Tag from '$lib/components/Tag.svelte'; import { TAGS } from '$lib/constants'; import { page } from '$app/stores'; + import { onMount } from 'svelte'; + import confetti from 'canvas-confetti'; export let data; + const isNew = $page.url.searchParams.get('new') === 'true' ? true : false; const formattedDate = dayjs(data.created_at).format('MMMM D, YYYY'); + + onMount(async () => { + const fireConfetti = (placement: 'left' | 'right') => { + // https://www.flagcolorcodes.com/transgender + const colors = ['#ffffff', '#5BCEFA', '#F5A9B8']; + const baseAngle = placement === 'left' ? 70 : 110; + const origin = placement === 'left' ? { x: -0, y: 1 } : { x: 1, y: 1 }; + const drift = placement === 'left' ? 0.5 : -0.5; + + const sharedProps = { + particleCount: 100, + scalar: 0.8, + angle: baseAngle, + ticks: 300, + origin, + drift, + colors, + disableForReducedMotion: true, + zIndex: 999 + }; + + // The strongest blast of confetti, centered on the baseAngle + confetti({ + ...sharedProps, + spread: 20, + startVelocity: 90, + decay: 0.92 + }); + + // A weaker last of confetti with a larger spread + confetti({ + ...sharedProps, + spread: 50, + startVelocity: 60, + decay: 0.9 + }); + + // The weakest blast of confetti + confetti({ + ...sharedProps, + spread: 60, + startVelocity: 40, + decay: 0.89 + }); + }; + + if (isNew) { + setTimeout(() => fireConfetti('left'), 600); + setTimeout(() => fireConfetti('right'), 1200); + } + }); diff --git a/src/routes/new/+page.server.ts b/src/routes/new/+page.server.ts index 559bf33..68d28bf 100644 --- a/src/routes/new/+page.server.ts +++ b/src/routes/new/+page.server.ts @@ -132,7 +132,7 @@ export const actions = { // Success! Redirect :) if (data) { - throw redirect(302, `/cover/${data.slug}`); + throw redirect(302, `/cover/${data.slug}?new=true`); } }