Restyle Klaro to actually match the brand, not just its accent colors

CSS-var overrides alone (colors, corner position) still left Klaro's
own border/shadow/spacing/typography, which read as an obviously
bolted-on library widget next to this site's hand-designed
components. New KlaroTheme component overrides Klaro's real DOM
classnames directly (confirmed against kiprotect/klaro's own scss
source) — kills the default border, adds this site's own soft-shadow
card look, restyles every button, uses the site's actual serif/sans
font pairing. Also warms up the notice/modal copy.

Updates both READMEs with the tracking-codes/Klaro/back-in-stock/
settings-search/DHL-shipment-label work from this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-08-01 21:20:28 +00:00
parent a8ab3e4f44
commit f6b001dd11
3 changed files with 153 additions and 34 deletions
+82 -17
View File
@@ -20,6 +20,66 @@ import { loadTrackingCode } from "../lib/loadTrackingCode";
// stays static (Next.js requires CSS imports to be static, not inside a
// dynamic import()), paired with the "-no-css" JS build so the stylesheet
// isn't loaded twice.
//
// `buildKlaroConfig`'s `styling` CSS-var overrides (brand colors, corner
// position) only get Klaro so far — its bundled klaro.css still draws its
// own border/shadow/spacing/typography, which read as an obviously
// bolted-on library widget next to this site's own hand-designed
// components (NewsletterModal.tsx, NotifyMeForm.tsx, etc.). The <style>
// block below is a real CSS override pass against Klaro's actual DOM
// classnames (confirmed against kiprotect/klaro's own src/scss/*.scss,
// not guessed) — same "plain unlayered <style> tag wins the cascade"
// approach the Payload admin's own AdminUIStyles.tsx uses, `!important`
// added only where needed to beat klaro.css's own rules of otherwise-equal
// specificity. Kills Klaro's default border entirely (replaced with a
// soft shadow, matching this site's own card language) and restyles
// every button to the site's actual rounded/weighted look instead of
// Klaro's generic flat rectangles.
function KlaroTheme() {
return (
<style>{`
.klaro, .klaro * { box-sizing: border-box; }
.klaro .cookie-notice, .klaro .cookie-modal {
border: none !important;
box-shadow: 0 20px 44px -14px rgba(26,26,24,0.22), 0 4px 14px rgba(26,26,24,0.07) !important;
border-radius: 18px !important;
font-family: var(--font-inter), -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important;
}
.klaro .cookie-notice .cn-body { padding: 22px 24px !important; }
.klaro .cookie-notice p, .klaro .cookie-modal p {
font-size: 14px !important;
line-height: 1.6 !important;
margin-top: 0 !important;
margin-bottom: 10px !important;
}
.klaro h1, .klaro h2 {
font-family: var(--font-lora), Georgia, serif !important;
font-weight: 700 !important;
letter-spacing: -0.01em !important;
}
.klaro .cm-btn {
border: none !important;
border-radius: 8px !important;
font-weight: 700 !important;
font-size: 13px !important;
padding: 10px 18px !important;
transition: opacity 0.15s ease, transform 0.15s ease;
}
.klaro .cm-btn:hover { opacity: 0.88; }
.klaro .cm-btn:active { transform: scale(0.97); }
.klaro .cm-btn:focus-visible { outline: 2px solid #f6a701 !important; outline-offset: 2px; }
.klaro a.cm-link, .klaro .cookie-notice a, .klaro .cookie-modal a {
color: #a06b00 !important;
text-decoration: underline !important;
font-weight: 600 !important;
}
.klaro select, .klaro .cm-list-input + label {
border-radius: 6px !important;
}
`}</style>
);
}
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
@@ -48,24 +108,29 @@ export function KlaroConsentManager({ codes }: { codes: TrackingCode[] }) {
// meant to be called more than once per page load anyway.
}, []);
if (!klaroModule) return null;
if (codes.length === 0) return null;
return (
<button
type="button"
onClick={() => klaroModule.show()}
aria-label="Cookie-Einstellungen öffnen"
title="Cookie-Einstellungen"
className="fixed bottom-5 left-5 z-40 flex h-11 w-11 items-center justify-center rounded-full border border-border bg-bg-base shadow-md hover:border-brand transition-colors"
>
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" aria-hidden="true">
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="1.6" />
<circle cx="9" cy="9.5" r="1.1" fill="currentColor" />
<circle cx="14" cy="8.5" r="1" fill="currentColor" />
<circle cx="15" cy="13.5" r="1.1" fill="currentColor" />
<circle cx="10.5" cy="14.5" r="1" fill="currentColor" />
<circle cx="12" cy="11" r="0.9" fill="currentColor" />
</svg>
</button>
<>
<KlaroTheme />
{klaroModule && (
<button
type="button"
onClick={() => klaroModule.show()}
aria-label="Cookie-Einstellungen öffnen"
title="Cookie-Einstellungen"
className="fixed bottom-5 left-5 z-40 flex h-11 w-11 items-center justify-center rounded-full border border-border bg-bg-base shadow-md hover:border-brand transition-colors"
>
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" aria-hidden="true">
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="1.6" />
<circle cx="9" cy="9.5" r="1.1" fill="currentColor" />
<circle cx="14" cy="8.5" r="1" fill="currentColor" />
<circle cx="15" cy="13.5" r="1.1" fill="currentColor" />
<circle cx="10.5" cy="14.5" r="1" fill="currentColor" />
<circle cx="12" cy="11" r="0.9" fill="currentColor" />
</svg>
</button>
)}
</>
);
}