7.8 KiB
Seasonal Events Banner
The seasonal banner is a full-width strip that sits above the site header across the public site. It is used for time-sensitive announcements tied to holidays or events — booking reminders, holiday hour notices, etc.
Component
frontend/src/components/SeasonalBanner.svelte
Integrated at the layout level in frontend/src/routes/+layout.svelte. The banner renders site wide on public routes and is excluded from /admin.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
theme |
string |
'christmas' |
Controls colours and particle animation |
message |
string |
Christmas greeting | Main bold text shown in the banner |
sub |
string |
— | Smaller secondary text (hidden on mobile) |
link |
{ label, url } |
Book now → /contact | Optional CTA button rendered to the right |
visible |
boolean |
true |
Set false to suppress the banner entirely |
Themes
Switching themes changes the banner background, text colours, button colours, and the particle animation. To activate a theme, update the theme prop in +layout.svelte along with a matching message and sub.
Christmas — theme="christmas"
| Property | Value |
|---|---|
| Background | Dark green gradient #1a3a1a → #213021 |
| Text | White #ffffff |
| Accent | Yellow #FFD100 |
| Animation | ❄ Snowflakes falling straight down with slow rotation |
Particles: 18 snowflakes at varied horizontal positions, sizes (8–14 px), and durations (3–4.5 s).
Example usage:
<SeasonalBanner
theme="christmas"
message="🎄 Merry Christmas from the Tiny Gang! Walks continue over the holidays."
sub="Book before 20 Dec to secure your spot."
link={{ label: 'Book now', url: '/contact' }}
/>
Easter — theme="easter"
| Property | Value |
|---|---|
| Background | Purple gradient #7c3aed → #a855f7 |
| Text | White #ffffff |
| Accent | Soft yellow #fde68a |
| Animation | 🌸 Cherry blossom petals drifting down with a gentle lateral sway and rotation |
Particles: 14 petals at varied positions, sizes (8–13 px), and durations (3.5–5.5 s). The petal-fall keyframe adds horizontal drift at each quarter-step to mimic a natural tumbling fall.
Example usage:
<SeasonalBanner
theme="easter"
message="🐣 Happy Easter from the Tiny Gang! We're walking all through the long weekend."
sub="Book your spot before it fills up."
link={{ label: 'Book now', url: '/contact' }}
/>
Active window: Good Friday through Easter Monday (exact dates vary — check annually).
Halloween — theme="halloween"
| Property | Value |
|---|---|
| Background | Near-black gradient #1c1917 → #292524 |
| Text | Orange #f97316 |
| Accent | Orange #f97316 |
| Animation | 🦇 Bats flying right-to-left across the banner with a sinusoidal vertical wobble |
Particles: 8 bats staggered across vertical positions (10–80% height), sizes (11–18 px), delays (0–7 s) and durations (6–10.5 s). The bat-fly keyframe starts off the right edge (left: 108%) and translates to -115vw, with Y offsets at 30 %, 60 %, and 85 % of the animation to create the swooping motion.
Example usage:
<SeasonalBanner
visible={true}
theme="halloween"
message="🎃 Boo! The Tiny Gang is still walking this Halloween weekend."
sub="Spooky walks, same great dogs."
link={{ label: 'Book now', url: '/contact' }}
/>
Active window: ~October 28 – November 1.
New Year's Eve / New Year's Day — theme="newYear"
| Property | Value |
|---|---|
| Background | Deep navy gradient #0a0a1a → #1a102e |
| Text | Gold #FFD700 |
| Accent | Gold #FFD700 |
| Animation | ✨ Sparkles and confetti (✨ 🎊 ⭐ 💫) falling and rotating with a scale pulse |
Particles: 20 sparkles cycling through four emoji types, varied positions, sizes (10–14 px), and durations (2.5–4.5 s). The sparkle-fall keyframe scales up at 40 % for a "pop" effect before fading out.
Example usage:
<SeasonalBanner
theme="newYear"
message="🥂 Happy New Year from the Tiny Gang! Walks resume 2 Jan."
sub="Book ahead for the first week — spots go fast."
link={{ label: 'Book now', url: '/contact' }}
/>
Active window: December 31 – January 1 (and optionally through January 2 if there is a holiday schedule notice).
Summer — theme="summer"
| Property | Value |
|---|---|
| Background | Blue gradient #0ea5e9 → #06b6d4 |
| Text | White #ffffff |
| Accent | Pale yellow #fef08a |
| Animation | None |
General-purpose warm-weather banner. No particle effect. Good for school holiday or summer schedule notices.
Custom — theme="custom"
Falls back to dark green with yellow accents (same palette as Christmas but without snow). Use this as a neutral base for one-off announcements that don't fit a seasonal theme.
Behaviour
Dismissal — The ✕ button sets a local dismissed boolean. The banner hides for the remainder of the session but reappears on next page load (no localStorage persistence).
Mobile — Below 600 px the sub text is hidden and the main message font drops to 0.82 rem. The CTA button and dismiss button remain visible.
z-index — The banner sits at z-index: 200, above the header (z-index: 20).
Analytics — CTA button clicks fire a banner_click signal event via signalClick (see frontend/src/lib/signals.js). Metadata includes the button label and destination URL.
How to switch themes
Edit frontend/src/routes/+layout.svelte and update the three props on <SeasonalBanner>:
<SeasonalBanner
visible={true}
theme="halloween"
message="🎃 Boo! The Tiny Gang is still walking this Halloween weekend."
sub="Spooky walks, same great dogs."
link={{ label: 'Book now', url: '/contact' }}
/>
To disable the banner entirely, set visible={false} or remove the component from the layout. To limit it to specific routes again, pass a route-based condition from +layout.svelte.
Adding a new theme
- Add an entry to the
THEMESobject inSeasonalBanner.svelte:myTheme: { bg: 'linear-gradient(90deg, #colour1, #colour2)', accent: '#hex', text: '#hex', sub: 'rgba(r,g,b,0.75)', btn: '#hex', btnText: '#hex', particles: false, // or 'snow' | 'bats' | 'petals' | 'confetti' }, - If you need a custom particle effect, add a particle array and a matching
{:else if t.particles === 'myEffect'}block in the template, plus a@keyframesrule in the<style>block. - Update
+layout.svelteto use the new theme key.