LumeoA11yfocus-managedkeyboarddialogregionDepends onflow-canvasTested
Tier 3 · 69 testsView source ↗Consent Banner
GDPR-ready cookie / tracking consent primitive. Persists per-category choices in localStorage and exposes them via ConsentService for gating third-party scripts.
Installation
dotnet add package Lumeo
One-time app setup (AddLumeo(), CSS & JS) is covered in the
installation guide.
Usage
@using Lumeo <ConsentBanner />
69 tests across 16 files. Auto-generated from the test suite.
When to use
- Any site that loads analytics (Google Analytics, Cloudflare Web Analytics, Plausible, Umami) in the EU / UK / CA.
- Any site that embeds third-party scripts users should opt into (YouTube embeds, Intercom, Hotjar).
- SaaS apps that want to give end users a "Manage cookie preferences" link in the footer.
No live preview here — the banner can only show once per browser. Copy the code into your own MainLayout.razor to see it slide in.
Drop the banner into your root layout. Default categories are `necessary` (locked) + `analytics`.
Analytics consent:
No beacon. Nothing leaves the browser.
Toggle Analytics in to see this flip.
The whole point: nothing hits a third-party until the user says yes.
Session, theme preference, routing — required for the site to work.
Cloudflare Web Analytics — anonymous aggregate page-view stats.
Meta Pixel and LinkedIn Insight Tag for remarketing.
YouTube, Vimeo, Tweet embeds — set cookies when loaded.
Define your own buckets — one per third-party service you load.
We use a minimal set of cookies to run the site and optionally measure anonymous usage to improve it. You choose what's on.
Every string is a parameter. Pair with `ILumeoLocalizer` if you want them to follow the user's language.
API reference
<ConsentBanner>
| Prop | Type | Default | Description |
|---|---|---|---|
| Class | string? | — | Additional CSS classes merged onto the banner's root role="region" element (the preferences dialog is unaffected). |
| AdditionalAttributes | Dictionary<string, object>? | — | Unmatched attributes splatted onto the banner's root role="region" element. |
| Categories | IReadOnlyList<Lumeo.Services.ConsentCategory> | DefaultCategories | Consent buckets to expose in the preferences dialog. Omit `Required: true` ones if your site doesn't use strictly-necessary cookies. |
| PrivacyPolicyUrl | string? | — | URL to your privacy policy page. If null, the link is hidden. |
| PolicyVersion | string | "1" | Privacy-policy version this banner asks consent for. When a stored decision was recorded against a different version, the banner re-prompts (previous choices prefill the preferences dialog, but the user must re-confirm). Bump this whenever your policy materially changes. Defaults to "1". |
| Title | string | "Cookies & consent" | Banner heading, shown next to the cookie icon. |
| Description | string | "We use a minimal set of cookies to run the site and optionally measure anonymous usage to improve it. You choose what's on." | Banner body text, followed by the privacy-policy link when PrivacyPolicyUrl is set. |
| PrivacyPolicyLabel | string | "Read the privacy policy" | Link text for the privacy-policy link (only shown when PrivacyPolicyUrl is set). |
| AcceptLabel | string | "Accept all" | Label for the layer-1 "accept everything" button. |
| RejectLabel | string | "Reject optional" | Label for the layer-1 "reject optional categories" button. |
| CustomizeLabel | string | "Customize" | Label for the button that opens the preferences dialog; only rendered when at least one non-required category exists. |
| PreferencesTitle | string | "Consent preferences" | Heading of the preferences dialog. |
| PreferencesDescription | string | "Pick which categories you're okay with. You can change this later." | Body text of the preferences dialog. |
| RequiredBadge | string | "Required" | Badge text shown next to a category that is Required: true (always on, not toggleable). |
| CancelLabel | string | "Cancel" | Label for the preferences dialog's cancel button (discards draft changes). |
| SaveLabel | string | "Save preferences" | Label for the preferences dialog's save button (commits the draft toggles). |
| AnimationClass | string | "animate-slide-in-from-bottom" | CSS animation class applied to the banner on mount (default a slide-in from the bottom edge). |
ConsentCategory
| Property | Type | Description |
|---|---|---|
| Key | string | Machine-readable identifier (e.g. "analytics"). Used as the persistence key and the argument to ConsentService.HasConsent(key). |
| Title | string | Short label shown in the preferences dialog. |
| Description | string | One-sentence explanation for the end user. |
| Required | bool | Locked-on toggle. Use for strictly-necessary cookies (session, theme preference). |
ConsentService
| Member | Description |
|---|---|
| bool HasDecided | True once the user has answered the banner. While false, the banner shows. |
| bool HasConsent(string key) | Did the user consent to this category? "necessary" always returns true; unknown keys return false. |
| Task EnsureLoadedAsync() | Hydrate from localStorage. Called automatically by the banner on first render; safe to call yourself before the banner mounts. |
| Task AcceptAllAsync(IEnumerable<string>) | Grant every non-necessary category. Persists to localStorage. Fires OnChange. |
| Task RejectAllAsync(IEnumerable<string>) | Deny every non-necessary category. Persists and fires OnChange. |
| Task SetManyAsync(IReadOnlyDictionary<string, bool>) | Commit a per-category map. Used by the preferences dialog's Save button. |
| Task ResetAsync() | Clear the stored decision — banner re-appears on next render. |
| void RequestOpenPreferences() | Ask any mounted <ConsentBanner> to pop its dialog. Wire a "Cookie settings" footer link to this (as this site's footer does). |
| string PolicyVersion | Policy version to ask consent for. Set from the banner's PolicyVersion parameter; a stored decision from another version re-prompts. |
| DateTimeOffset? DecidedAtUtc | UTC timestamp of the last recorded decision (proof of consent), or null if none stored. |
| string? DecisionPolicyVersion | Policy version the last recorded decision was given against. Null for a legacy (versionless) record. |
| event Action? OnChange | Fires when any category value changes. Subscribe if you want to dynamically load / unload scripts. |
| event Action? OnRequestOpenPreferences | Internal coordination between RequestOpenPreferences and the banner. |