banner and intro fix

This commit is contained in:
Kismet Hasanaj
2026-05-03 01:06:11 +02:00
parent af798cc58c
commit d66c54088a
4 changed files with 106 additions and 32 deletions
+17 -7
View File
@@ -28,28 +28,35 @@ import { site } from "@/content";
const CONSENT_KEY = "novarix-cookie-consent";
const INTRO_SEEN_KEY = "novarix-intro-seen";
const REOPEN_EVENT = "novarix:open-cookie-banner";
const INTRO_EVENT = "novarix:start-intro";
type Consent = "unknown" | "ack" | "rst";
export default function CookieBanner() {
// Start hidden on the server and on first client paint to avoid a flash.
const [visible, setVisible] = useState(false);
// Start from the pre-hydration decision made in layout.tsx so the banner
// can appear immediately on first visit without waiting for a delayed effect.
const [visible, setVisible] = useState(() => {
if (typeof document === "undefined") return false;
return document.documentElement.dataset.showCookieBanner === "1";
});
// Read the stored consent on mount and decide whether to show the banner.
useEffect(() => {
try {
const stored = window.localStorage.getItem(CONSENT_KEY) as Consent | null;
if (stored !== "ack" && stored !== "rst") {
// No decision yet — show the banner. We delay slightly so the page
// settles in first; feels less aggressive than appearing instantly.
const t = window.setTimeout(() => setVisible(true), 600);
return () => window.clearTimeout(t);
document.documentElement.dataset.showCookieBanner = "1";
// eslint-disable-next-line react-hooks/set-state-in-effect
setVisible(true);
} else {
document.documentElement.dataset.showCookieBanner = "0";
}
} catch {
// localStorage unavailable (private mode, blocked, etc.) — show the
// banner so the user is still told. Sync-once-on-mount is a legitimate
// use of setState in an effect.
// eslint-disable-next-line react-hooks/set-state-in-effect
document.documentElement.dataset.showCookieBanner = "1";
setVisible(true);
}
}, []);
@@ -67,10 +74,13 @@ export default function CookieBanner() {
if (choice === "rst") {
// Honour the rejection by clearing any non-consent storage.
window.sessionStorage.removeItem(INTRO_SEEN_KEY);
} else {
window.dispatchEvent(new Event(INTRO_EVENT));
}
} catch {
/* storage unavailable — nothing to do */
}
document.documentElement.dataset.showCookieBanner = "0";
setVisible(false);
}
@@ -81,7 +91,7 @@ export default function CookieBanner() {
role="dialog"
aria-live="polite"
aria-label="Cookie consent"
className="fixed inset-x-0 bottom-0 z-[1500] flex justify-center p-3 sm:p-5"
className="fixed inset-x-0 bottom-0 z-[2500] flex justify-center p-3 sm:p-5"
>
<div className="pointer-events-auto w-full max-w-3xl rounded-2xl border border-[var(--border-strong)] bg-[var(--surface-strong)] p-4 shadow-[0_24px_60px_-20px_oklch(0_0_0/0.45)] backdrop-blur-xl sm:p-5">
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between sm:gap-6">