From 72b7bc629cc7d38231924281adb4036a326bca7f Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 1 Aug 2026 21:07:26 +0000 Subject: [PATCH] Restyle Klaro banner to brand + add persistent reopen button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Was full-width ('wide' theme) with Klaro's default green/dark palette, neither matching the brand. Now: compact bottom-left corner notice (~380px), brand colors via Klaro's CSS-var overrides (dark1/light1 etc. — confusingly named, they're background/text, not a dark-mode switch), neutral gray decline button instead of red. Also adds a persistent bottom-left cookie icon (KlaroConsentManager.tsx) so a visitor can reopen the consent manager any time via Klaro.show(), not just on first visit. Co-Authored-By: Claude Sonnet 5 --- app/components/KlaroConsentManager.tsx | 30 ++++++++++++++++++++-- app/lib/klaroConfig.ts | 35 ++++++++++++++++++-------- types/klaro.d.ts | 3 +++ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/app/components/KlaroConsentManager.tsx b/app/components/KlaroConsentManager.tsx index d2426a7..56b8b62 100644 --- a/app/components/KlaroConsentManager.tsx +++ b/app/components/KlaroConsentManager.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import "klaro/dist/klaro.css"; import type { TrackingCode } from "../lib/payload"; import { buildKlaroConfig } from "../lib/klaroConfig"; @@ -21,6 +21,12 @@ import { loadTrackingCode } from "../lib/loadTrackingCode"; // dynamic import()), paired with the "-no-css" JS build so the stylesheet // isn't loaded twice. export function KlaroConsentManager({ codes }: { codes: TrackingCode[] }) { + // Kept in state (not just called once) so the persistent reopen button + // below can call Klaro.show() itself, any time after the initial + // accept/reject decision — a visitor must always be able to revisit + // their choice, not just on first load. + const [klaroModule, setKlaroModule] = useState(null); + useEffect(() => { // Nothing to ask consent for — don't even load/render Klaro. A cookie // banner with zero services to list would just be visual noise. @@ -31,6 +37,7 @@ export function KlaroConsentManager({ codes }: { codes: TrackingCode[] }) { if (cancelled) return; const config = buildKlaroConfig(codes, loadTrackingCode); Klaro.setup(config); + setKlaroModule(Klaro); }); return () => { cancelled = true; @@ -41,5 +48,24 @@ export function KlaroConsentManager({ codes }: { codes: TrackingCode[] }) { // meant to be called more than once per page load anyway. }, []); - return null; + if (!klaroModule) return null; + + return ( + + ); } diff --git a/app/lib/klaroConfig.ts b/app/lib/klaroConfig.ts index 754a7b4..efaf4b7 100644 --- a/app/lib/klaroConfig.ts +++ b/app/lib/klaroConfig.ts @@ -56,20 +56,35 @@ export function buildKlaroConfig(codes: TrackingCode[], onAccept: (code: Trackin return { version: 1, elementID: "klaro", - // 'light' (not 'dark'), 'bottom' (matches the previous custom - // CookieBanner.tsx's own position), 'wide' (roomier than Klaro's - // narrow default notice, closer to the old banner's proportions). + // 'light' + 'bottom' + 'left' — a compact corner notice (Klaro's own + // default max-width, ~400px), not a full-width bar. 'wide' (tried + // first) stretched it across nearly the whole viewport, which read as + // too dominant compared to a typical bottom-left corner CMP. // Extra keys beyond `theme` override individual CSS custom properties // (Klaro's injectStyles() applies any non-'theme' `styling` key as a - // `--` var) — green1 is what colors the "Alle akzeptieren" - // button (.cm-btn-success), so this is how the accept button gets the - // site's actual brand color instead of Klaro's default green. + // `--` var, see node_modules/klaro's own utils/styling.js) — this + // is the actual brand-color pass: dark1/light1 are (confusingly + // named) the notice's background/text colors, not a dark-mode toggle; + // green1 colors the accept button, red1 the decline button (set + // neutral gray, not alarming red — this site's own secondary buttons + // are plain-bordered, never red, see NotifyMeForm.tsx). styling: { - theme: ["light", "bottom", "wide"], - green1: "#f6a701", // --color-brand - "button-text-color": "#1a1a18", // --color-text-primary — dark text reads better on the brand orange than Klaro's default white - "border-radius": "6px", + theme: ["light", "bottom", "left"], + dark1: "#fffdf8", // --color-bg-paper — notice/modal background + dark2: "#e5e0d8", // --color-border + dark3: "#f3efe9", + light1: "#1a1a18", // --color-text-primary — notice/modal text + light2: "#6b6b69", // --color-text-muted + light3: "#1a1a18", + green1: "#f6a701", // --color-brand — accept button + green2: "#d99000", + red1: "#e5e0d8", // decline button — neutral bordered look, not red + red2: "#d1cabf", + "button-text-color": "#1a1a18", + "border-radius": "10px", + "border-width": "1px", "font-family": "inherit", + "notice-max-width": "380px", }, storageMethod: "cookie", cookieName: "klaro-consent", diff --git a/types/klaro.d.ts b/types/klaro.d.ts index 77091b1..3204420 100644 --- a/types/klaro.d.ts +++ b/types/klaro.d.ts @@ -5,6 +5,9 @@ // codebase relies on). declare module "klaro/dist/klaro-no-css" { export function setup(config: unknown): void; + // Re-opens the consent modal on demand — used by KlaroConsentManager.tsx's + // persistent bottom-left reopen button. + export function show(config?: unknown, modal?: boolean): void; } declare module "klaro/dist/klaro.css";