Build a cookie-consent banner with Tailwind CSS: a fixed bottom bar with a short privacy message and a link, plus "Accept all" and "Reject" buttons. Keep it unobtrusive with a soft shadow and rounded corners. Then add the JavaScript that gives it meaning: record the choice and the timestamp in localStorage, hide the banner with a slide-down transition once a choice is made, skip showing it at all on later visits, wrap every storage call in try/catch so private-mode browsers do not throw, and dispatch a custom cookie-consent event carrying the decision so analytics or embeds can subscribe rather than being hard-wired into the banner.
Paste it into Claude, Cursor, v0 or any AI coding tool. Prefer the
finished markup? .
Build a cookie-consent banner with Tailwind CSS: a fixed bottom bar with a short privacy message and a link, plus "Accept all" and "Reject" buttons. Keep it unobtrusive with a soft shadow and rounded corners. Then add the JavaScript that gives it meaning: record the choice and the timestamp in localStorage, hide the banner with a slide-down transition once a choice is made, skip showing it at all on later visits, wrap every storage call in try/catch so private-mode browsers do not throw, and dispatch a custom cookie-consent event carrying the decision so analytics or embeds can subscribe rather than being hard-wired into the banner.
var STORAGE_KEY = "cookie-consent";
var bar = document.getElementById("cookieBar");
// Storage access throws in private mode and in sandboxed frames — never let a
// consent banner take the page down with it.
function read(key) {
try { return localStorage.getItem(key); } catch (e) { return null; }
}
function write(key, value) {
try { localStorage.setItem(key, value); } catch (e) {}
}
function decide(choice) {
write(STORAGE_KEY, JSON.stringify({ choice: choice, at: new Date().toISOString() }));
// Let the rest of the page react instead of wiring analytics in here.
document.dispatchEvent(new CustomEvent("cookie-consent", { detail: { choice: choice } }));
bar.classList.add("translate-y-full");
setTimeout(function () { bar.remove(); }, 300);
}
if (read(STORAGE_KEY)) {
bar.remove();
} else {
[].slice.call(bar.querySelectorAll("[data-consent]")).forEach(function (button) {
button.addEventListener("click", function () {
decide(button.getAttribute("data-consent"));
});
});
}
// Example subscriber — replace with your own loader.
document.addEventListener("cookie-consent", function (e) {
if (e.detail.choice === "accepted") console.log("Analytics may load now.");
});