@c15t/react 3.0.0-alpha.8 → 3.0.0
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 +10 -12
- package/README.md +41 -70
- package/SKILL.md +1 -1
- package/dist/aggregate-components.js +1 -1
- package/dist/components/consent-gate/atoms.js +1 -1
- package/dist/components/consent-gate/frame.js +2 -0
- package/dist/components/consent-gate/index.js +1 -1
- package/dist/components/iab-panel/atoms/root.js +1 -1
- package/dist/components/iab-panel/iab-panel.js +1 -1
- package/dist/components/iab-prompt/atoms/root.js +1 -1
- package/dist/components/iab-prompt/iab-prompt.js +1 -1
- package/dist/components/panel/atoms/root.js +1 -1
- package/dist/components/panel-trigger/atoms/root.js +1 -1
- package/dist/components/panel-trigger/panel-trigger.js +1 -1
- package/dist/components/panel-trigger/toolbar-loader.js +2 -0
- package/dist/components/preferences/atoms/root.js +1 -1
- package/dist/components/prompt/atoms/early-tap-script.js +2 -0
- package/dist/components/prompt/atoms/root.js +1 -1
- package/dist/components/prompt/prompt.js +1 -1
- package/dist/components/shared/dialog-sheets.js +1 -0
- package/dist/components/shared/first-paint-sheets.js +1 -0
- package/dist/components/shared/iab-dialog-sheets.js +1 -0
- package/dist/components/shared/iab-first-paint-sheets.js +1 -0
- package/dist/components/shared/primitives/button.js +1 -1
- package/dist/components/shared/surface-styles.js +2 -0
- package/dist/consent-gate.js +1 -1
- package/dist/context/index.js +1 -1
- package/dist/devtools.js +1 -1
- package/dist/hooks/use-iab-policy-guard.js +1 -0
- package/dist/iab/styles.tw3.css +2 -2
- package/dist/iab-context.js +1 -1
- package/dist/iab-dialog-deferred.js +2 -0
- package/dist/iab.js +1 -1
- package/dist/index-parts/consent-gate.js +1 -1
- package/dist/index-parts/core.js +1 -1
- package/dist/index-parts/frame.js +1 -0
- package/dist/index-parts/hosted.js +1 -0
- package/dist/index-parts/offline.js +1 -0
- package/dist/index-parts/presets.js +1 -0
- package/dist/index.js +1 -1
- package/dist/modes.js +1 -0
- package/dist/panel-link.js +1 -1
- package/dist/panel-trigger.js +1 -1
- package/dist/provider.js +1 -1
- package/dist/styles.tw3.css +2 -2
- package/dist/transports/hosted.js +1 -0
- package/dist/transports/manifest.js +1 -0
- package/dist/utils/deferred-module.js +1 -1
- package/dist/version.js +1 -1
- package/dist-types/chunk-warming.d.ts +7 -6
- package/dist-types/components/consent-gate/frame.d.ts +19 -0
- package/dist-types/components/consent-gate/index.d.ts +3 -19
- package/dist-types/components/iab-prompt/iab-prompt.d.ts +1 -1
- package/dist-types/components/panel/index.d.ts +1 -1
- package/dist-types/components/panel-trigger/toolbar-loader.d.ts +34 -0
- package/dist-types/components/preferences/index.d.ts +1 -1
- package/dist-types/components/prompt/atoms/early-tap-script.d.ts +17 -0
- package/dist-types/components/prompt/index.d.ts +1 -1
- package/dist-types/components/shared/dialog-sheets.d.ts +9 -0
- package/dist-types/components/shared/first-paint-sheets.d.ts +8 -0
- package/dist-types/components/shared/iab-dialog-sheets.d.ts +3 -0
- package/dist-types/components/shared/iab-first-paint-sheets.d.ts +3 -0
- package/dist-types/components/shared/surface-styles.d.ts +60 -0
- package/dist-types/consent-gate.d.ts +1 -1
- package/dist-types/context/index.d.ts +3 -3
- package/dist-types/context.d.ts +2 -0
- package/dist-types/gpp.d.ts +1 -1
- package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
- package/dist-types/iab-dialog-deferred.d.ts +36 -0
- package/dist-types/iab.d.ts +3 -2
- package/dist-types/index-parts/consent-gate.d.ts +1 -1
- package/dist-types/index-parts/core.d.ts +1 -2
- package/dist-types/index-parts/frame.d.ts +7 -0
- package/dist-types/index-parts/hosted.d.ts +7 -0
- package/dist-types/index-parts/offline.d.ts +7 -0
- package/dist-types/index-parts/presets.d.ts +7 -0
- package/dist-types/index.d.ts +5 -1
- package/dist-types/modes.d.ts +26 -0
- package/dist-types/panel-link.d.ts +1 -1
- package/dist-types/panel-trigger.d.ts +1 -1
- package/dist-types/provider.d.ts +22 -4
- package/dist-types/transports/hosted.d.ts +36 -0
- package/dist-types/transports/manifest.d.ts +48 -0
- package/dist-types/ui-config-context.d.ts +4 -0
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +10 -12
- package/docs/concepts/choose-your-setup.md +45 -8
- package/docs/concepts/consent-categories.md +1 -1
- package/docs/concepts/consent-state.md +5 -2
- package/docs/concepts/data-fetching.md +100 -40
- package/docs/concepts/modes.md +281 -0
- package/docs/customization/dark-mode.md +1 -1
- package/docs/customization/motion.md +2 -2
- package/docs/customization/overview.md +3 -2
- package/docs/customization/recipes.md +4 -4
- package/docs/customization/slots.md +25 -25
- package/docs/customization/stylesheets.md +161 -50
- package/docs/customization/tailwind.md +71 -50
- package/docs/customization/tokens.md +42 -13
- package/docs/frameworks/react/components/consent-banner.md +14 -12
- package/docs/frameworks/react/components/consent-dialog.md +15 -13
- package/docs/frameworks/react/components/consent-provider.md +51 -46
- package/docs/frameworks/react/components.md +16 -13
- package/docs/frameworks/react/compose.md +3 -3
- package/docs/frameworks/react/content-security-policy.md +35 -12
- package/docs/frameworks/react/customize.md +21 -13
- package/docs/frameworks/react/hooks.md +2 -2
- package/docs/frameworks/react/iab.md +56 -6
- package/docs/frameworks/react/quickstart.md +65 -99
- package/docs/frameworks/react/rendering.md +170 -94
- package/docs/frameworks/react/scripts.md +19 -30
- package/docs/frameworks/react/troubleshooting.md +100 -32
- package/docs/frameworks/react/upgrade-v3.md +133 -79
- package/docs/frameworks/react/vendor-consent.md +19 -7
- package/docs/guides/banner-experiments.md +21 -8
- package/docs/guides/troubleshooting.md +90 -26
- package/docs/guides/verify-consent.md +23 -8
- package/docs/integrations/adobe-analytics.md +60 -64
- package/docs/integrations/ahrefs-analytics.md +58 -63
- package/docs/integrations/amplitude.md +60 -64
- package/docs/integrations/clearbit.md +59 -63
- package/docs/integrations/cloudflare-web-analytics.md +56 -60
- package/docs/integrations/cloudflare-zaraz.md +55 -57
- package/docs/integrations/crisp.md +64 -69
- package/docs/integrations/databuddy.md +62 -64
- package/docs/integrations/fathom-analytics.md +56 -60
- package/docs/integrations/front-chat.md +56 -60
- package/docs/integrations/google-maps.md +25 -13
- package/docs/integrations/google-tag-manager.md +153 -77
- package/docs/integrations/google-tag.md +134 -78
- package/docs/integrations/heap.md +56 -60
- package/docs/integrations/hightouch.md +55 -60
- package/docs/integrations/hotjar.md +60 -64
- package/docs/integrations/intercom.md +55 -60
- package/docs/integrations/klaviyo.md +65 -66
- package/docs/integrations/linkedin-insights.md +58 -63
- package/docs/integrations/logrocket.md +55 -60
- package/docs/integrations/matomo-analytics.md +58 -60
- package/docs/integrations/meta-pixel.md +56 -60
- package/docs/integrations/microsoft-clarity.md +57 -60
- package/docs/integrations/microsoft-uet.md +58 -61
- package/docs/integrations/mixpanel-analytics.md +73 -75
- package/docs/integrations/one-dollar-stats.md +53 -59
- package/docs/integrations/openai-pixel.md +58 -60
- package/docs/integrations/overview.md +59 -42
- package/docs/integrations/pinterest-tag.md +56 -60
- package/docs/integrations/pirsch.md +54 -60
- package/docs/integrations/plausible-analytics.md +55 -60
- package/docs/integrations/posthog.md +56 -60
- package/docs/integrations/promptwatch.md +57 -63
- package/docs/integrations/reddit-pixel.md +57 -60
- package/docs/integrations/rudderstack.md +65 -67
- package/docs/integrations/rybbit-analytics.md +70 -75
- package/docs/integrations/segment.md +56 -60
- package/docs/integrations/sentry.md +65 -60
- package/docs/integrations/snapchat-pixel.md +54 -60
- package/docs/integrations/tiktok-pixel.md +59 -63
- package/docs/integrations/umami-analytics.md +54 -60
- package/docs/integrations/vercel-analytics.md +53 -59
- package/docs/integrations/vercel-speed-insights.md +317 -0
- package/docs/integrations/x-pixel.md +57 -63
- package/docs/integrations/youtube.md +25 -13
- package/package.json +18 -8
- package/docs/upgrade-v3.md +0 -429
|
@@ -8,14 +8,14 @@ group: customization
|
|
|
8
8
|
## Where tokens come from
|
|
9
9
|
|
|
10
10
|
c15t's components take their colors from `--c15t-*` CSS variables, and most
|
|
11
|
-
of their fonts, radii, spacing, shadows and motion too. c15t's
|
|
12
|
-
|
|
11
|
+
of their fonts, radii, spacing, shadows and motion too. c15t's rules set the
|
|
12
|
+
defaults. You change them with a theme object or with CSS, and every part
|
|
13
13
|
that reads a token changes with it. Some values are still fixed for one
|
|
14
14
|
component, such as button padding, the radius of the "Secured by" tag and
|
|
15
15
|
several font sizes and weights, so a token change does not move them. Restyle
|
|
16
16
|
those parts through [slots](./slots.md) or your own CSS.
|
|
17
17
|
[Stylesheets and CSS layers](./stylesheets.md)
|
|
18
|
-
covers
|
|
18
|
+
covers how c15t loads its rules, and [dark mode](./dark-mode.md)
|
|
19
19
|
covers the dark set of tokens.
|
|
20
20
|
|
|
21
21
|
## Set semantic values together
|
|
@@ -40,13 +40,13 @@ export const theme = defineTheme({
|
|
|
40
40
|
Install `@c15t/ui` if importing its theme helper directly. Where the theme
|
|
41
41
|
goes depends on the framework:
|
|
42
42
|
|
|
43
|
-
| Framework | Tokens | `consentActions`
|
|
44
|
-
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
-
| Next.js, TanStack Start, React | `<ConsentTheme theme={theme} />`, rendered on the server where the app has one | `theme` in the provider options
|
|
46
|
-
| Nuxt, Vue | `theme` or `tokens` in the module or plugin options | Not available
|
|
47
|
-
| Astro | `theme` in the integration options | The same `theme`
|
|
48
|
-
| Svelte, SvelteKit | `generateThemeCSS(theme)` from `@c15t/ui/theme` on the server, in a `<style>` element, or `--c15t-*` variables in your stylesheet | `theme` on `
|
|
49
|
-
| HTML, JavaScript | `ui.theme` | Not available
|
|
43
|
+
| Framework | Tokens | `consentActions` |
|
|
44
|
+
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
45
|
+
| Next.js, TanStack Start, React | `<ConsentTheme theme={theme} />`, rendered on the server where the app has one | `theme` in the provider options |
|
|
46
|
+
| Nuxt, Vue | `theme` or `tokens` in the module or plugin options | Not available |
|
|
47
|
+
| Astro | `theme` in the integration options | The same `theme` |
|
|
48
|
+
| Svelte, SvelteKit | `generateThemeCSS(theme)` from `@c15t/ui/theme` on the server, in a `<style>` element, or `--c15t-*` variables in your stylesheet | `theme` on `ConsentProvider` (Svelte) or `ConsentRoot` (SvelteKit) |
|
|
49
|
+
| HTML, JavaScript | `ui.theme` | Not available |
|
|
50
50
|
|
|
51
51
|
React and Svelte providers do not turn tokens in their `theme` option into
|
|
52
52
|
CSS, and warn in development when a theme holds tokens but the page has no
|
|
@@ -59,9 +59,9 @@ setup.
|
|
|
59
59
|
## Combine a generated theme with your own CSS
|
|
60
60
|
|
|
61
61
|
`generateThemeCSS` writes its variables on `:root:root` and
|
|
62
|
-
`.c15t-theme-root.c15t-theme-root`,
|
|
63
|
-
|
|
64
|
-
`<style>` element comes before or after
|
|
62
|
+
`.c15t-theme-root.c15t-theme-root`, more specific than c15t's defaults. The
|
|
63
|
+
theme therefore overrides the defaults whether its
|
|
64
|
+
`<style>` element comes before or after c15t's rules. The same output backs
|
|
65
65
|
`ConsentTheme` in React, Next.js and TanStack Start, Astro's `theme` option and
|
|
66
66
|
the script tag's `ui.theme`.
|
|
67
67
|
|
|
@@ -169,6 +169,35 @@ them, on any screen size.
|
|
|
169
169
|
Test long translations and small screens after changing width or typography.
|
|
170
170
|
A compact banner must still fit the required actions.
|
|
171
171
|
|
|
172
|
+
## Stack the banner with your own layers
|
|
173
|
+
|
|
174
|
+
The banner and its overlay sit at the top of the page's stacking order by
|
|
175
|
+
default. Lower them when a navbar, drawer, or chat widget should cover the
|
|
176
|
+
banner.
|
|
177
|
+
|
|
178
|
+
| Variable | Default | Target |
|
|
179
|
+
| -------------------------------------- | -------- | ----------------------------- |
|
|
180
|
+
| `--consent-banner-z-index` | `999998` | Banner |
|
|
181
|
+
| `--consent-banner-overlay-z-index` | `999997` | Backdrop of a blocking banner |
|
|
182
|
+
| `--iab-consent-banner-z-index` | `999998` | IAB TCF banner |
|
|
183
|
+
| `--iab-consent-banner-overlay-z-index` | `999997` | IAB TCF banner backdrop |
|
|
184
|
+
| `--consent-dialog-z-index` | `999999` | Preferences dialog |
|
|
185
|
+
| `--consent-dialog-overlay-z-index` | `999998` | Preferences dialog backdrop |
|
|
186
|
+
|
|
187
|
+
```css
|
|
188
|
+
:root {
|
|
189
|
+
--consent-banner-z-index: 40;
|
|
190
|
+
--consent-banner-overlay-z-index: 39;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Keep each z-index above its overlay's, or the backdrop covers the card it
|
|
195
|
+
belongs to. Keep the dialog above the banner so Customize opens on top.
|
|
196
|
+
|
|
197
|
+
Only the card and the "Secured by" tag take clicks. Clicks on the space
|
|
198
|
+
around a floating card, or beside the tag on a bar, reach the page. A
|
|
199
|
+
blocking banner catches every click.
|
|
200
|
+
|
|
172
201
|
## Restyle the "Secured by" tag
|
|
173
202
|
|
|
174
203
|
The tag sits on the edge of the banner and dialog cards and uses the primary
|
|
@@ -12,28 +12,30 @@ The [quickstart](../quickstart.md) mounts both in
|
|
|
12
12
|
`src/consent.tsx`:
|
|
13
13
|
|
|
14
14
|
```tsx title="src/consent.tsx"
|
|
15
|
-
import {
|
|
15
|
+
import { posthog } from '@c15t/integrations/posthog';
|
|
16
16
|
import {
|
|
17
17
|
ConsentBanner,
|
|
18
18
|
ConsentDialog,
|
|
19
19
|
ConsentDialogLink,
|
|
20
20
|
ConsentProvider,
|
|
21
|
+
hosted,
|
|
21
22
|
} from 'c15t/react';
|
|
22
23
|
import type { ReactNode } from 'react';
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
const options = {
|
|
26
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
27
|
+
mode: hosted(),
|
|
28
|
+
scripts: [
|
|
29
|
+
posthog({
|
|
30
|
+
id: 'phc_your_project_key',
|
|
31
|
+
initOptions: { cookieless_mode: 'never' },
|
|
32
|
+
loadMode: 'after-consent',
|
|
33
|
+
}),
|
|
34
|
+
],
|
|
35
|
+
};
|
|
34
36
|
|
|
35
37
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
36
|
-
<ConsentProvider options={
|
|
38
|
+
<ConsentProvider options={options}>
|
|
37
39
|
{children}
|
|
38
40
|
<ConsentBanner />
|
|
39
41
|
<ConsentDialog />
|
|
@@ -14,28 +14,30 @@ group: frameworks
|
|
|
14
14
|
code.
|
|
15
15
|
|
|
16
16
|
```tsx title="src/consent.tsx"
|
|
17
|
-
import {
|
|
17
|
+
import { posthog } from '@c15t/integrations/posthog';
|
|
18
18
|
import {
|
|
19
19
|
ConsentBanner,
|
|
20
20
|
ConsentDialog,
|
|
21
21
|
ConsentDialogLink,
|
|
22
22
|
ConsentProvider,
|
|
23
|
+
hosted,
|
|
23
24
|
} from 'c15t/react';
|
|
24
25
|
import type { ReactNode } from 'react';
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
const options = {
|
|
28
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
29
|
+
mode: hosted(),
|
|
30
|
+
scripts: [
|
|
31
|
+
posthog({
|
|
32
|
+
id: 'phc_your_project_key',
|
|
33
|
+
initOptions: { cookieless_mode: 'never' },
|
|
34
|
+
loadMode: 'after-consent',
|
|
35
|
+
}),
|
|
36
|
+
],
|
|
37
|
+
};
|
|
36
38
|
|
|
37
39
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
38
|
-
<ConsentProvider options={
|
|
40
|
+
<ConsentProvider options={options}>
|
|
39
41
|
{children}
|
|
40
42
|
<ConsentBanner />
|
|
41
43
|
<ConsentDialog />
|
|
@@ -135,7 +137,7 @@ If a preload fails, for example because the visitor is offline, nothing is
|
|
|
135
137
|
cached: the next hover, focus or open tries the download again.
|
|
136
138
|
|
|
137
139
|
The dialog's CSS travels in the same chunk and is applied before the dialog
|
|
138
|
-
renders, so
|
|
140
|
+
renders, so the first page load carries only the banner's rules.
|
|
139
141
|
|
|
140
142
|
Without an `open` prop, Escape closes the dialog without saving. If the
|
|
141
143
|
policy still owes a choice, the banner comes back. Save Settings, Accept All and
|
|
@@ -14,28 +14,30 @@ The [quickstart](../quickstart.md) does this in
|
|
|
14
14
|
`src/consent.tsx`:
|
|
15
15
|
|
|
16
16
|
```tsx title="src/consent.tsx"
|
|
17
|
-
import {
|
|
17
|
+
import { posthog } from '@c15t/integrations/posthog';
|
|
18
18
|
import {
|
|
19
19
|
ConsentBanner,
|
|
20
20
|
ConsentDialog,
|
|
21
21
|
ConsentDialogLink,
|
|
22
22
|
ConsentProvider,
|
|
23
|
+
hosted,
|
|
23
24
|
} from 'c15t/react';
|
|
24
25
|
import type { ReactNode } from 'react';
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
const options = {
|
|
28
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
29
|
+
mode: hosted(),
|
|
30
|
+
scripts: [
|
|
31
|
+
posthog({
|
|
32
|
+
id: 'phc_your_project_key',
|
|
33
|
+
initOptions: { cookieless_mode: 'never' },
|
|
34
|
+
loadMode: 'after-consent',
|
|
35
|
+
}),
|
|
36
|
+
],
|
|
37
|
+
};
|
|
36
38
|
|
|
37
39
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
38
|
-
<ConsentProvider options={
|
|
40
|
+
<ConsentProvider options={options}>
|
|
39
41
|
{children}
|
|
40
42
|
<ConsentBanner />
|
|
41
43
|
<ConsentDialog />
|
|
@@ -46,11 +48,14 @@ export const Consent = ({ children }: { children: ReactNode }) => (
|
|
|
46
48
|
);
|
|
47
49
|
```
|
|
48
50
|
|
|
49
|
-
`
|
|
50
|
-
|
|
51
|
-
the
|
|
52
|
-
`
|
|
53
|
-
|
|
51
|
+
`hosted()` from `c15t/react` asks the backend's `/init` for the visitor's
|
|
52
|
+
policy on each page load, and sends consent choices to the same backend. It
|
|
53
|
+
uses the backend URL `consentManifest()` read from `VITE_C15T_BACKEND_URL` or
|
|
54
|
+
`VITE_INTH_PROJECT_URL`. Set one to the backend URL from your Inth project. To
|
|
55
|
+
resolve a bundled policy in the browser instead, pass `manifest()` from
|
|
56
|
+
`c15t/react`; see
|
|
57
|
+
[rendering](../rendering.md#bundle-the-policy-at-build-time).
|
|
58
|
+
The Next.js and TanStack Start adapters export `ConsentRoot` instead, which wraps
|
|
54
59
|
this provider and passes it server-resolved state.
|
|
55
60
|
|
|
56
61
|
## Provider options
|
|
@@ -63,35 +68,35 @@ the provider to change them. `scripts`, `vendors`, `networkBlocker`,
|
|
|
63
68
|
`iframeBlocker`, `consentCategories`, `overrides`, `user`, `callbacks` and
|
|
64
69
|
`enabled` apply when they change.
|
|
65
70
|
|
|
66
|
-
| Option | Purpose
|
|
67
|
-
| ----------------------------- |
|
|
68
|
-
| `mode` | Required. `hosted(
|
|
69
|
-
| `prefetch` | Server-resolved state, or a promise of it, from a framework adapter's server helper
|
|
70
|
-
| `scripts` | Consent-gated vendor scripts. See [scripts and embeds](../scripts.md)
|
|
71
|
-
| `vendors` | Vendors listed under their category with their own switch. See [vendor consent](../vendor-consent.md)
|
|
72
|
-
| `scriptLoader` | Options for the script loader module
|
|
73
|
-
| `networkBlocker` | Rules that hold `fetch` and `XMLHttpRequest` calls until their category is allowed, or `false`
|
|
74
|
-
| `iframeBlocker` | Gates DOM iframes that carry `data-category`. On by default; `false` turns it off
|
|
75
|
-
| `persistence` | Stores the visitor's choice in a cookie and localStorage. On by default
|
|
76
|
-
| `storageConfig` | Storage key and cookie settings for the stored choice
|
|
77
|
-
| `clearOnRevocation` | Cookies and storage keys to delete when a category is denied
|
|
78
|
-
| `reloadOnConsentRevoked` | Reload the page after the visitor turns off a granted category or vendor. Defaults to `true`
|
|
79
|
-
| `consentCategories` | Categories the preference dialog offers alongside those your scripts use, within the policy's scope
|
|
80
|
-
| `overrides` | Force the country, region or language the policy is resolved for, for testing
|
|
81
|
-
| `user` | Link consent records to a signed-in user
|
|
82
|
-
| `callbacks` | Choice, permission and error events
|
|
83
|
-
| `i18n` | Languages and message overrides
|
|
84
|
-
| `legalLinks` | Privacy policy and other links shown in the banner and dialog
|
|
85
|
-
| `theme` | `consentActions` and slot styles. Tokens go through `ConsentTheme`; see [customize](../customize.md)
|
|
86
|
-
| `components` | Slot attributes per component part
|
|
87
|
-
| `presentation` | Banner and dialog shape, position and blocking
|
|
88
|
-
| `experiment` | A/B test of `presentation`, read once at mount. See [banner experiments](../../../guides/banner-experiments.md)
|
|
89
|
-
| `journey` | Random id that links each `/init` to the save that follows. See [session reports](../../../concepts/data-fetching.md#link-an-init-to-the-save-that-follows)
|
|
90
|
-
| `colorScheme` | `'light'`, `'dark'`, `'system'`, or `null` to leave the `c15t-dark` class alone
|
|
91
|
-
| `noStyle`, `disableAnimation` | Drop the built-in styles, or turn off animations
|
|
92
|
-
| `preloadDialog` | When the deferred `ConsentDialog` starts loading: `'idle'` (default) or `'intent'`; see [ConsentDialog](./consent-dialog.md#behavior)
|
|
93
|
-
| `nonce` | Content Security Policy nonce for script elements c15t inserts
|
|
94
|
-
| `enabled` | Set `false` only when you deliberately bypass consent enforcement
|
|
71
|
+
| Option | Purpose |
|
|
72
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
73
|
+
| `mode` | Required. `hosted()` for the backend's `/init`, `manifest()` for a bundled policy, `offline()` for local policies, all from `c15t/react`, or `custom()` for your own transport. See [consent modes](../../../concepts/modes.md) |
|
|
74
|
+
| `prefetch` | Server-resolved state, or a promise of it, from a framework adapter's server helper |
|
|
75
|
+
| `scripts` | Consent-gated vendor scripts. See [scripts and embeds](../scripts.md) |
|
|
76
|
+
| `vendors` | Vendors listed under their category with their own switch. See [vendor consent](../vendor-consent.md) |
|
|
77
|
+
| `scriptLoader` | Options for the script loader module |
|
|
78
|
+
| `networkBlocker` | Rules that hold `fetch` and `XMLHttpRequest` calls until their category is allowed, or `false` |
|
|
79
|
+
| `iframeBlocker` | Gates DOM iframes that carry `data-category`. On by default; `false` turns it off |
|
|
80
|
+
| `persistence` | Stores the visitor's choice in a cookie and localStorage. On by default |
|
|
81
|
+
| `storageConfig` | Storage key and cookie settings for the stored choice |
|
|
82
|
+
| `clearOnRevocation` | Cookies and storage keys to delete when a category is denied |
|
|
83
|
+
| `reloadOnConsentRevoked` | Reload the page after the visitor turns off a granted category or vendor. Defaults to `true` |
|
|
84
|
+
| `consentCategories` | Categories the preference dialog offers alongside those your scripts use, within the policy's scope |
|
|
85
|
+
| `overrides` | Force the country, region or language the policy is resolved for, for testing |
|
|
86
|
+
| `user` | Link consent records to a signed-in user |
|
|
87
|
+
| `callbacks` | Choice, permission and error events |
|
|
88
|
+
| `i18n` | Languages and message overrides |
|
|
89
|
+
| `legalLinks` | Privacy policy and other links shown in the banner and dialog |
|
|
90
|
+
| `theme` | `consentActions` and slot styles. Tokens go through `ConsentTheme`; see [customize](../customize.md) |
|
|
91
|
+
| `components` | Slot attributes per component part |
|
|
92
|
+
| `presentation` | Banner and dialog shape, position and blocking |
|
|
93
|
+
| `experiment` | A/B test of `presentation`, read once at mount. See [banner experiments](../../../guides/banner-experiments.md) |
|
|
94
|
+
| `journey` | Random id that links each `/init` to the save that follows. See [session reports](../../../concepts/data-fetching.md#link-an-init-to-the-save-that-follows) |
|
|
95
|
+
| `colorScheme` | `'light'`, `'dark'`, `'system'`, or `null` to leave the `c15t-dark` class alone |
|
|
96
|
+
| `noStyle`, `disableAnimation` | Drop the built-in styles, or turn off animations |
|
|
97
|
+
| `preloadDialog` | When the deferred `ConsentDialog` starts loading: `'idle'` (default) or `'intent'`; see [ConsentDialog](./consent-dialog.md#behavior) |
|
|
98
|
+
| `nonce` | Content Security Policy nonce for script elements c15t inserts |
|
|
99
|
+
| `enabled` | Set `false` only when you deliberately bypass consent enforcement |
|
|
95
100
|
|
|
96
101
|
`enabled: false` grants categories and allows gated loading while suppressing
|
|
97
102
|
consent UI. It is not a way to fix failed initialization or hide a banner in
|
|
@@ -36,28 +36,30 @@ Most apps start with four components. `ConsentProvider` holds the runtime,
|
|
|
36
36
|
one file:
|
|
37
37
|
|
|
38
38
|
```tsx title="src/consent.tsx"
|
|
39
|
-
import {
|
|
39
|
+
import { posthog } from '@c15t/integrations/posthog';
|
|
40
40
|
import {
|
|
41
41
|
ConsentBanner,
|
|
42
42
|
ConsentDialog,
|
|
43
43
|
ConsentDialogLink,
|
|
44
44
|
ConsentProvider,
|
|
45
|
+
hosted,
|
|
45
46
|
} from 'c15t/react';
|
|
46
47
|
import type { ReactNode } from 'react';
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
const options = {
|
|
50
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
51
|
+
mode: hosted(),
|
|
52
|
+
scripts: [
|
|
53
|
+
posthog({
|
|
54
|
+
id: 'phc_your_project_key',
|
|
55
|
+
initOptions: { cookieless_mode: 'never' },
|
|
56
|
+
loadMode: 'after-consent',
|
|
57
|
+
}),
|
|
58
|
+
],
|
|
59
|
+
};
|
|
58
60
|
|
|
59
61
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
60
|
-
<ConsentProvider options={
|
|
62
|
+
<ConsentProvider options={options}>
|
|
61
63
|
{children}
|
|
62
64
|
<ConsentBanner />
|
|
63
65
|
<ConsentDialog />
|
|
@@ -84,7 +86,8 @@ explains the trade-off.
|
|
|
84
86
|
|
|
85
87
|
Import `IABProvider`, `IABConsentBanner` and `IABConsentDialog` from
|
|
86
88
|
`c15t/react/iab`, render them inside `ConsentProvider` next to
|
|
87
|
-
`ConsentBanner` and `ConsentDialog`, and load `c15t/react/
|
|
89
|
+
`ConsentBanner` and `ConsentDialog`, and load `c15t/react/styles.css` and
|
|
90
|
+
`c15t/react/iab/styles.css` with `styles: false`. The stock banner and dialog stay closed
|
|
88
91
|
under an IAB policy. See
|
|
89
92
|
[IAB TCF](./iab.md).
|
|
90
93
|
|
|
@@ -315,9 +315,9 @@ banner keeps them as long as you keep the parts that own them:
|
|
|
315
315
|
|
|
316
316
|
## Keep theme tokens and slots working
|
|
317
317
|
|
|
318
|
-
The parts render the stock class names,
|
|
319
|
-
|
|
320
|
-
|
|
318
|
+
The parts render the stock class names, and the banner's `Root` renders
|
|
319
|
+
c15t's rules, so c15t's styles and `--c15t-*` tokens style a composed
|
|
320
|
+
banner the way they style the stock one.
|
|
321
321
|
|
|
322
322
|
Slots in the provider's `options.components` reach each part by key:
|
|
323
323
|
`banner.root`, `banner.card`, `banner.header`, `banner.title`,
|
|
@@ -10,13 +10,16 @@ group: frameworks
|
|
|
10
10
|
|
|
11
11
|
A React app with c15t adds these to the page, and your policy must allow them:
|
|
12
12
|
|
|
13
|
-
| What
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
| `<
|
|
18
|
-
|
|
|
19
|
-
|
|
|
13
|
+
| What | Directive |
|
|
14
|
+
| --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
|
|
15
|
+
| The `<style>` elements the banner, dialog and other stock components render with c15t's rules | `style-src` with a nonce |
|
|
16
|
+
| `c15t/react/styles.css`, only if you import it with `styles: false` | `style-src 'self'` |
|
|
17
|
+
| The `<style id="c15t-theme">` element, if you render `ConsentTheme` | `style-src` with a nonce or its hash |
|
|
18
|
+
| `<script>` elements the script loader creates for `scripts` entries, both `src` and inline | `script-src` with each vendor's host, or a nonce |
|
|
19
|
+
| The inline `<script>` that `consentManifest()` adds to `index.html` to send `/init` early | `script-src` with a nonce or its hash |
|
|
20
|
+
| With server rendering, the inline `<script>` before the banner's buttons that holds a tap made before hydration | `script-src` with a nonce or its hash |
|
|
21
|
+
| Browser requests to your backend's `/init` and `/subjects` | `connect-src` with the backend origin |
|
|
22
|
+
| Iframes inside `ConsentGate`, and the frames, images and requests your vendors load | `frame-src`, `img-src`, `connect-src` for each vendor |
|
|
20
23
|
|
|
21
24
|
In a client-rendered app, c15t components set their inline styles through
|
|
22
25
|
React. A policy does not restrict styles set that way, so they need no
|
|
@@ -24,8 +27,10 @@ directive.
|
|
|
24
27
|
|
|
25
28
|
## Allow the consent backend
|
|
26
29
|
|
|
27
|
-
With `hosted(
|
|
28
|
-
and `POST {url}/subjects` when the visitor accepts, rejects or saves.
|
|
30
|
+
With `hosted()`, the browser calls `GET {url}/init` on every page load
|
|
31
|
+
and `POST {url}/subjects` when the visitor accepts, rejects or saves. With
|
|
32
|
+
`manifest()`, it calls `POST {url}/subjects`, and `GET {url}/init` only when
|
|
33
|
+
the policy needs a location the browser does not know. Add the
|
|
29
34
|
backend's origin to `connect-src`:
|
|
30
35
|
|
|
31
36
|
```txt title="Content-Security-Policy (partial)"
|
|
@@ -60,13 +65,15 @@ when a server renders or rewrites your `index.html` per request.
|
|
|
60
65
|
|
|
61
66
|
Pass the nonce as `options.nonce` on `ConsentProvider`. The script loader
|
|
62
67
|
stamps it on every `<script>` it creates. A `nonce` on a single `scripts`
|
|
63
|
-
entry takes precedence for that element.
|
|
68
|
+
entry takes precedence for that element. The stock components put it on the
|
|
69
|
+
`<style>` elements that carry c15t's rules.
|
|
64
70
|
|
|
65
71
|
With Vite, set `html.cspNonce` to a placeholder in `vite.config.ts`, and have
|
|
66
72
|
your server replace it with a new nonce on every response. Vite then adds
|
|
67
73
|
`<meta property="csp-nonce" nonce="...">` to the page, and the browser keeps the
|
|
68
|
-
value in the tag's `nonce` property.
|
|
69
|
-
the
|
|
74
|
+
value in the tag's `nonce` property. Vite also stamps the nonce on the early
|
|
75
|
+
`/init` script. Read it where you create the provider, in the
|
|
76
|
+
quickstart's `src/consent.tsx`:
|
|
70
77
|
|
|
71
78
|
```tsx title="src/consent.tsx (partial)"
|
|
72
79
|
const nonce =
|
|
@@ -83,6 +90,22 @@ The provider reads `options.nonce` once, when it mounts. A server-rendered
|
|
|
83
90
|
React app, such as one built with React Router framework mode, reads the nonce
|
|
84
91
|
from its own request and passes it the same way.
|
|
85
92
|
|
|
93
|
+
On a static host, allow the early `/init` script by the hash in the browser's
|
|
94
|
+
`Refused to execute inline script` error. If the policy blocks it, the app
|
|
95
|
+
sends `/init` itself.
|
|
96
|
+
|
|
97
|
+
## Allow c15t's style elements
|
|
98
|
+
|
|
99
|
+
The banner, dialog and other stock components render c15t's rules as
|
|
100
|
+
`<style>` elements. A `style-src` without `'unsafe-inline'` must admit them.
|
|
101
|
+
Either:
|
|
102
|
+
|
|
103
|
+
* Set `options.nonce` on `ConsentProvider`, as in [use a nonce](#use-a-nonce).
|
|
104
|
+
The elements then render next to each component with the nonce. React 19
|
|
105
|
+
would otherwise move them into `<head>` and drop the nonce.
|
|
106
|
+
* Or set `styles: false` in the provider options and import
|
|
107
|
+
`c15t/react/styles.css` from your bundle. `style-src 'self'` admits it.
|
|
108
|
+
|
|
86
109
|
## Allow the theme style element
|
|
87
110
|
|
|
88
111
|
`ConsentTheme` renders your theme tokens into a `<style id="c15t-theme">`
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Customize
|
|
3
3
|
description: Change the colors, fonts, layout, button styles and copy of the
|
|
4
|
-
c15t banner and dialog in a React app with
|
|
5
|
-
|
|
4
|
+
c15t banner and dialog in a React app with theme tokens, provider options and
|
|
5
|
+
slots, and load the stylesheet yourself when you need to.
|
|
6
6
|
group: frameworks
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -24,26 +24,35 @@ across frameworks.
|
|
|
24
24
|
See the [design gallery](../../customization/recipes.md) for five banner designs,
|
|
25
25
|
from a bottom bar to a fully custom one, with tested code for this framework.
|
|
26
26
|
|
|
27
|
-
## Import the stylesheet
|
|
27
|
+
## Import the stylesheet yourself
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
A React app imports no c15t stylesheet. `ConsentBanner`, `ConsentDialog` and
|
|
30
|
+
the other stock components render the rules they use as `<style>` elements.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Import the stylesheet yourself with Tailwind CSS 3, to put c15t's rules in a
|
|
33
|
+
named cascade layer. Set `styles: false` in the provider
|
|
34
|
+
options, so the components add no second copy, and import the stylesheet once
|
|
35
|
+
in the module that renders `ConsentProvider`:
|
|
36
|
+
|
|
37
|
+
```tsx title="src/consent.tsx (partial)"
|
|
33
38
|
import 'c15t/react/styles.css';
|
|
39
|
+
|
|
40
|
+
// In the ConsentProvider options:
|
|
41
|
+
styles: false,
|
|
34
42
|
```
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
`@
|
|
39
|
-
|
|
44
|
+
To import the stylesheet from CSS instead, put it at the top of your global
|
|
45
|
+
stylesheet, above any `@tailwind` directives. `postcss-import`, which Vite
|
|
46
|
+
uses, ignores an `@import` that follows other rules. Tailwind 3 also needs a
|
|
47
|
+
PostCSS plugin;
|
|
40
48
|
[Tailwind CSS](../../customization/tailwind.md#set-up-tailwind-css-3) shows the
|
|
41
49
|
setup.
|
|
42
50
|
|
|
43
51
|
## Change colors, fonts and radius
|
|
44
52
|
|
|
45
53
|
Colors, radii, shadows, typography, and motion come from `--c15t-*` custom
|
|
46
|
-
properties. The
|
|
54
|
+
properties. The rules the components render set the default values, as
|
|
55
|
+
does `styles.css` when you import it with `styles: false`. To change them,
|
|
47
56
|
render `ConsentTheme` with your theme where your app renders on the server,
|
|
48
57
|
or override the variables directly in your CSS.
|
|
49
58
|
|
|
@@ -80,8 +89,7 @@ inside `<style>`.
|
|
|
80
89
|
|
|
81
90
|
A single-page app has no server render, so pick one of two ways:
|
|
82
91
|
|
|
83
|
-
* **Set the variables in your CSS.** Nothing extra ships to the browser
|
|
84
|
-
this after `c15t/react/styles.css`:
|
|
92
|
+
* **Set the variables in your CSS.** Nothing extra ships to the browser:
|
|
85
93
|
|
|
86
94
|
```css title="src/index.css"
|
|
87
95
|
:root {
|
|
@@ -65,6 +65,6 @@ Use focused hooks for feature gates. For a complete custom prompt or preference
|
|
|
65
65
|
center, use `useHeadlessConsentUI()` for surface actions and `useConsentDraft()`
|
|
66
66
|
for staged choices, inside one `ConsentDraftProvider` so the save commits the
|
|
67
67
|
same draft. v3 has no `useConsentManager()`; the
|
|
68
|
-
[
|
|
69
|
-
|
|
68
|
+
[`use-consent-manager-to-hooks` codemod](https://c15t.com/docs/cli/commands/codemods#migrate-useconsentmanager-to-v3-hooks)
|
|
69
|
+
rewrites most of its calls to hooks. Read [how consent works](../../concepts/how-consent-works.md#a-permission-is-not-a-recorded-choice) before
|
|
70
70
|
treating a callback as evidence of a choice.
|