@c15t/nextjs 2.2.1 → 3.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +103 -142
- package/README.md +4 -4
- package/dist/api.js +1 -0
- package/dist/config.js +1 -0
- package/dist/devtools.js +2 -0
- package/dist/headers.js +1 -0
- package/dist/iab/styles.css +1 -1
- package/dist/iab/styles.tw3.css +27 -19
- package/dist/index.js +1 -1
- package/dist/middleware.js +1 -0
- package/dist/node-bridge.js +1 -0
- package/dist/pages.js +1 -0
- package/dist/proxy.js +1 -0
- package/dist/root.js +2 -0
- package/dist/server.js +1 -0
- package/dist/static.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/styles.tw3.css +67 -29
- package/dist/version.js +1 -1
- package/dist-types/api.d.ts +88 -0
- package/dist-types/config.d.ts +110 -0
- package/dist-types/devtools.d.ts +1 -0
- package/dist-types/headers.d.ts +4 -0
- package/dist-types/index.d.ts +28 -10
- package/dist-types/middleware.d.ts +15 -0
- package/dist-types/node-bridge.d.ts +57 -0
- package/dist-types/pages.d.ts +88 -0
- package/dist-types/proxy.d.ts +34 -0
- package/dist-types/root.d.ts +92 -0
- package/dist-types/server.d.ts +164 -0
- package/dist-types/static.d.ts +42 -0
- package/dist-types/types.d.ts +5 -36
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +103 -142
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/customization/overview.md +45 -0
- package/docs/customization/recipes.md +79 -0
- package/docs/customization/slots.md +55 -0
- package/docs/customization/tokens.md +76 -0
- package/docs/customization/translations.md +49 -0
- package/docs/frameworks/next/api-reference/data-fetching.md +416 -0
- package/docs/frameworks/next/app-router.md +403 -0
- package/docs/frameworks/next/client-side.md +118 -0
- package/docs/frameworks/next/components/consent-banner.md +251 -211
- package/docs/frameworks/next/components/consent-dialog-link.md +96 -35
- package/docs/frameworks/next/components/consent-dialog-trigger.md +74 -149
- package/docs/frameworks/next/components/consent-dialog.md +189 -134
- package/docs/frameworks/next/components/consent-manager-provider.md +68 -318
- package/docs/frameworks/next/components/consent-widget.md +172 -114
- package/docs/frameworks/next/components/dev-tools.md +199 -40
- package/docs/frameworks/next/components/frame.md +137 -42
- package/docs/frameworks/next/concepts/consent-categories.md +24 -89
- package/docs/frameworks/next/concepts/policy-presets.md +142 -0
- package/docs/frameworks/next/content-security-policy.md +189 -0
- package/docs/frameworks/next/data-fetching.md +74 -0
- package/docs/frameworks/next/geography-headers.md +251 -0
- package/docs/frameworks/next/headless.md +95 -185
- package/docs/frameworks/next/hooks/use-consent-manager/overview.md +42 -163
- package/docs/frameworks/next/iab/overview.md +37 -107
- package/docs/frameworks/next/optimization.md +158 -194
- package/docs/frameworks/next/pages-router.md +296 -0
- package/docs/frameworks/next/quickstart.md +31 -132
- package/docs/frameworks/next/script-loader.md +140 -465
- package/docs/frameworks/next/server-side.md +97 -130
- package/docs/frameworks/next/static-export.md +164 -0
- package/docs/frameworks/next/styling/overview.md +174 -248
- package/docs/frameworks/next/troubleshooting.md +134 -144
- package/docs/guides/consent-state.md +60 -0
- package/docs/guides/data-fetching.md +163 -0
- package/docs/guides/deployment-modes.md +63 -0
- package/docs/guides/troubleshooting.md +68 -0
- package/docs/guides/verify-consent.md +62 -0
- package/docs/integrations/adobe-analytics.md +239 -105
- package/docs/integrations/ahrefs-analytics.md +238 -104
- package/docs/integrations/amplitude.md +219 -157
- package/docs/integrations/building-integrations.md +32 -224
- package/docs/integrations/clear-on-revocation.md +167 -0
- package/docs/integrations/clearbit.md +247 -86
- package/docs/integrations/cloudflare-web-analytics.md +250 -84
- package/docs/integrations/crisp.md +251 -97
- package/docs/integrations/databuddy.md +259 -153
- package/docs/integrations/fathom-analytics.md +239 -96
- package/docs/integrations/google-maps.md +328 -207
- package/docs/integrations/google-tag-manager.md +248 -96
- package/docs/integrations/google-tag.md +261 -90
- package/docs/integrations/heap.md +222 -149
- package/docs/integrations/hightouch.md +225 -131
- package/docs/integrations/hotjar.md +239 -90
- package/docs/integrations/intercom.md +239 -98
- package/docs/integrations/linkedin-insights.md +243 -113
- package/docs/integrations/logrocket.md +241 -123
- package/docs/integrations/matomo-analytics.md +256 -111
- package/docs/integrations/meta-pixel.md +197 -324
- package/docs/integrations/microsoft-clarity.md +233 -114
- package/docs/integrations/microsoft-uet.md +245 -110
- package/docs/integrations/mixpanel-analytics.md +252 -87
- package/docs/integrations/openai-pixel.md +441 -0
- package/docs/integrations/overview.md +95 -133
- package/docs/integrations/pirsch.md +249 -96
- package/docs/integrations/plausible-analytics.md +241 -100
- package/docs/integrations/posthog.md +353 -214
- package/docs/integrations/promptwatch.md +251 -81
- package/docs/integrations/reddit-pixel.md +226 -173
- package/docs/integrations/rudderstack.md +244 -187
- package/docs/integrations/rybbit-analytics.md +244 -91
- package/docs/integrations/segment.md +238 -92
- package/docs/integrations/snapchat-pixel.md +240 -110
- package/docs/integrations/tiktok-pixel.md +249 -81
- package/docs/integrations/umami-analytics.md +242 -95
- package/docs/integrations/vercel-analytics.md +242 -90
- package/docs/integrations/x-pixel.md +238 -104
- package/docs/integrations/youtube.md +354 -142
- package/docs/upgrade-v3.md +334 -0
- package/iab/styles.css +1 -1
- package/iab/styles.tw3.css +1 -1
- package/package.json +106 -65
- package/readme.json +3 -3
- package/src/iab/styles.css +1 -1
- package/src/iab/styles.tw3.css +1 -1
- package/src/styles.css +1 -1
- package/src/styles.tw3.css +1 -1
- package/styles.css +1 -1
- package/styles.tw3.css +1 -1
- package/client/components/consent-dialog-link.js +0 -3
- package/client/components/integrations.js +0 -3
- package/dist/components/integrations/index.cjs +0 -1
- package/dist/components/integrations/index.js +0 -1
- package/dist/headless.cjs +0 -1
- package/dist/index.cjs +0 -1
- package/dist/libs/browser-initial-data.cjs +0 -1
- package/dist/libs/browser-initial-data.js +0 -1
- package/dist/libs/initial-data.cjs +0 -1
- package/dist/libs/initial-data.js +0 -1
- package/dist/types.cjs +0 -1
- package/dist/version.cjs +0 -1
- package/dist-types/components/integrations/index.d.ts +0 -1
- package/dist-types/libs/browser-initial-data.d.ts +0 -9
- package/dist-types/libs/initial-data.d.ts +0 -33
- package/docs/frameworks/next/building-headless-components.md +0 -379
- package/docs/frameworks/next/callbacks.md +0 -186
- package/docs/frameworks/next/concepts/client-modes.md +0 -177
- package/docs/frameworks/next/concepts/consent-models.md +0 -117
- package/docs/frameworks/next/concepts/cookie-management.md +0 -122
- package/docs/frameworks/next/concepts/glossary.md +0 -24
- package/docs/frameworks/next/concepts/initialization-flow.md +0 -149
- package/docs/frameworks/next/concepts/policy-packs.md +0 -230
- package/docs/frameworks/next/hooks/use-color-scheme.md +0 -41
- package/docs/frameworks/next/hooks/use-consent-manager/checking-consent.md +0 -96
- package/docs/frameworks/next/hooks/use-consent-manager/location-info.md +0 -97
- package/docs/frameworks/next/hooks/use-consent-manager/setting-consent.md +0 -94
- package/docs/frameworks/next/hooks/use-draggable.md +0 -59
- package/docs/frameworks/next/hooks/use-focus-trap.md +0 -42
- package/docs/frameworks/next/hooks/use-reduced-motion.md +0 -37
- package/docs/frameworks/next/hooks/use-ssr-status.md +0 -32
- package/docs/frameworks/next/hooks/use-text-direction.md +0 -50
- package/docs/frameworks/next/hooks/use-translations.md +0 -55
- package/docs/frameworks/next/iab/consent-banner.md +0 -91
- package/docs/frameworks/next/iab/consent-dialog.md +0 -129
- package/docs/frameworks/next/iab/use-gvl-data.md +0 -21
- package/docs/frameworks/next/iframe-blocking.md +0 -106
- package/docs/frameworks/next/internationalization.md +0 -207
- package/docs/frameworks/next/network-blocker.md +0 -140
- package/docs/frameworks/next/policy-packs.md +0 -248
- package/docs/frameworks/next/styling/classnames.md +0 -94
- package/docs/frameworks/next/styling/color-scheme.md +0 -84
- package/docs/frameworks/next/styling/css-variables.md +0 -53
- package/docs/frameworks/next/styling/slots.md +0 -94
- package/docs/frameworks/next/styling/tailwind.md +0 -137
- package/docs/frameworks/next/styling/tokens.md +0 -156
- package/docs/shared/concepts/client-modes.md +0 -103
- package/docs/shared/concepts/consent-categories.md +0 -41
- package/docs/shared/concepts/consent-models.md +0 -72
- package/docs/shared/concepts/cookie-management.md +0 -88
- package/docs/shared/concepts/glossary.md +0 -24
- package/docs/shared/concepts/initialization-flow.md +0 -105
- package/docs/shared/concepts/policy-packs.md +0 -225
- package/docs/shared/react/components/consent-banner.md +0 -242
- package/docs/shared/react/components/consent-dialog-link.md +0 -45
- package/docs/shared/react/components/consent-dialog-trigger.md +0 -185
- package/docs/shared/react/components/consent-dialog.md +0 -119
- package/docs/shared/react/components/consent-manager-provider.md +0 -225
- package/docs/shared/react/components/consent-widget.md +0 -121
- package/docs/shared/react/components/dev-tools.md +0 -81
- package/docs/shared/react/components/frame.md +0 -52
- package/docs/shared/react/guides/building-headless-components.md +0 -110
- package/docs/shared/react/guides/callbacks.md +0 -89
- package/docs/shared/react/guides/headless.md +0 -31
- package/docs/shared/react/guides/iframe-blocking.md +0 -65
- package/docs/shared/react/guides/internationalization.md +0 -123
- package/docs/shared/react/guides/network-blocker.md +0 -72
- package/docs/shared/react/guides/optimization.md +0 -44
- package/docs/shared/react/guides/policy-packs.md +0 -173
- package/docs/shared/react/guides/script-loader.md +0 -311
- package/docs/shared/react/hooks/use-color-scheme.md +0 -31
- package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +0 -95
- package/docs/shared/react/hooks/use-consent-manager/location-info.md +0 -96
- package/docs/shared/react/hooks/use-consent-manager/overview.md +0 -74
- package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +0 -93
- package/docs/shared/react/hooks/use-draggable.md +0 -30
- package/docs/shared/react/hooks/use-focus-trap.md +0 -20
- package/docs/shared/react/hooks/use-reduced-motion.md +0 -33
- package/docs/shared/react/hooks/use-ssr-status.md +0 -16
- package/docs/shared/react/hooks/use-text-direction.md +0 -38
- package/docs/shared/react/hooks/use-translations.md +0 -15
- package/docs/shared/react/iab/consent-banner.md +0 -60
- package/docs/shared/react/iab/consent-dialog.md +0 -76
- package/docs/shared/react/iab/overview.md +0 -80
- package/docs/shared/react/iab/use-gvl-data.md +0 -21
- package/docs/shared/react/styling/classnames.md +0 -93
- package/docs/shared/react/styling/color-scheme.md +0 -35
- package/docs/shared/react/styling/css-variables.md +0 -53
- package/docs/shared/react/styling/overview.md +0 -261
- package/docs/shared/react/styling/slots.md +0 -93
- package/docs/shared/react/styling/stylesheet-entrypoint.md +0 -8
- package/docs/shared/react/styling/tailwind.md +0 -88
- package/docs/shared/react/styling/tokens.md +0 -155
- package/docs/shared/troubleshooting.md +0 -82
|
@@ -1,258 +1,298 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: ConsentBanner
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
markup must change.
|
|
3
|
+
description: Render the pre-built ConsentBanner inside a Next.js ConsentRoot and
|
|
4
|
+
configure its variants, per-policy buttons and compound parts.
|
|
6
5
|
group: frameworks
|
|
7
6
|
---
|
|
8
|
-
`ConsentBanner` is a ready-to-use consent banner that appears automatically in **opt-in jurisdictions** (like GDPR) where explicit consent is required before tracking. In opt-out jurisdictions (like CCPA), the banner won't appear — users get an opt-out mechanism instead. It includes reject, accept, and customize buttons with configurable layout.
|
|
9
7
|
|
|
10
|
-
##
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
Keep the `ConsentRoot` and URL configuration from your
|
|
11
|
+
[App Router setup](../app-router.md). Render one banner inside
|
|
12
|
+
that existing root. Keep the global stylesheet from that setup,
|
|
13
|
+
with the c15t import after Tailwind CSS 4's import:
|
|
11
14
|
|
|
12
15
|
```tsx
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
// app/layout.tsx
|
|
17
|
+
import { ConsentBanner, ConsentDialog, ConsentRoot } from 'c15t/next';
|
|
18
|
+
import { resolveConsent } from 'c15t/next/server';
|
|
19
|
+
import { consentConfig } from '../c15t.config';
|
|
20
|
+
import './globals.css';
|
|
21
|
+
|
|
22
|
+
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
23
|
+
const state = resolveConsent({ config: consentConfig });
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<html lang="en">
|
|
27
|
+
<body>
|
|
28
|
+
<ConsentRoot state={state} config={consentConfig}>
|
|
29
|
+
{children}
|
|
30
|
+
<ConsentBanner />
|
|
31
|
+
<ConsentDialog />
|
|
32
|
+
</ConsentRoot>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
35
|
+
);
|
|
21
36
|
}
|
|
22
37
|
```
|
|
23
38
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
The banner renders what the resolved policy rule requires. This example lets
|
|
40
|
+
the page render while the prompt waits for the prefetch promise. Await the
|
|
41
|
+
helper inside `Suspense` to render resolved consent UI on the server; the
|
|
42
|
+
surrounding shell may stream first. The server and client use the same
|
|
43
|
+
prepared state:
|
|
44
|
+
|
|
45
|
+
* A `choice` prompt shows the actions the rule allows: reject and accept at
|
|
46
|
+
equal prominence, plus customize when the rule offers it.
|
|
47
|
+
* A `notice` prompt shows an "OK" button and a button styled as
|
|
48
|
+
underlined text, labeled "Do not sell or share my data". The latter opens
|
|
49
|
+
preferences. A notice never traps focus or locks scroll.
|
|
50
|
+
* A rule with `prompt: 'none'` renders nothing.
|
|
51
|
+
|
|
52
|
+
An opt-out rule with `prompt: 'none'` still has rights, so the preference
|
|
53
|
+
center and the dialog trigger stay available as the route to preferences. A
|
|
54
|
+
rule with `model: 'none'` owes no rights, so nothing renders unless you add
|
|
55
|
+
`rights: ['preferences']`. With no resolved rule at all, because resolution
|
|
56
|
+
failed, no rule matched and you set no default, or init is still withheld, no
|
|
57
|
+
consent surface renders: not the banner, the dialog, the widget, the
|
|
58
|
+
preferences link, or the trigger. They appear as soon as a rule resolves,
|
|
59
|
+
without a remount. `offline()` without `policyRules` resolves the recommended
|
|
60
|
+
pack, so it shows the strict opt-in banner until you pass a country.
|
|
61
|
+
|
|
62
|
+
Acknowledging a notice records its dismissal. It does not record consent or
|
|
63
|
+
change category permissions, including existing denials and privacy-signal
|
|
64
|
+
restrictions. Customize the label through `common.acknowledge` in your
|
|
65
|
+
translations, or use `dismissButtonText` for one banner.
|
|
66
|
+
|
|
67
|
+
The additional preferences button uses the opt-out label when appropriate.
|
|
68
|
+
A choice prompt without Customize renders a "Manage preferences" button.
|
|
69
|
+
Both are button elements that open the preference center; CSS gives them
|
|
70
|
+
an underlined text appearance. They do not submit an opt-out by themselves.
|
|
71
|
+
|
|
72
|
+
`preferenceControls` recommends these extra buttons for the stock UI.
|
|
73
|
+
It does not verify disclosure or access to rights. Configure your legal links
|
|
74
|
+
and keep preferences reachable after the banner closes.
|
|
34
75
|
|
|
35
|
-
|
|
36
|
-
<ConsentBanner layout={['accept', ['reject', 'customize']]} />
|
|
37
|
-
```
|
|
76
|
+
## Props
|
|
38
77
|
|
|
39
|
-
|
|
78
|
+
| Prop | Type | Default | Description |
|
|
79
|
+
| --------------------- | --------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
80
|
+
| `title` | `ReactNode` | translation | Overrides the title. Under a notice the default is `cookieBanner.noticeTitle`. |
|
|
81
|
+
| `description` | `ReactNode` | translation | Overrides the description. Under a notice the default is `cookieBanner.noticeDescription`. |
|
|
82
|
+
| `acceptButtonText` | `ReactNode` | `common.acceptAll` | Accept label. |
|
|
83
|
+
| `rejectButtonText` | `ReactNode` | `common.rejectAll` | Reject label. |
|
|
84
|
+
| `customizeButtonText` | `ReactNode` | `common.customize` | Customize label. |
|
|
85
|
+
| `dismissButtonText` | `ReactNode` | `common.acknowledge` | Label of the notice acknowledgement. |
|
|
86
|
+
| `variant` | `PromptVariant` | `floating` | Shape of the prompt. See [Variants](#variants). |
|
|
87
|
+
| `position` | `PromptPosition` | per variant | Where the prompt sits. Must be valid for the variant. |
|
|
88
|
+
| `blocking` | `boolean` | `true` on `wall` | Backdrop, scroll lock, focus trap, and no outside dismissal, as one value. |
|
|
89
|
+
| `layout` | `ConsentBannerLayout` | policy default | Orders and groups actions. Required actions the layout omits are restored. |
|
|
90
|
+
| `primaryButton` | `ConsentBannerButton \|ConsentBannerButton[]` | `'customize'` | Which actions get the primary treatment. On a notice, dismiss is primary when it is the only action. |
|
|
91
|
+
| `direction` | `'row' \|'column'` | `'row'` | How action groups flow. |
|
|
92
|
+
| `legalLinks` | `(keyof LegalLinks)[] \|null` | none | Which configured legal links render inline. |
|
|
93
|
+
| `hideBranding` | `boolean` | `false` | Hides the "Secured by" tag. |
|
|
94
|
+
| `scrollLock` | `boolean` | unset | Deprecated. Use `blocking` to control scrolling, focus and backdrop together. |
|
|
95
|
+
| `trapFocus` | `boolean` | unset | Deprecated. Use `blocking`. |
|
|
96
|
+
| `disableAnimation` | `boolean` | `false` | Skips enter and exit animations. |
|
|
97
|
+
| `noStyle` | `boolean` | `false` | Removes the built-in styling from every part. |
|
|
98
|
+
|
|
99
|
+
## Per-policy buttons
|
|
100
|
+
|
|
101
|
+
The default already makes Customize primary on a choice banner and OK
|
|
102
|
+
primary on a notice. To set button order and treatment for specific rules,
|
|
103
|
+
read the active policy inside the provider:
|
|
40
104
|
|
|
41
105
|
```tsx
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
106
|
+
'use client';
|
|
107
|
+
|
|
108
|
+
import { ConsentBanner, usePolicyRule } from 'c15t/next';
|
|
109
|
+
import type { ConsentBannerProps } from 'c15t/next';
|
|
110
|
+
|
|
111
|
+
const banners: Record<
|
|
112
|
+
string,
|
|
113
|
+
Pick<ConsentBannerProps, 'layout' | 'primaryButton' | 'variant'>
|
|
114
|
+
> = {
|
|
115
|
+
europe_opt_in: {
|
|
116
|
+
layout: [['reject', 'accept'], 'customize'],
|
|
117
|
+
primaryButton: 'customize',
|
|
118
|
+
},
|
|
119
|
+
us_privacy_states: {
|
|
120
|
+
layout: ['dismiss'],
|
|
121
|
+
primaryButton: 'dismiss',
|
|
122
|
+
variant: 'bar',
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export function RegionalBanner() {
|
|
127
|
+
const policy = usePolicyRule();
|
|
128
|
+
return <ConsentBanner {...(policy ? banners[policy.id] : undefined)} />;
|
|
129
|
+
}
|
|
46
130
|
```
|
|
47
131
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
consentActions: {
|
|
65
|
-
default: { mode: 'stroke' },
|
|
66
|
-
accept: { variant: 'primary', mode: 'stroke' },
|
|
67
|
-
customize: { variant: 'neutral', mode: 'ghost' },
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
}}
|
|
71
|
-
>
|
|
72
|
-
<ConsentBanner />
|
|
73
|
-
</ConsentManagerProvider>
|
|
132
|
+
Render `RegionalBanner` inside your existing consent boundary, replacing its
|
|
133
|
+
stock banner. The layout controls the
|
|
134
|
+
action groups; the opt-out preferences button still appears on a notice.
|
|
135
|
+
Required actions omitted from a layout are restored. Accept and Reject
|
|
136
|
+
keep equivalent default prominence.
|
|
137
|
+
|
|
138
|
+
Choose one brand color and make whichever action is primary use a filled
|
|
139
|
+
button through the provider's theme:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
const theme = {
|
|
143
|
+
colors: { primary: '#2f6f4e', primaryHover: '#24563c' },
|
|
144
|
+
consentActions: {
|
|
145
|
+
primary: { variant: 'primary', mode: 'filled' },
|
|
146
|
+
},
|
|
147
|
+
} as const;
|
|
74
148
|
```
|
|
75
149
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
150
|
+
Pass `theme` in `ConsentProvider` options. Per-action theme overrides such
|
|
151
|
+
as `consentActions.dismiss` take precedence over this primary style.
|
|
152
|
+
See [Styling](../styling/overview.md) for tokens and slots, and
|
|
153
|
+
[Policy presets](../concepts/policy-presets.md) for the rule IDs and coverage.
|
|
79
154
|
|
|
80
|
-
|
|
81
|
-
> For pure theming, stay inside the pre-built banner. Start with layout props, theme.consentActions, design tokens, and theme.slots before reaching for compound components. See Styling Overview.
|
|
155
|
+
## Variants
|
|
82
156
|
|
|
83
|
-
The
|
|
157
|
+
The policy decides which actions the banner offers. The variant decides the
|
|
158
|
+
shape those actions take. Both come from the same component, so a bar for a
|
|
159
|
+
notice region and a card for an opt-in region need no extra components.
|
|
84
160
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
* Card, footer, and title tweaks -> `theme.slots.consentBannerCard`, `consentBannerFooter`, and `consentBannerTitle`
|
|
161
|
+
Set the variant on the banner, or on the provider under
|
|
162
|
+
`presentation.prompt` when every banner should share it. The prop wins.
|
|
88
163
|
|
|
89
164
|
```tsx
|
|
90
|
-
<
|
|
91
|
-
options={{
|
|
92
|
-
theme: {
|
|
93
|
-
colors: {
|
|
94
|
-
surface: '#fffdf8',
|
|
95
|
-
surfaceHover: '#f6f3ee',
|
|
96
|
-
},
|
|
97
|
-
slots: {
|
|
98
|
-
consentBannerCard: 'rounded-[28px] shadow-xl',
|
|
99
|
-
consentBannerFooter: 'border-t border-black/10 px-6',
|
|
100
|
-
consentBannerTitle: 'tracking-tight',
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
}}
|
|
104
|
-
>
|
|
105
|
-
<ConsentBanner />
|
|
106
|
-
</ConsentManagerProvider>
|
|
165
|
+
<ConsentBanner variant="floating" position="bottom-center" />
|
|
107
166
|
```
|
|
108
167
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
Highlight specific button(s) as the primary action:
|
|
168
|
+
A floating card in a corner or centered on an edge. This is the default for
|
|
169
|
+
every prompt. A notice keeps the same card, with its right link and "OK" in the footer.
|
|
112
170
|
|
|
113
171
|
```tsx
|
|
114
|
-
|
|
115
|
-
<ConsentBanner primaryButton="accept" />
|
|
116
|
-
|
|
117
|
-
{/* Multiple primaries */}
|
|
118
|
-
<ConsentBanner primaryButton={['accept', 'customize']} />
|
|
172
|
+
<ConsentBanner variant="bar" position="top" />
|
|
119
173
|
```
|
|
120
174
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
175
|
+
A bar across the full width of the viewport. From 1024px wide the text, the
|
|
176
|
+
right links, and the controls share one row. Opt in to it for regions that
|
|
177
|
+
expect a classic cookie bar.
|
|
124
178
|
|
|
125
179
|
```tsx
|
|
126
|
-
|
|
127
|
-
<ConsentBanner legalLinks={undefined} />
|
|
128
|
-
|
|
129
|
-
{/* Show no links */}
|
|
130
|
-
<ConsentBanner legalLinks={null} />
|
|
131
|
-
|
|
132
|
-
{/* Show specific links */}
|
|
133
|
-
<ConsentBanner legalLinks={['privacyPolicy', 'cookiePolicy']} />
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
> ℹ️ **Info:**
|
|
137
|
-
> Legal link URLs are configured in the ConsentManagerProvider options via the legalLinks prop, not on the banner itself.
|
|
138
|
-
|
|
139
|
-
## Customizing Copy
|
|
140
|
-
|
|
141
|
-
Prefer provider `i18n` when you want to rename the stock banner content:
|
|
142
|
-
|
|
143
|
-
```tsx
|
|
144
|
-
<ConsentManagerProvider
|
|
145
|
-
options={{
|
|
146
|
-
i18n: {
|
|
147
|
-
locale: 'en',
|
|
148
|
-
messages: {
|
|
149
|
-
en: {
|
|
150
|
-
cookieBanner: {
|
|
151
|
-
title: 'We value your privacy',
|
|
152
|
-
description: 'We use cookies to improve the site and measure performance.',
|
|
153
|
-
},
|
|
154
|
-
common: {
|
|
155
|
-
acceptAll: 'Accept all',
|
|
156
|
-
rejectAll: 'Reject all',
|
|
157
|
-
customize: 'Manage preferences',
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
}}
|
|
163
|
-
>
|
|
164
|
-
<ConsentBanner />
|
|
165
|
-
</ConsentManagerProvider>
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Direct text props such as `title`, `description`, and `acceptButtonText` are still supported for one-off overrides, but `i18n` is the preferred path for copy changes.
|
|
169
|
-
|
|
170
|
-
## Advanced: Compound Components
|
|
171
|
-
|
|
172
|
-
Use compound components only when the stock banner structure is no longer enough and you need to rearrange existing c15t primitives while keeping policy-driven action grouping and emphasis:
|
|
173
|
-
|
|
174
|
-
```tsx
|
|
175
|
-
<ConsentBanner.Root>
|
|
176
|
-
<ConsentBanner.Overlay />
|
|
177
|
-
<ConsentBanner.Card>
|
|
178
|
-
<ConsentBanner.Header>
|
|
179
|
-
<ConsentBanner.Title />
|
|
180
|
-
<ConsentBanner.Description />
|
|
181
|
-
</ConsentBanner.Header>
|
|
182
|
-
<ConsentBanner.PolicyActions />
|
|
183
|
-
</ConsentBanner.Card>
|
|
184
|
-
</ConsentBanner.Root>
|
|
180
|
+
<ConsentBanner variant="widget" position="bottom-right" />
|
|
185
181
|
```
|
|
186
182
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
* `ConsentBanner.Header` — Contains title and description
|
|
190
|
-
* `ConsentBanner.Title` — Heading, defaults to translation `consentBanner.title`
|
|
191
|
-
* `ConsentBanner.Description` — Description text, supports `legalLinks` prop
|
|
192
|
-
* `ConsentBanner.PolicyActions` — Renders policy-aware grouped actions inside the banner footer
|
|
193
|
-
* `ConsentBanner.Footer` — Action buttons container
|
|
194
|
-
* `ConsentBanner.FooterSubGroup` — Groups related buttons together
|
|
195
|
-
* `ConsentBanner.RejectButton` — Rejects all consent
|
|
196
|
-
* `ConsentBanner.CustomizeButton` — Opens the consent dialog
|
|
197
|
-
* `ConsentBanner.AcceptButton` — Accepts all consent
|
|
198
|
-
* `ConsentBanner.Overlay` — Optional backdrop overlay
|
|
199
|
-
|
|
200
|
-
For a fixed layout that intentionally ignores policy grouping, render the footer manually:
|
|
183
|
+
A compact card with smaller type. The full description and its legal links
|
|
184
|
+
remain visible. Pair it with a short notice.
|
|
201
185
|
|
|
202
186
|
```tsx
|
|
203
|
-
<ConsentBanner
|
|
204
|
-
<ConsentBanner.Card>
|
|
205
|
-
<ConsentBanner.Header>
|
|
206
|
-
<ConsentBanner.Title />
|
|
207
|
-
<ConsentBanner.Description />
|
|
208
|
-
</ConsentBanner.Header>
|
|
209
|
-
<ConsentBanner.Footer>
|
|
210
|
-
<ConsentBanner.FooterSubGroup>
|
|
211
|
-
<ConsentBanner.RejectButton />
|
|
212
|
-
<ConsentBanner.AcceptButton />
|
|
213
|
-
</ConsentBanner.FooterSubGroup>
|
|
214
|
-
<ConsentBanner.CustomizeButton />
|
|
215
|
-
</ConsentBanner.Footer>
|
|
216
|
-
</ConsentBanner.Card>
|
|
217
|
-
</ConsentBanner.Root>
|
|
187
|
+
<ConsentBanner variant="wall" />
|
|
218
188
|
```
|
|
219
189
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
190
|
+
A centered card over a backdrop that blocks the page until the visitor
|
|
191
|
+
answers. A wall is always blocking.
|
|
192
|
+
|
|
193
|
+
Each variant accepts its own positions:
|
|
194
|
+
|
|
195
|
+
| Variant | Positions | Default |
|
|
196
|
+
| ---------- | ------------------------------------------------------------------------------------- | -------------- |
|
|
197
|
+
| `floating` | `bottom-left`, `bottom-right`, `top-left`, `top-right`, `bottom-center`, `top-center` | `bottom-left` |
|
|
198
|
+
| `bar` | `top`, `bottom` | `bottom` |
|
|
199
|
+
| `widget` | `bottom-left`, `bottom-right`, `top-left`, `top-right` | `bottom-right` |
|
|
200
|
+
| `wall` | `center` | `center` |
|
|
201
|
+
|
|
202
|
+
A default corner mirrors left and right for right-to-left languages. A
|
|
203
|
+
position you set is never mirrored. A position that is not valid for the
|
|
204
|
+
variant falls back to the default and logs an `invalid-position` diagnostic
|
|
205
|
+
in development.
|
|
206
|
+
|
|
207
|
+
`blocking` controls the backdrop, scroll lock, and focus trap together.
|
|
208
|
+
An explicit value overrides the deprecated `scrollLock` and `trapFocus`
|
|
209
|
+
options. Without `blocking`, either legacy option set to `false` selects
|
|
210
|
+
non-blocking behavior; otherwise a legacy `true` selects blocking behavior.
|
|
211
|
+
|
|
212
|
+
A choice `wall` always blocks. Notices always stay non-blocking, and asking
|
|
213
|
+
for a notice `wall` falls back to `floating` with an `invalid-variant`
|
|
214
|
+
diagnostic. Blocking banners carry `role="dialog"` and `aria-modal="true"`.
|
|
215
|
+
Non-blocking banners leave page controls usable by keyboard and pointer.
|
|
216
|
+
|
|
217
|
+
`PromptVariant` and `PromptPosition` are exported from `c15t/next`.
|
|
218
|
+
Compound parts can read the resolved shape with `useConsentBannerSurface()`,
|
|
219
|
+
which returns `variant`, `position`, `positionSource` (`host` or `default`),
|
|
220
|
+
and `blocking`.
|
|
221
|
+
|
|
222
|
+
## Composition
|
|
223
|
+
|
|
224
|
+
Every part is available as `ConsentBanner.<Part>` for custom layouts. The
|
|
225
|
+
parts read the same policy state the pre-built banner does, so a custom layout
|
|
226
|
+
still gets the right actions for the active rule. Render this Client Component
|
|
227
|
+
inside the existing boundary, replacing its stock banner. Keep the dialog and
|
|
228
|
+
persistent preferences control.
|
|
229
|
+
|
|
230
|
+
```tsx title="components/compact-banner.tsx"
|
|
231
|
+
'use client';
|
|
232
|
+
|
|
233
|
+
import { ConsentBanner } from 'c15t/next';
|
|
234
|
+
|
|
235
|
+
export function CompactBanner() {
|
|
236
|
+
return (
|
|
237
|
+
<ConsentBanner.Root>
|
|
238
|
+
<ConsentBanner.Card>
|
|
239
|
+
<ConsentBanner.Header>
|
|
240
|
+
<ConsentBanner.Title />
|
|
241
|
+
<ConsentBanner.Description />
|
|
242
|
+
</ConsentBanner.Header>
|
|
243
|
+
<ConsentBanner.PolicyActions />
|
|
244
|
+
</ConsentBanner.Card>
|
|
245
|
+
</ConsentBanner.Root>
|
|
246
|
+
);
|
|
247
|
+
}
|
|
226
248
|
```
|
|
227
249
|
|
|
228
|
-
`
|
|
250
|
+
`ConsentBanner.PolicyActions` renders the resolved action groups and, before
|
|
251
|
+
them, the additional preferences buttons. Pass children to replace those
|
|
252
|
+
buttons while retaining the policy action groups. This supports custom labels
|
|
253
|
+
and button markup.
|
|
254
|
+
|
|
255
|
+
Use the individual parts when you need a different order or your own markup:
|
|
256
|
+
|
|
257
|
+
* `ConsentBanner.AcceptButton`, `ConsentBanner.RejectButton`,
|
|
258
|
+
`ConsentBanner.CustomizeButton`, and `ConsentBanner.DismissButton` render one
|
|
259
|
+
action each. `DismissButton` defaults its label to `common.acknowledge`.
|
|
260
|
+
* `ConsentBanner.Rights` renders the additional preferences buttons. It
|
|
261
|
+
renders nothing when the list is empty. Pass `rights` to override the
|
|
262
|
+
list.
|
|
263
|
+
* `ConsentBanner.RightLink` renders a single right. `right` is `'opt-out'`
|
|
264
|
+
or `'preferences'`. By default it is a button element styled as an
|
|
265
|
+
underlined text link, carrying `data-action="right"` and `data-right`; it
|
|
266
|
+
opens the preference center on click and accepts `asChild` to render your
|
|
267
|
+
own element, such as an anchor to a dedicated opt-out page.
|
|
229
268
|
|
|
230
269
|
```tsx
|
|
231
|
-
<ConsentBanner.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
case 'accept':
|
|
237
|
-
return <ConsentBanner.AcceptButton key={key} {...buttonProps} />
|
|
238
|
-
case 'reject':
|
|
239
|
-
return <ConsentBanner.RejectButton key={key} {...buttonProps} />
|
|
240
|
-
case 'customize':
|
|
241
|
-
return <ConsentBanner.CustomizeButton key={key} {...buttonProps} />
|
|
242
|
-
}
|
|
243
|
-
}}
|
|
244
|
-
/>
|
|
270
|
+
<ConsentBanner.Rights>
|
|
271
|
+
<ConsentBanner.RightLink right="opt-out" asChild>
|
|
272
|
+
<a href="/privacy/do-not-sell">Do not sell or share my data</a>
|
|
273
|
+
</ConsentBanner.RightLink>
|
|
274
|
+
</ConsentBanner.Rights>
|
|
245
275
|
```
|
|
246
276
|
|
|
247
|
-
`
|
|
277
|
+
`useBannerCopy()` returns the title, description, and prompt kind the banner
|
|
278
|
+
would use, for custom headers that still follow the notice copy.
|
|
248
279
|
|
|
249
|
-
|
|
280
|
+
## Data attributes
|
|
250
281
|
|
|
251
|
-
|
|
282
|
+
The root element carries attributes you can target from CSS or Tailwind. The
|
|
283
|
+
card carries `data-state` (`open` or `closed`) for the enter and exit
|
|
284
|
+
animations.
|
|
252
285
|
|
|
253
|
-
|
|
|
254
|
-
|
|
255
|
-
|
|
|
256
|
-
|
|
|
286
|
+
| Attribute | Values |
|
|
287
|
+
| --------------- | ------------------------------------- |
|
|
288
|
+
| `data-prompt` | `choice`, `notice` |
|
|
289
|
+
| `data-model` | `opt-in`, `opt-out`, `iab` |
|
|
290
|
+
| `data-variant` | `floating`, `bar`, `widget`, `wall` |
|
|
291
|
+
| `data-position` | The resolved position for the variant |
|
|
292
|
+
| `data-blocking` | `true`, present only while blocking |
|
|
257
293
|
|
|
258
|
-
|
|
294
|
+
Each action button carries `data-action`, and each right link carries
|
|
295
|
+
`data-action="right"` plus `data-right`. The built-in stylesheet keys every
|
|
296
|
+
variant's geometry on `data-variant` and `data-position`, and uses
|
|
297
|
+
`data-prompt="notice"` to lay the footer out as one row with the right
|
|
298
|
+
links leading and "OK" trailing.
|