maintenance-banner.tsx36 lines · main
1'use client';
2
3import { useState } from 'react';
4
5/**
6 * Thin, dismissible pre-announcement strip. Rendered only when maintenance is
7 * `upcoming` (scheduled but not started). Purely informational — no fetch, no
8 * gated data; the parent server component decides whether to render it and
9 * passes the pre-formatted window in. Dismiss state is local to the session.
10 */
11export function MaintenanceBanner({ window: label }: { window: string }) {
12 const [dismissed, setDismissed] = useState(false);
13 if (dismissed) return null;
14
15 return (
16 <div
17 role="status"
18 className="relative z-40 flex items-center justify-center gap-3 border-b border-[var(--color-border-primary)] bg-[var(--color-primary-subtle)] px-4 py-2 text-center font-mono text-[var(--color-text)] text-[var(--text-xs)]"
19 >
20 <span>
21 <span className="uppercase tracking-wider text-[var(--color-primary)]">
22 scheduled maintenance:
23 </span>{' '}
24 {label}
25 </span>
26 <button
27 type="button"
28 aria-label="dismiss"
29 onClick={() => setDismissed(true)}
30 className="absolute right-3 text-[var(--color-text-subtle)] transition-colors hover:text-[var(--color-text)]"
31 >
32
33 </button>
34 </div>
35 );
36}