React Cookie Consent

Legally required across the EU, and almost universally implemented in bad faith. The constraints here are legal, not aesthetic — and getting them right costs nothing except the dark pattern.

Installation

npx shadcn@latest add "https://kelvinui.com/registry/cookie-consent.json"

Props

PropTypeDescription
categoriesConsentCategory[]{ id, label, description, required?, vendors? }
policyHrefstringLink to your cookie policy
variant"banner" \"panel"
onChange(consent: ConsentState) => voidFires on accept / reject / save

The four rules it encodes

These are not style opinions. They are what regulators have repeatedly found consent banners failing on:

  1. Nothing optional is pre-enabled. Initial state sets every non-required category to false. Pre-ticked boxes are not consent — the CJEU settled that in Planet49.
  2. Reject is exactly as easy as accept. "Accept all" and "Reject all" are the same size, the same colour, side by side, both on the first screen. No greyed-out ghost button, no burying rejection behind "Manage preferences". This is the single most-cited violation, and it costs you one line of styling to avoid.
  3. Consent is withdrawable. After saving, the banner collapses to a summary with a "Change your choices" link, and variant="panel" gives you the persistent settings surface to link from your footer.
  4. Vendors are named. vendors lists who actually receives the data per category. "Analytics" is not informed consent; "Google Analytics, Vercel Analytics" is.

This component records a decision — it does not enforce it. Wire onChange so that no analytics or marketing script loads until its category is true, and so that revoking consent stops the collection. A banner that fires trackers on page load and asks afterwards is worse than no banner: you have the same violation plus written evidence you knew the rule.

Persist the result yourself (a first-party cookie or localStorage), along with a timestamp and the policy version consented to — you may need to demonstrate when and to what a user agreed. Note that the demo above resets on reload, because storing consent is your integration's job, not the component's.

Nothing here is legal advice; consult counsel for your jurisdiction. Different regimes differ — several US state laws are opt-out rather than opt-in, and Brazil's LGPD and others have their own requirements.

New components every week

Get the week's new Kelvin UI components and templates in one short email. No spam, unsubscribe anytime.