Skip to main content
The WeatherBanner component displays urgent weather-related service cancellation alerts in a modal dialog format. It’s designed for temporary emergency announcements that expire automatically.

Features

  • Modal Dialog: Full-screen overlay with centered alert
  • Auto-Expiration: Automatically hides after specified date
  • Session Dismissal: Remembers dismissal via sessionStorage
  • Keyboard Support: Escape key closes the modal
  • Backdrop Dismissal: Click outside to close
  • Urgent Styling: Red accent for emergency visibility

Installation

import WeatherBanner from '../components/WeatherBanner.astro';

Basic Usage

<WeatherBanner />

Props

messageId
string
default:"cancel-jan-25-2026"
Unique identifier for tracking dismissals. Use a meaningful ID that includes the date.
expiresAt
string
default:"2026-01-28T23:59:59"
ISO 8601 date string indicating when the alert should stop showing. Format: YYYY-MM-DDTHH:MM:SS

Current Active Example

From the source code (lines 1-15):
<WeatherBanner 
  messageId="cancel-jan-25-2026"
  expiresAt="2026-01-28T23:59:59"
/>
Displays:
Service Canceled
Sunday, January 25

Due to inclement weather, our in-person worship service has been 
canceled for this Sunday. Please stay safe and we look forward to 
seeing you next week.

[Got it]

Message Customization

To customize the message, edit the component HTML:
<h2 id={`weatherTitle-${messageId}`}>
  Sunday, January 25  <!-- Change date here -->
</h2>
<p>
  Due to inclement weather, our in-person worship service has been 
  <strong>canceled</strong> for this Sunday. Please stay safe and 
  we look forward to seeing you next week.
  <!-- Customize message here -->
</p>

Examples

Different Date

<WeatherBanner 
  messageId="cancel-feb-15-2026"
  expiresAt="2026-02-18T23:59:59"
/>
Then update the display date in the component:
<h2>Sunday, February 15</h2>

Shorter Expiration

<WeatherBanner 
  messageId="cancel-today"
  expiresAt="2026-03-03T18:00:00"  <!-- Expires at 6 PM same day -->
/>

Delayed Service (Not Canceled)

Modify the message content:
<p class="text-xs font-semibold text-yellow-600 uppercase tracking-wider mb-2">
  Service Delayed
</p>
<h2>Sunday, January 25</h2>
<p>
  Due to inclement weather, our worship service will start at 
  <strong>11:00 AM</strong> instead of the usual time. 
  Please drive safely!
</p>

Behavior

Expiration Check

Two-level expiration checking: Server-side (Astro):
---
const expirationDate = new Date(expiresAt);
const isExpired = new Date() > expirationDate;
---

{!isExpired && (
  <!-- Modal content -->
)}
Client-side (JavaScript):
if (expirationDate && new Date() > new Date(expirationDate)) {
  modal?.remove();
}

Dismissal Tracking

Uses sessionStorage (per-tab):
function closeModal() {
  if (messageId) {
    sessionStorage.setItem(`weather-${messageId}`, 'dismissed');
  }
  modal?.remove();
}

// Check on page load
if (messageId && sessionStorage.getItem(`weather-${messageId}`) === 'dismissed') {
  modal?.remove();
}
Storage Key Format:
  • Pattern: weather-{messageId}
  • Example: weather-cancel-jan-25-2026
  • Value: "dismissed"

Styling

Emergency Red Accent

<p class="text-xs font-semibold text-red-600 uppercase tracking-wider mb-2">
  Service Canceled
</p>
<div class="fixed inset-0 bg-black/70 z-[150] flex items-center justify-center p-6">
  • z-[150]: Above most content
  • bg-black/70: 70% opacity backdrop
  • Centered with flexbox

Content Card

<div class="bg-white rounded-lg max-w-sm w-full p-6 modal-content">
  • Max width: 28rem (448px)
  • White background
  • Rounded corners
  • Fade-in animation

Animation

.modal-content {
  animation: fadeIn 0.2s ease-out;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
Quick 200ms fade-in for immediate visibility.

Event Handling

Button Click

closeBtn?.addEventListener('click', closeModal);

Backdrop Click

modal?.addEventListener('click', (e) => { 
  if (e.target === modal) closeModal(); 
});
Only closes if clicking the backdrop, not the card.

Escape Key

document.addEventListener('keydown', (e) => { 
  if (e.key === 'Escape') closeModal(); 
});

Accessibility

  • role="alertdialog": Indicates urgent modal
  • aria-modal="true": Screen reader modal behavior
  • aria-labelledby: References title for context
  • High contrast colors (red on white)
  • Keyboard dismissal support
  • Clear, urgent language

Z-Index Layering

WeatherBanner: z-[150]

AlertBanner: z-[150]

Accessibility Menu: z-[140]

Cookie Banner: z-[9999]
WeatherBanner and AlertBanner share the same z-index since they’re mutually exclusive emergency alerts.

Use Cases

Weather Cancellations

<!-- Snow/ice -->
<WeatherBanner messageId="snow-cancel-2026-01-25" />

<!-- Severe storms -->
<WeatherBanner messageId="storm-cancel-2026-03-15" />

<!-- Flooding -->
<WeatherBanner messageId="flood-cancel-2026-05-10" />

Building Issues

<p class="text-xs font-semibold text-red-600">
  Facility Closed
</p>
<p>
  Due to a power outage, our building is temporarily closed. 
  We're working to resolve this issue.
</p>

Health Emergencies

<p class="text-xs font-semibold text-red-600">
  Service Format Changed
</p>
<p>
  Out of an abundance of caution, today's service will be 
  <strong>online only</strong>. Join us via livestream.
</p>

Best Practices

Unique Message IDs

Use descriptive IDs with dates:
✅ Good: "cancel-jan-25-2026"
✅ Good: "snow-delay-2026-02-10"
❌ Bad: "alert1"
❌ Bad: "weather"

Expiration Dates

Set expiration a few days after the event:
<!-- Event: Sunday Jan 25 -->
<!-- Expires: Tuesday Jan 28 -->
<WeatherBanner 
  messageId="cancel-jan-25-2026"
  expiresAt="2026-01-28T23:59:59"  <!-- +3 days -->
/>
This ensures:
  • Alert doesn’t show on next Sunday
  • Gives time for people checking later in the week
  • Automatic cleanup

Message Tone

✅ Reassuring: "Please stay safe and we look forward to seeing you next week."
✅ Clear: "Service has been canceled for this Sunday."
✅ Action-oriented: "Join us online at..."
❌ Vague: "There might be an issue."
❌ Alarmist: "URGENT!!! DO NOT COME!!!"

Testing

Test Expiration

<!-- Set expiration 1 minute in future -->
<WeatherBanner 
  expiresAt={new Date(Date.now() + 60000).toISOString()}
/>

Test Dismissal

// Console
sessionStorage.setItem('weather-cancel-jan-25-2026', 'dismissed');
location.reload();

Clear Dismissal

// Console
sessionStorage.removeItem('weather-cancel-jan-25-2026');
location.reload();

Comparison with AlertBanner

FeatureWeatherBannerAlertBanner
PurposeEmergency cancellationsGeneral announcements
UrgencyHigh (red accent)Medium (neutral)
Typical Duration1-3 days1-4 weeks
MessageHard-codedProp-based
StyleEmergency alertStandard notice
Common UseWeather closuresEvent promotions
  • AlertBanner: General announcements and notices
  • SeasonalBanner: Non-modal seasonal messages

Quick Reference

Enable Alert:
<WeatherBanner 
  messageId="unique-id-with-date"
  expiresAt="YYYY-MM-DDTHH:MM:SS"
/>
Disable Alert: Remove the component or set expiration to past date. Update Message: Edit the HTML content in the component file at:
  • Line 28-31: Title and date
  • Line 33-35: Message text

Build docs developers (and LLMs) love