@c15t/react 3.0.0-alpha.3 → 3.0.0-alpha.4
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 +91 -72
- package/README.md +21 -17
- package/SKILL.md +34 -0
- package/dist/component-hooks/use-headless-consent-ui.js +1 -1
- package/dist/components/consent-gate/atoms.js +1 -1
- package/dist/components/consent-gate/consent-gate.js +1 -1
- package/dist/components/iab-panel/atoms/card.js +1 -1
- package/dist/components/iab-panel/atoms/feature-item.js +2 -0
- package/dist/components/iab-panel/atoms/header.js +1 -1
- package/dist/components/iab-panel/iab-panel.js +1 -1
- package/dist/components/iab-panel/index.js +1 -1
- package/dist/components/iab-prompt/atoms/overlay.js +1 -1
- package/dist/components/iab-prompt/atoms/root.js +1 -1
- package/dist/components/panel/atoms/card.js +1 -1
- package/dist/components/panel/atoms/root.js +1 -1
- package/dist/components/panel-trigger/atoms/button.js +1 -1
- package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
- package/dist/components/preferences/atoms/accordion.js +1 -1
- package/dist/components/prompt/atoms/overlay.js +1 -1
- package/dist/components/prompt/atoms/root.js +1 -1
- package/dist/components/prompt/components.js +1 -1
- package/dist/components/shared/libs/compose-refs.js +1 -0
- package/dist/components/shared/libs/slot.js +1 -1
- package/dist/components/shared/primitives/button.js +1 -1
- package/dist/components/shared/ui/dialog/dialog.js +1 -1
- package/dist/components/shared/ui/icon.js +1 -1
- package/dist/context/consent-tracking-context.js +1 -1
- package/dist/devtools.js +1 -1
- package/dist/draft.js +1 -1
- package/dist/hooks/use-focus-trap.js +1 -1
- package/dist/hooks.js +1 -1
- package/dist/iab/styles.tw3.css +4 -4
- package/dist/index.js +1 -1
- package/dist/module-hooks/iframe-blocker.js +1 -1
- package/dist/postcss-tailwind3.js +1 -0
- package/dist/provider.js +1 -1
- package/dist/server/fetch-ssr-data.js +1 -1
- package/dist/server/headers.js +1 -1
- package/dist/server/normalize-url.js +1 -1
- package/dist/styles.tw3.css +16 -16
- package/dist/transports/offline.js +1 -1
- package/dist/ui-save.js +1 -1
- package/dist/utils/merge-slot-props.js +1 -1
- package/dist/utils/theme-utils.js +1 -1
- package/dist/version.js +1 -1
- package/dist-types/component-hooks/use-headless-consent-ui.d.ts +1 -1
- package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
- package/dist-types/components/iab-panel/iab-panel.d.ts +2 -2
- package/dist-types/components/iab-panel/index.d.ts +5 -2
- package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
- package/dist-types/components/iab-prompt/iab-prompt.d.ts +2 -2
- package/dist-types/components/iab-prompt/index.d.ts +2 -2
- package/dist-types/components/panel/atoms/card.d.ts +1 -0
- package/dist-types/components/prompt/components.d.ts +6 -0
- package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
- package/dist-types/components/shared/ui/icon.d.ts +2 -1
- package/dist-types/context/consent-tracking-context.d.ts +10 -0
- package/dist-types/context/theme-context.d.ts +2 -2
- package/dist-types/context.d.ts +6 -0
- package/dist-types/devtools.d.ts +13 -2
- package/dist-types/draft.d.ts +10 -4
- package/dist-types/hooks/use-focus-trap.d.ts +3 -1
- package/dist-types/hooks.d.ts +54 -13
- package/dist-types/iab.d.ts +1 -1
- package/dist-types/index.d.ts +2 -2
- package/dist-types/postcss-tailwind3.d.ts +21 -0
- package/dist-types/provider.d.ts +22 -5
- package/dist-types/server/headers.d.ts +14 -4
- package/dist-types/server/normalize-url.d.ts +14 -7
- package/dist-types/server/types.d.ts +12 -1
- package/dist-types/transports/offline.d.ts +7 -16
- package/dist-types/ui-config-context.d.ts +7 -1
- package/dist-types/utils/merge-slot-props.d.ts +15 -1
- package/dist-types/utils/theme-utils.d.ts +17 -2
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +91 -72
- package/docs/assets/v3/bottom-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/brand-preferences.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/headless-bar-html.png +0 -0
- package/docs/assets/v3/headless-bar-mobile.png +0 -0
- package/docs/assets/v3/headless-bar.png +0 -0
- package/docs/assets/v3/slim-bar.png +0 -0
- package/docs/concepts/choose-your-setup.md +87 -0
- package/docs/{frameworks/react/concepts → concepts}/consent-categories.md +22 -7
- package/docs/{guides → concepts}/consent-state.md +71 -101
- package/docs/{guides → concepts}/data-fetching.md +31 -27
- package/docs/concepts/how-consent-works.md +123 -0
- package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +7 -59
- package/docs/customization/class-names.md +202 -0
- package/docs/customization/dark-mode.md +157 -0
- package/docs/customization/motion.md +119 -0
- package/docs/customization/overview.md +67 -34
- package/docs/customization/recipes.md +839 -49
- package/docs/customization/slots.md +216 -35
- package/docs/customization/stylesheets.md +147 -0
- package/docs/customization/tailwind.md +842 -0
- package/docs/customization/tokens.md +163 -96
- package/docs/customization/translations.md +61 -3
- package/docs/frameworks/react/callbacks.md +118 -0
- package/docs/frameworks/react/clear-on-revocation.md +106 -0
- package/docs/frameworks/react/components/consent-banner.md +42 -28
- package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
- package/docs/frameworks/react/components/consent-dialog-trigger.md +81 -76
- package/docs/frameworks/react/components/consent-dialog.md +56 -50
- package/docs/frameworks/react/components/consent-gate.md +37 -20
- package/docs/frameworks/react/components/consent-provider.md +126 -0
- package/docs/frameworks/react/components/consent-widget.md +23 -20
- package/docs/frameworks/react/components/dev-tools.md +52 -84
- package/docs/frameworks/react/components.md +105 -0
- package/docs/frameworks/react/compose.md +354 -0
- package/docs/frameworks/react/content-security-policy.md +126 -0
- package/docs/frameworks/react/customize.md +250 -0
- package/docs/frameworks/react/embeds.md +89 -0
- package/docs/frameworks/react/{hooks/overview.md → hooks.md} +21 -16
- package/docs/frameworks/react/{iab/overview.md → iab.md} +80 -31
- package/docs/frameworks/react/network-blocker.md +35 -41
- package/docs/frameworks/react/quickstart.md +139 -101
- package/docs/frameworks/react/rendering.md +128 -0
- package/docs/frameworks/react/scripts.md +115 -0
- package/docs/frameworks/react/translations.md +155 -0
- package/docs/frameworks/react/troubleshooting.md +92 -47
- package/docs/frameworks/react/vendor-consent.md +170 -0
- package/docs/guides/banner-experiments.md +654 -0
- package/docs/guides/troubleshooting.md +120 -47
- package/docs/guides/verify-consent.md +81 -49
- package/docs/integrations/adobe-analytics.md +167 -159
- package/docs/integrations/ahrefs-analytics.md +152 -154
- package/docs/integrations/amplitude.md +162 -156
- package/docs/integrations/building-integrations.md +136 -37
- package/docs/integrations/clearbit.md +154 -154
- package/docs/integrations/cloudflare-web-analytics.md +156 -156
- package/docs/integrations/cloudflare-zaraz.md +209 -261
- package/docs/integrations/crisp.md +164 -158
- package/docs/integrations/databuddy.md +157 -173
- package/docs/integrations/fathom-analytics.md +158 -156
- package/docs/integrations/front-chat.md +167 -167
- package/docs/integrations/google-maps.md +118 -83
- package/docs/integrations/google-tag-manager.md +178 -163
- package/docs/integrations/google-tag.md +163 -160
- package/docs/integrations/heap.md +163 -155
- package/docs/integrations/hightouch.md +161 -157
- package/docs/integrations/hotjar.md +159 -155
- package/docs/integrations/intercom.md +183 -153
- package/docs/integrations/klaviyo.md +486 -0
- package/docs/integrations/linkedin-insights.md +174 -150
- package/docs/integrations/logrocket.md +160 -156
- package/docs/integrations/matomo-analytics.md +188 -178
- package/docs/integrations/meta-pixel.md +188 -150
- package/docs/integrations/microsoft-clarity.md +163 -155
- package/docs/integrations/microsoft-uet.md +148 -154
- package/docs/integrations/mixpanel-analytics.md +155 -160
- package/docs/integrations/one-dollar-stats.md +166 -165
- package/docs/integrations/openai-pixel.md +204 -301
- package/docs/integrations/overview.md +137 -80
- package/docs/integrations/pinterest-tag.md +191 -183
- package/docs/integrations/pirsch.md +169 -159
- package/docs/integrations/plausible-analytics.md +172 -158
- package/docs/integrations/posthog.md +226 -241
- package/docs/integrations/promptwatch.md +154 -154
- package/docs/integrations/reddit-pixel.md +185 -157
- package/docs/integrations/rudderstack.md +201 -186
- package/docs/integrations/rybbit-analytics.md +171 -160
- package/docs/integrations/segment.md +182 -154
- package/docs/integrations/snapchat-pixel.md +186 -156
- package/docs/integrations/tiktok-pixel.md +171 -150
- package/docs/integrations/umami-analytics.md +163 -158
- package/docs/integrations/vercel-analytics.md +166 -157
- package/docs/integrations/x-pixel.md +176 -150
- package/docs/integrations/youtube.md +121 -86
- package/docs/upgrade-v3.md +475 -467
- package/package.json +15 -9
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/frameworks/react/components/consent-manager-provider.md +0 -95
- package/docs/frameworks/react/script-loader.md +0 -69
- package/docs/frameworks/react/styling/overview.md +0 -266
- package/docs/guides/deployment-modes.md +0 -75
- package/docs/guides/shared-consent-controls.md +0 -158
- package/docs/integrations/clear-on-revocation.md +0 -167
- package/docs/integrations/granular-consent.md +0 -210
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c15t/react",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.4",
|
|
4
4
|
"description": "React cookie banner, consent manager, preference center, and headless CMP components with IAB TCF and Consent Mode support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ccpa",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"dist",
|
|
47
47
|
"dist-types",
|
|
48
48
|
"AGENTS.md",
|
|
49
|
+
"SKILL.md",
|
|
49
50
|
"docs",
|
|
50
51
|
"styles.css",
|
|
51
52
|
"styles.tw3.css",
|
|
@@ -150,6 +151,11 @@
|
|
|
150
151
|
"./styles.tw3.css": "./dist/styles.tw3.css",
|
|
151
152
|
"./iab/styles.css": "./dist/iab/styles.css",
|
|
152
153
|
"./iab/styles.tw3.css": "./dist/iab/styles.tw3.css",
|
|
154
|
+
"./postcss-tailwind3": {
|
|
155
|
+
"types": "./dist-types/postcss-tailwind3.d.ts",
|
|
156
|
+
"import": "./dist/postcss-tailwind3.js",
|
|
157
|
+
"default": "./dist/postcss-tailwind3.js"
|
|
158
|
+
},
|
|
153
159
|
"./primitives": {
|
|
154
160
|
"types": "./dist-types/primitives.d.ts",
|
|
155
161
|
"import": "./dist/primitives.js",
|
|
@@ -243,20 +249,20 @@
|
|
|
243
249
|
"test:watch": "bun prebuild && vitest"
|
|
244
250
|
},
|
|
245
251
|
"dependencies": {
|
|
246
|
-
"@c15t/core": "3.0.0-alpha.
|
|
247
|
-
"@c15t/dev-tools": "3.0.0-alpha.
|
|
248
|
-
"@c15t/iab": "3.0.0-alpha.
|
|
249
|
-
"@c15t/schema": "3.0.0-alpha.
|
|
250
|
-
"@c15t/translations": "3.0.0-alpha.
|
|
251
|
-
"@c15t/ui": "3.0.0-alpha.
|
|
252
|
+
"@c15t/core": "3.0.0-alpha.4",
|
|
253
|
+
"@c15t/dev-tools": "3.0.0-alpha.4",
|
|
254
|
+
"@c15t/iab": "3.0.0-alpha.4",
|
|
255
|
+
"@c15t/schema": "3.0.0-alpha.3",
|
|
256
|
+
"@c15t/translations": "3.0.0-alpha.4",
|
|
257
|
+
"@c15t/ui": "3.0.0-alpha.4",
|
|
252
258
|
"@types/google.maps": "3.65.3"
|
|
253
259
|
},
|
|
254
260
|
"devDependencies": {
|
|
255
|
-
"@c15t/backend": "3.0.0-alpha.
|
|
261
|
+
"@c15t/backend": "3.0.0-alpha.4",
|
|
256
262
|
"@c15t/conformance": "0.0.1",
|
|
257
263
|
"@c15t/typescript-config": "0.0.1",
|
|
258
264
|
"@c15t/vitest-config": "1.0.0",
|
|
259
|
-
"@iabtechlabtcf/core": "^1.5.
|
|
265
|
+
"@iabtechlabtcf/core": "^1.5.22",
|
|
260
266
|
"genversion": "3.2.0",
|
|
261
267
|
"msw": "^2.14.6",
|
|
262
268
|
"typescript": "7.0.2"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: ConsentProvider
|
|
3
|
-
description: Configure the v3 consent runtime and share its state with child components.
|
|
4
|
-
group: frameworks
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Mount one provider
|
|
8
|
-
|
|
9
|
-
```tsx
|
|
10
|
-
import type { ReactNode } from 'react';
|
|
11
|
-
import { ConsentProvider, ConsentBanner, ConsentDialog, ConsentDialogLink, hosted } from 'c15t/react';
|
|
12
|
-
|
|
13
|
-
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
14
|
-
|
|
15
|
-
export function Consent({ children }: { children: ReactNode }) {
|
|
16
|
-
return (
|
|
17
|
-
<ConsentProvider options={{ mode }}>
|
|
18
|
-
{children}
|
|
19
|
-
<ConsentBanner />
|
|
20
|
-
<ConsentDialog />
|
|
21
|
-
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
22
|
-
</ConsentProvider>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Replace the URL with your Inth project endpoint. Import the adapter stylesheet
|
|
28
|
-
once at the app root. In Next.js this component needs a client boundary; prefer
|
|
29
|
-
the framework's `ConsentRoot` when passing server-resolved state.
|
|
30
|
-
|
|
31
|
-
## Provider responsibilities
|
|
32
|
-
|
|
33
|
-
The provider owns initialization, persistence, configured script loading and
|
|
34
|
-
subscriptions. Keep it mounted across client navigation. Its initial mode and
|
|
35
|
-
prefetch configuration belong to the runtime's creation, not a per-render
|
|
36
|
-
mechanism for switching visitors or backends.
|
|
37
|
-
|
|
38
|
-
| Option | Purpose |
|
|
39
|
-
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
40
|
-
| `mode` | Hosted, offline or custom transport factory |
|
|
41
|
-
| `scripts` | Consent-managed script configurations |
|
|
42
|
-
| `callbacks` | Choice, permission and error events |
|
|
43
|
-
| `theme`, `components` | Consent-action styles, theme slots and component slot attributes. Tokens render through `ConsentTheme` |
|
|
44
|
-
| `presentation` | Prompt and preferences layout behavior |
|
|
45
|
-
| `preloadDialog` | When the deferred `ConsentDialog` starts loading: `'idle'` (default) or `'intent'`; see [ConsentDialog](./consent-dialog.md#behavior) |
|
|
46
|
-
| `i18n` | Languages and message overrides |
|
|
47
|
-
| `storageConfig` | Browser record storage configuration |
|
|
48
|
-
| `enabled` | Set false only when intentionally bypassing consent enforcement |
|
|
49
|
-
| `reloadOnConsentRevoked` | Reload the page after the visitor turns off a granted category or vendor; defaults to `true` |
|
|
50
|
-
|
|
51
|
-
`enabled: false` grants categories and allows gated loading while suppressing
|
|
52
|
-
consent UI. It is not a way to fix failed initialization or hide a banner in
|
|
53
|
-
production.
|
|
54
|
-
|
|
55
|
-
## Observe changes without inventing choices
|
|
56
|
-
|
|
57
|
-
`onChoiceRecorded` reports explicit accept, reject and save actions.
|
|
58
|
-
`onPermissionsChanged` also covers changes caused by policy, expiry or privacy
|
|
59
|
-
signals. Hydration and notice dismissal do not become explicit choices.
|
|
60
|
-
|
|
61
|
-
An externally owned runtime can be passed through `runtime`. Its owner must
|
|
62
|
-
start and dispose it. A provider borrowing that runtime must not initialize or
|
|
63
|
-
dispose a second copy. Passing a different `runtime` moves the provider and its
|
|
64
|
-
hooks to the new runtime's kernel and unsubscribes them from the previous one.
|
|
65
|
-
The previous runtime keeps running until its owner disposes it. Switch the
|
|
66
|
-
provider to another runtime, or unmount it, before disposing the runtime it
|
|
67
|
-
renders. Changing between a borrowed runtime and a provider-created one still
|
|
68
|
-
requires remounting the provider. IAB actions taken before its handle is ready
|
|
69
|
-
wait for that handle. If the provider unmounts or switches runtimes first, a
|
|
70
|
-
pending `save()` rejects with an `AbortError` instead of waiting indefinitely.
|
|
71
|
-
See [consent state](../../../guides/consent-state.md) and
|
|
72
|
-
[deployment modes](../../../guides/deployment-modes.md).
|
|
73
|
-
|
|
74
|
-
## Reload after revocation
|
|
75
|
-
|
|
76
|
-
Removing a script cannot stop code that already ran. A vendor's listeners,
|
|
77
|
-
timers and widgets keep working until the page unloads. When an accept, reject
|
|
78
|
-
or save turns off a category or vendor that was granted, the provider reloads
|
|
79
|
-
the page once the save request settles, so the next page runs only permitted
|
|
80
|
-
code. `onBeforeConsentRevocationReload` runs just before the reload. With a
|
|
81
|
-
[`consentSource`](../../../guides/shared-consent-controls.md), any withdrawal the
|
|
82
|
-
external CMP reports reloads the same way, including expiry.
|
|
83
|
-
|
|
84
|
-
Otherwise, expiry, policy changes and privacy signals do not reload the page. Set
|
|
85
|
-
`reloadOnConsentRevoked: false` only when every gated vendor stops itself on
|
|
86
|
-
revocation, for example through its own opt-out API.
|
|
87
|
-
|
|
88
|
-
## Clear data when consent is denied
|
|
89
|
-
|
|
90
|
-
Set `options.clearOnRevocation` to declare cookies, localStorage keys, and
|
|
91
|
-
sessionStorage keys by optional consent category. Cleanup waits for policy
|
|
92
|
-
resolution, then clears denied categories and later allowed-to-denied
|
|
93
|
-
transitions. This option is initial-only. See
|
|
94
|
-
[clear on revocation](../../../integrations/clear-on-revocation.md) for examples,
|
|
95
|
-
cookie scopes, and browser limits.
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Load scripts with consent
|
|
3
|
-
description: Register vendor scripts once and let effective permissions control loading.
|
|
4
|
-
group: frameworks
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Register scripts on the provider
|
|
8
|
-
|
|
9
|
-
Install `@c15t/scripts` for vendor helpers. This React-compatible client component
|
|
10
|
-
uses Inth as the backend. Set the URL to the endpoint supplied by your Inth
|
|
11
|
-
project and keep the component mounted around your application.
|
|
12
|
-
|
|
13
|
-
```tsx title="components/consent.tsx"
|
|
14
|
-
'use client';
|
|
15
|
-
|
|
16
|
-
import type { ReactNode } from 'react';
|
|
17
|
-
import { ConsentProvider, ConsentBanner, ConsentDialog, ConsentDialogLink, hosted } from 'c15t/react';
|
|
18
|
-
import { metaPixel } from '@c15t/scripts/meta-pixel';
|
|
19
|
-
|
|
20
|
-
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
21
|
-
const scripts = [metaPixel({ pixelId: '123456789012345' })];
|
|
22
|
-
|
|
23
|
-
export function Consent({ children }: { children: ReactNode }) {
|
|
24
|
-
return (
|
|
25
|
-
<ConsentProvider options={{ mode, scripts }}>
|
|
26
|
-
{children}
|
|
27
|
-
<ConsentBanner />
|
|
28
|
-
<ConsentDialog />
|
|
29
|
-
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
30
|
-
</ConsentProvider>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Import your adapter's stylesheet globally, as in the framework quickstart. For
|
|
36
|
-
an existing server-resolved `ConsentRoot`, keep that root and pass
|
|
37
|
-
`scripts` as a top-level prop instead of mounting a second provider.
|
|
38
|
-
|
|
39
|
-
## Understand loading and revocation
|
|
40
|
-
|
|
41
|
-
Ordinary scripts wait for their category's effective permission. Give each
|
|
42
|
-
script a stable unique `id` and remove any other loader for the same vendor.
|
|
43
|
-
Some helpers use `alwaysLoad` to load the SDK and signal consent through its own
|
|
44
|
-
API. Read the vendor guide; a category field alone does not guarantee no
|
|
45
|
-
requests.
|
|
46
|
-
|
|
47
|
-
Removing a script element cannot undo JavaScript that already executed or
|
|
48
|
-
requests already sent. Use the vendor's supported consent and cleanup behavior,
|
|
49
|
-
and stop future event calls after revocation. Test both initial denial and a
|
|
50
|
-
change from allowed to denied.
|
|
51
|
-
|
|
52
|
-
Use [custom integrations](../../integrations/building-integrations.md) for an
|
|
53
|
-
unlisted vendor and [verification](../../guides/verify-consent.md) for the network
|
|
54
|
-
checks. Google helpers have a separate
|
|
55
|
-
[Consent Mode contract](../../integrations/google-tag-manager.md).
|
|
56
|
-
|
|
57
|
-
## Clear stored tracking data
|
|
58
|
-
|
|
59
|
-
Script gating does not remove cookies or Web Storage entries that a script
|
|
60
|
-
already wrote. Add `clearOnRevocation` to `ConsentProvider.options` to remove
|
|
61
|
-
declared data when its category is denied. See
|
|
62
|
-
[clear on revocation](../../integrations/clear-on-revocation.md) for configuration
|
|
63
|
-
and browser limits.
|
|
64
|
-
|
|
65
|
-
## Shared lifecycle controls
|
|
66
|
-
|
|
67
|
-
See [shared consent controls](../../guides/shared-consent-controls.md) for external CMPs,
|
|
68
|
-
preference delegation, withdrawal reloads, and application events. These controls
|
|
69
|
-
use the same core runtime across frameworks.
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Styling
|
|
3
|
-
description: Import the React stylesheet and theme c15t components with tokens,
|
|
4
|
-
slots, and class names on ConsentProvider.
|
|
5
|
-
group: frameworks
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Stylesheet
|
|
9
|
-
|
|
10
|
-
Import the stylesheet once, next to your global CSS, in the entry module that
|
|
11
|
-
renders `ConsentProvider`:
|
|
12
|
-
|
|
13
|
-
```tsx
|
|
14
|
-
import 'c15t/react/styles.css';
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Every rule lives in `@layer components`, so unlayered utilities from Tailwind
|
|
18
|
-
v4 and atomic classes from StyleX override it without specificity tricks.
|
|
19
|
-
Tailwind v3 treats `@layer components` as its own directive, so import the
|
|
20
|
-
Tailwind 3 build from your Tailwind entry instead, between the `components`
|
|
21
|
-
and `utilities` directives:
|
|
22
|
-
|
|
23
|
-
```css
|
|
24
|
-
@tailwind base;
|
|
25
|
-
@tailwind components;
|
|
26
|
-
@import 'c15t/react/styles.tw3.css';
|
|
27
|
-
@tailwind utilities;
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Tokens
|
|
31
|
-
|
|
32
|
-
Colors, radii, shadows, typography, and motion come from `--c15t-*` custom
|
|
33
|
-
properties. The package stylesheet sets the default values. To change them,
|
|
34
|
-
render `ConsentTheme` with your theme where your app renders on the server,
|
|
35
|
-
or override the variables directly in your CSS.
|
|
36
|
-
|
|
37
|
-
`ConsentTheme` renders a `<style id="c15t-theme">` element with the
|
|
38
|
-
variables for `theme`. It is not a client component: rendered from a Server
|
|
39
|
-
Component or another server-only file, the theme generator stays out of the
|
|
40
|
-
browser bundle. Rendered from a client component it still works, but the
|
|
41
|
-
browser downloads the generator (about 1.7 KB gzip). The provider no longer
|
|
42
|
-
turns `theme` tokens into CSS. It still reads `consentActions` and slot
|
|
43
|
-
styles from its `theme` option, and warns in development when `theme` holds
|
|
44
|
-
tokens but the page has no `c15t-theme` stylesheet.
|
|
45
|
-
|
|
46
|
-
| `ConsentTheme` prop | Purpose |
|
|
47
|
-
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
48
|
-
| `theme` | Colors, `dark` colors, typography, spacing, radius, shadows and motion. Defaults to the built-in theme. |
|
|
49
|
-
| `colorScheme` | `'dark'` makes the dark tokens the default before hydration. `'system'` follows `prefers-color-scheme` with a CSS media query. Omit it to follow a `dark` or `c15t-dark` class on `<html>`. |
|
|
50
|
-
| `nonce` | Content Security Policy nonce for the `<style>` element. |
|
|
51
|
-
|
|
52
|
-
Pass the same `colorScheme` to `ConsentTheme` and to the provider. The
|
|
53
|
-
provider keeps the `c15t-dark` class on `<html>` in sync after hydration.
|
|
54
|
-
If your app manages dark mode through a root class, such as next-themes'
|
|
55
|
-
`dark` class, omit `colorScheme` and include that class in the server
|
|
56
|
-
HTML.
|
|
57
|
-
|
|
58
|
-
To switch between light and dark at runtime, render `ConsentTheme` without
|
|
59
|
-
`colorScheme` and toggle the `dark` class on `<html>`: its output already
|
|
60
|
-
holds the variables for both schemes. To switch between different token
|
|
61
|
-
sets, render `ConsentTheme` from a client component and change its props,
|
|
62
|
-
which ships the generator.
|
|
63
|
-
|
|
64
|
-
Outside React, call `generateThemeCSS(theme, colorScheme)` from
|
|
65
|
-
`@c15t/ui/theme` on the server or at build time and put the result in a
|
|
66
|
-
`<style>` element or your stylesheet. It escapes `<`, so the result is safe
|
|
67
|
-
inside `<style>`.
|
|
68
|
-
|
|
69
|
-
```ts title="src/consent-theme.ts"
|
|
70
|
-
import { defineTheme } from 'c15t/react';
|
|
71
|
-
|
|
72
|
-
export const theme = defineTheme({
|
|
73
|
-
colors: { primary: '#2f6f4e' },
|
|
74
|
-
radius: { lg: '4px' },
|
|
75
|
-
consentActions: {
|
|
76
|
-
primary: { variant: 'primary', mode: 'filled' },
|
|
77
|
-
dismiss: { variant: 'neutral', mode: 'stroke' },
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
With server rendering, render `ConsentTheme` in the server-only part of your
|
|
83
|
-
document, next to the provider. In a single-page app with no server render,
|
|
84
|
-
either render it next to the provider, which ships the generator, or write the
|
|
85
|
-
variables into your stylesheet. This partial example keeps the provider's
|
|
86
|
-
`mode`, children and other options:
|
|
87
|
-
|
|
88
|
-
```tsx
|
|
89
|
-
import { ConsentProvider, ConsentTheme } from 'c15t/react';
|
|
90
|
-
|
|
91
|
-
import { theme } from './consent-theme';
|
|
92
|
-
|
|
93
|
-
<>
|
|
94
|
-
<ConsentTheme theme={theme} />
|
|
95
|
-
<ConsentProvider options={{ mode, theme }}>{children}</ConsentProvider>
|
|
96
|
-
</>;
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
The provider's `theme` option only supplies `consentActions` and slot styles.
|
|
100
|
-
|
|
101
|
-
Earlier v3 alphas generated theme CSS in the browser from the provider's
|
|
102
|
-
`theme` option. To migrate:
|
|
103
|
-
|
|
104
|
-
1. Move the theme into a module without `'use client'`, so server and
|
|
105
|
-
client files can both import it.
|
|
106
|
-
2. Render `<ConsentTheme theme={theme} />` next to the consent root, from a
|
|
107
|
-
Server Component or another server-rendered file. Pass `colorScheme` and
|
|
108
|
-
`nonce` if you set them on the provider.
|
|
109
|
-
3. Keep passing `theme` to the provider only for `consentActions` and slot
|
|
110
|
-
styles. A theme with tokens only can be removed from the provider.
|
|
111
|
-
4. Keep the package stylesheet import. It carries the default tokens the
|
|
112
|
-
provider used to inject.
|
|
113
|
-
|
|
114
|
-
`consentActions` decides how each action role looks: `default` applies to
|
|
115
|
-
every button, `primary` to whichever actions the policy or your props mark
|
|
116
|
-
primary, and `accept`, `reject`, `customize`, and `dismiss` to one role each.
|
|
117
|
-
Per-action keys win over `primary`, which wins over `default`.
|
|
118
|
-
|
|
119
|
-
Banner sizing has its own variables. Override them in CSS when a variant
|
|
120
|
-
needs a different footprint:
|
|
121
|
-
|
|
122
|
-
| Variable | Default | Applies to |
|
|
123
|
-
| ----------------------------------- | ------- | ---------------- |
|
|
124
|
-
| `--consent-banner-max-width` | `440px` | `floating` cards |
|
|
125
|
-
| `--consent-banner-widget-max-width` | `20rem` | `widget` chips |
|
|
126
|
-
| `--consent-banner-wall-max-width` | `30rem` | `wall` cards |
|
|
127
|
-
|
|
128
|
-
## Colors by consent model
|
|
129
|
-
|
|
130
|
-
The primary action can change while the brand color stays the same. Set
|
|
131
|
-
`consentActions.primary` once, then select `primaryButton` per policy as
|
|
132
|
-
shown in [ConsentBanner](../components/consent-banner.md#per-policy-buttons).
|
|
133
|
-
|
|
134
|
-
To give opt-in and opt-out banners different colors, scope the tokens to
|
|
135
|
-
the root's attributes. Include hover and foreground colors when overriding
|
|
136
|
-
CSS tokens directly:
|
|
137
|
-
|
|
138
|
-
```css
|
|
139
|
-
[data-prompt][data-model='opt-in'] {
|
|
140
|
-
--c15t-primary: #2f6f4e;
|
|
141
|
-
--c15t-primary-hover: #24563c;
|
|
142
|
-
--c15t-text-on-primary: #fff;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
[data-prompt][data-model='opt-out'] {
|
|
146
|
-
--c15t-primary: #6b3fa0;
|
|
147
|
-
--c15t-primary-hover: #55327f;
|
|
148
|
-
--c15t-text-on-primary: #fff;
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
These colors apply to the action marked primary. Button layout and color
|
|
153
|
-
changes do not change the policy or expire a saved choice.
|
|
154
|
-
|
|
155
|
-
## Slots
|
|
156
|
-
|
|
157
|
-
Each component part is a slot. A slot accepts any attributes the element
|
|
158
|
-
takes, so the contract is the same whether you write class strings or pass an
|
|
159
|
-
object with `className` and `style`. Set slots on the provider under
|
|
160
|
-
`components`, keyed by component and part.
|
|
161
|
-
|
|
162
|
-
For a full-width notice, use the supported `bar` variant. Inside your existing
|
|
163
|
-
provider, replace the stock banner with:
|
|
164
|
-
|
|
165
|
-
```tsx title="src/regional-banner.tsx"
|
|
166
|
-
import { ConsentBanner, usePolicyRule } from 'c15t/react';
|
|
167
|
-
|
|
168
|
-
export function RegionalBanner() {
|
|
169
|
-
const policy = usePolicyRule();
|
|
170
|
-
return <ConsentBanner variant={policy?.prompt === 'notice' ? 'bar' : 'floating'} />;
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
To remove the notice card's radius, add these values to the existing
|
|
175
|
-
`options.components.banner` slots. The root owns `data-prompt`, so the card
|
|
176
|
-
uses Tailwind's `group` selector to read it:
|
|
177
|
-
|
|
178
|
-
```ts
|
|
179
|
-
const bannerSlots = {
|
|
180
|
-
root: { className: 'group' },
|
|
181
|
-
card: { className: 'group-data-[prompt=notice]:rounded-none' },
|
|
182
|
-
rightLink: {
|
|
183
|
-
className: 'underline-offset-4 data-[right=opt-out]:text-red-700',
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
// In the existing options.components object:
|
|
188
|
-
// banner: bannerSlots
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
The root also carries `data-variant`, so you can restyle one shape without
|
|
192
|
-
touching the others. Tailwind, giving a `bar` a brand-colored top edge and
|
|
193
|
-
tighter text:
|
|
194
|
-
|
|
195
|
-
```tsx
|
|
196
|
-
<ConsentProvider
|
|
197
|
-
options={{
|
|
198
|
-
mode,
|
|
199
|
-
presentation: { prompt: { variant: 'bar' } },
|
|
200
|
-
components: {
|
|
201
|
-
banner: {
|
|
202
|
-
root: { className: 'group' },
|
|
203
|
-
card: {
|
|
204
|
-
className:
|
|
205
|
-
'group-data-[variant=bar]:border-t-4 group-data-[variant=bar]:border-t-emerald-600',
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
description: {
|
|
209
|
-
banner: { className: 'group-data-[variant=bar]:text-xs' },
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
}}
|
|
213
|
-
/>
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
`data-variant` sits on the root, so child slots use Tailwind's `group`
|
|
217
|
-
prefix to read it.
|
|
218
|
-
|
|
219
|
-
StyleX, spreading the result of `stylex.props()` into a slot:
|
|
220
|
-
|
|
221
|
-
```tsx
|
|
222
|
-
import * as stylex from '@stylexjs/stylex';
|
|
223
|
-
|
|
224
|
-
const styles = stylex.create({
|
|
225
|
-
card: { borderRadius: 0, boxShadow: 'none' },
|
|
226
|
-
rightLink: { textUnderlineOffset: 4, color: 'rgb(185 28 28)' },
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
<ConsentProvider
|
|
230
|
-
options={{
|
|
231
|
-
mode,
|
|
232
|
-
components: {
|
|
233
|
-
banner: {
|
|
234
|
-
card: stylex.props(styles.card),
|
|
235
|
-
rightLink: stylex.props(styles.rightLink),
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
}}
|
|
239
|
-
/>;
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
Set `noStyle` on a component to drop the built-in classes from every part and
|
|
243
|
-
keep only what your slots pass. Set `noStyle` in the provider options to do it
|
|
244
|
-
for every component.
|
|
245
|
-
|
|
246
|
-
Banner slot keys under `components.banner`:
|
|
247
|
-
|
|
248
|
-
| Key | Element |
|
|
249
|
-
| ------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
250
|
-
| `root` | Fixed-position wrapper carrying `data-prompt`, `data-model`, `data-variant`, `data-position`, and `data-blocking` |
|
|
251
|
-
| `cardShell` | Sizes the card and holds the branding tag |
|
|
252
|
-
| `card` | The visible card, carrying `data-state` |
|
|
253
|
-
| `header` | Title and description container |
|
|
254
|
-
| `title` | Heading |
|
|
255
|
-
| `footer` | Action area |
|
|
256
|
-
| `actions` | Group of action groups |
|
|
257
|
-
| `actionGroup` | One group of equally prominent actions |
|
|
258
|
-
| `rights` | Group of right links, rendered before the actions |
|
|
259
|
-
| `rightLink` | One right link, carrying `data-action="right"` and `data-right` |
|
|
260
|
-
| `overlay` | Backdrop shown when the banner blocks the page |
|
|
261
|
-
|
|
262
|
-
Action buttons carry `data-action` and `data-variant`, and right links carry
|
|
263
|
-
`data-action="right"`, so a single rule such as `[data-action='dismiss']` or
|
|
264
|
-
`[data-action='right']` styles one role across every surface. Right links are
|
|
265
|
-
underlined text by default, so the only button on a notice is the primary
|
|
266
|
-
action.
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Choose a deployment mode
|
|
3
|
-
description: Choose who runs your consent backend, then select manifest, init or
|
|
4
|
-
offline resolution for your deployment.
|
|
5
|
-
group: guides
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Use Inth for managed policy and records
|
|
9
|
-
|
|
10
|
-
Start with [Inth](https://inth.com) unless you need to operate the consent
|
|
11
|
-
service yourself or deliberately need only local browser records. Configure
|
|
12
|
-
policy rules and trusted origins in the project, then use its exact backend
|
|
13
|
-
endpoint in your framework setup.
|
|
14
|
-
|
|
15
|
-
| Backend ownership | Policy source | Record storage | Use when |
|
|
16
|
-
| ------------------------- | ------------------------------------------------------ | ---------------------------------------- | ------------------------------------------------------------------------- |
|
|
17
|
-
| Inth hosted service | Centrally managed policy through a manifest or `/init` | Browser records plus backend submissions | You want managed policy and consent records |
|
|
18
|
-
| Self-hosted c15t | Your backend's manifest or `/init` | Browser records plus your database | You need to operate the service and its infrastructure |
|
|
19
|
-
| Browser-only offline mode | Bundled `policyRules` | Browser persistence | Local development and tests. Not recommended for production environments. |
|
|
20
|
-
|
|
21
|
-
Hosted and self-hosted c15t use the same transport protocol. Switching who runs
|
|
22
|
-
the backend does not require switching from manifests to `/init`.
|
|
23
|
-
|
|
24
|
-
## Choose data fetching separately
|
|
25
|
-
|
|
26
|
-
For Next.js deployments with a runtime server, use the
|
|
27
|
-
[manifest setup](https://c15t.com/docs/frameworks/next/data-fetching). It reuses public policy data
|
|
28
|
-
in your application while consent writes still go to Inth. Regular backend
|
|
29
|
-
`/init` is available when you want backend-owned request resolution or a simpler
|
|
30
|
-
browser setup. See [data fetching and transports](./data-fetching.md) for
|
|
31
|
-
the comparison, including custom transports and offline mode.
|
|
32
|
-
|
|
33
|
-
Manifest resolution removes the per-visitor `/init` request, and with it the
|
|
34
|
-
backend's only count of visitors. The server adapters replace it with a session
|
|
35
|
-
report: after each resolution, on a server-rendered page or the same-origin
|
|
36
|
-
init route, the host posts a small report to the backend's `POST /sessions`,
|
|
37
|
-
server-to-server and detached from the response. The browser makes no request
|
|
38
|
-
and the report stores no identity; the visitor's IP and user agent travel as
|
|
39
|
-
forwarded headers under the backend's usual IP handling. Each report is one
|
|
40
|
-
resolution; a page view can produce a `render` and a `route` report, and the
|
|
41
|
-
consuming side groups them into sessions by address and user agent within a
|
|
42
|
-
window. Static output resolves in the browser and sends none. Set `reportSessions: false` on an adapter to turn
|
|
43
|
-
it off.
|
|
44
|
-
|
|
45
|
-
## Match initialization to your application output
|
|
46
|
-
|
|
47
|
-
| Application output | Initial state | Required setup |
|
|
48
|
-
| ------------------ | ------------------------- | ----------------------------------------------------------- |
|
|
49
|
-
| Request SSR | Prepared for this visitor | Adapter request helper and matching client configuration |
|
|
50
|
-
| Static HTML or SPA | Resolved in the browser | Reachable external URLs or deliberately bundled local rules |
|
|
51
|
-
|
|
52
|
-
Request SSR can include the visitor's prompt in the initial HTML. Pass the
|
|
53
|
-
prepared records and policy resolution through to hydration. Do not convert
|
|
54
|
-
effective permissions into new stored choices.
|
|
55
|
-
|
|
56
|
-
Static HTML is shared across visitors. It cannot contain a choice resolved from
|
|
57
|
-
each visitor's cookies or geography at build time. A static site can still use
|
|
58
|
-
Inth through browser requests. A same-origin `/api/c15t` URL only works if a
|
|
59
|
-
service actually serves it; a Next.js static export does not run API routes.
|
|
60
|
-
|
|
61
|
-
A manifest contains reusable public policy data. A resolved init response and
|
|
62
|
-
personalized consent HTML belong to a request. Do not give them the same shared
|
|
63
|
-
cache treatment.
|
|
64
|
-
|
|
65
|
-
## Handle initialization and storage failures
|
|
66
|
-
|
|
67
|
-
While no policy resolves, optional permissions stay denied and the stock
|
|
68
|
-
consent UI stays hidden. No banner can mean pending or failed initialization.
|
|
69
|
-
It does not mean permission to load analytics. Observe errors before changing
|
|
70
|
-
presentation, and do not silently switch to offline policy after a hosted
|
|
71
|
-
request fails.
|
|
72
|
-
|
|
73
|
-
Browser storage can also be unavailable. A working in-memory interaction does
|
|
74
|
-
not prove the choice survives reload. Use
|
|
75
|
-
[verification](./verify-consent.md) to test the actual deployment.
|