diff --git a/package-lock.json b/package-lock.json index 8f32db46..d0637e95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "@fontsource-variable/nunito": "^5.2.7", "@fontsource-variable/outfit": "^5.2.8", "@fontsource-variable/playfair-display": "^5.2.8", + "@fontsource/bebas-neue": "^5.2.7", "@fontsource/bungee-shade": "^5.2.7", "@fontsource/caveat": "^5.2.8", "@fontsource/cherry-bomb-one": "^5.2.7", @@ -1456,6 +1457,15 @@ "url": "https://github.com/sponsors/ayuhito" } }, + "node_modules/@fontsource/bebas-neue": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@fontsource/bebas-neue/-/bebas-neue-5.2.7.tgz", + "integrity": "sha512-DsmBrmq55d9BCU0mt4DT4RZDdH8vhWRKEUOfbuNB1EEjMuwbtFvM8N+3gIlkYSFbsb10P8Q19BV5OdpMu2h0fA==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, "node_modules/@fontsource/bungee-shade": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/@fontsource/bungee-shade/-/bungee-shade-5.2.7.tgz", diff --git a/package.json b/package.json index 61b68826..dc4de403 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@fontsource-variable/nunito": "^5.2.7", "@fontsource-variable/outfit": "^5.2.8", "@fontsource-variable/playfair-display": "^5.2.8", + "@fontsource/bebas-neue": "^5.2.7", "@fontsource/bungee-shade": "^5.2.7", "@fontsource/caveat": "^5.2.8", "@fontsource/cherry-bomb-one": "^5.2.7", diff --git a/src/components/CampaignHeroBackground.tsx b/src/components/CampaignHeroBackground.tsx deleted file mode 100644 index 7d573c55..00000000 --- a/src/components/CampaignHeroBackground.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; - -import { sanitizeUrl } from '@/lib/sanitizeUrl'; -import { cn } from '@/lib/utils'; -interface CampaignHeroBackgroundProps { - /** - * Image URL for the active campaign. Each new URL crossfades over the - * previous one — we keep up to two layers mounted at a time so the - * transition is smooth even when the source changes mid-fade. - */ - imageUrl: string | undefined; - /** Optional className for the outer wrapper. */ - className?: string; -} - -interface Layer { - /** Stable key so React doesn't tear down the layer mid-transition. */ - id: number; - /** Sanitized URL (or `null` for the gradient-only fallback). */ - url: string | null; -} - -const FADE_MS = 1500; - -/** - * Full-bleed crossfading background built from the active campaign's banner - * image. Modelled after Treasures' HeroGallery: each image gets its own - * stacked layer and we toggle opacity to crossfade. The previous layer - * unmounts after the fade completes, so we never accumulate more than a - * couple of layers in the DOM. - * - * A warm tint + subtle film-grain SVG sit on top so headlines stay readable - * over any photo. - */ -export function CampaignHeroBackground({ imageUrl, className }: CampaignHeroBackgroundProps) { - const idRef = useRef(0); - const [layers, setLayers] = useState([]); - const lastUrlRef = useRef(null); - - useEffect(() => { - const safe = sanitizeUrl(imageUrl) ?? null; - if (safe === lastUrlRef.current) return; - lastUrlRef.current = safe; - - const id = ++idRef.current; - // Add the new layer; existing layers stay mounted so the crossfade has - // something to fade from. - setLayers((prev) => [...prev, { id, url: safe }]); - - // After the fade completes, drop everything except the most recent - // layer to keep the DOM tidy. - const timeout = window.setTimeout(() => { - setLayers((prev) => prev.filter((l) => l.id === id)); - }, FADE_MS + 50); - return () => window.clearTimeout(timeout); - }, [imageUrl]); - - return ( -