@c15t/react 3.0.0-alpha.8 → 3.0.0-alpha.9
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 +3 -3
- package/dist/components/consent-gate/atoms.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/panel/atoms/root.js +1 -1
- package/dist/components/panel-trigger/atoms/root.js +1 -1
- package/dist/components/preferences/atoms/root.js +1 -1
- 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/surface-styles.js +2 -0
- package/dist/hooks/use-iab-policy-guard.js +1 -0
- package/dist/iab/styles.tw3.css +1 -1
- package/dist/iab-context.js +1 -1
- package/dist/provider.js +1 -1
- package/dist/version.js +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 +36 -0
- package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
- package/dist-types/provider.d.ts +19 -1
- package/dist-types/ui-config-context.d.ts +4 -0
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +3 -3
- package/docs/concepts/choose-your-setup.md +3 -1
- package/docs/concepts/data-fetching.md +3 -1
- package/docs/customization/overview.md +3 -2
- package/docs/customization/stylesheets.md +163 -50
- package/docs/customization/tailwind.md +59 -44
- package/docs/customization/tokens.md +6 -6
- package/docs/frameworks/react/components/consent-banner.md +0 -2
- package/docs/frameworks/react/components/consent-dialog.md +1 -3
- package/docs/frameworks/react/components/consent-provider.md +0 -2
- package/docs/frameworks/react/components.md +2 -3
- package/docs/frameworks/react/compose.md +3 -3
- package/docs/frameworks/react/content-security-policy.md +22 -8
- package/docs/frameworks/react/customize.md +21 -13
- package/docs/frameworks/react/iab.md +36 -4
- package/docs/frameworks/react/quickstart.md +5 -5
- package/docs/frameworks/react/rendering.md +5 -3
- package/docs/frameworks/react/scripts.md +0 -2
- package/docs/frameworks/react/troubleshooting.md +43 -7
- package/docs/frameworks/react/upgrade-v3.md +23 -17
- package/docs/frameworks/react/vendor-consent.md +19 -7
- package/docs/guides/banner-experiments.md +0 -2
- package/docs/guides/troubleshooting.md +9 -9
- package/package.json +6 -6
|
@@ -24,8 +24,6 @@ import type { ReactNode } from 'react';
|
|
|
24
24
|
import { consentManifest } from './c15t-manifest';
|
|
25
25
|
import { scripts } from './scripts';
|
|
26
26
|
|
|
27
|
-
import 'c15t/react/styles.css';
|
|
28
|
-
|
|
29
27
|
const mode = manifest({
|
|
30
28
|
backendURL:
|
|
31
29
|
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
@@ -26,8 +26,6 @@ import type { ReactNode } from 'react';
|
|
|
26
26
|
import { consentManifest } from './c15t-manifest';
|
|
27
27
|
import { scripts } from './scripts';
|
|
28
28
|
|
|
29
|
-
import 'c15t/react/styles.css';
|
|
30
|
-
|
|
31
29
|
const mode = manifest({
|
|
32
30
|
backendURL:
|
|
33
31
|
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
@@ -135,7 +133,7 @@ If a preload fails, for example because the visitor is offline, nothing is
|
|
|
135
133
|
cached: the next hover, focus or open tries the download again.
|
|
136
134
|
|
|
137
135
|
The dialog's CSS travels in the same chunk and is applied before the dialog
|
|
138
|
-
renders, so
|
|
136
|
+
renders, so the first page load carries only the banner's rules.
|
|
139
137
|
|
|
140
138
|
Without an `open` prop, Escape closes the dialog without saving. If the
|
|
141
139
|
policy still owes a choice, the banner comes back. Save Settings, Accept All and
|
|
@@ -26,8 +26,6 @@ import type { ReactNode } from 'react';
|
|
|
26
26
|
import { consentManifest } from './c15t-manifest';
|
|
27
27
|
import { scripts } from './scripts';
|
|
28
28
|
|
|
29
|
-
import 'c15t/react/styles.css';
|
|
30
|
-
|
|
31
29
|
const mode = manifest({
|
|
32
30
|
backendURL:
|
|
33
31
|
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
@@ -48,8 +48,6 @@ import type { ReactNode } from 'react';
|
|
|
48
48
|
import { consentManifest } from './c15t-manifest';
|
|
49
49
|
import { scripts } from './scripts';
|
|
50
50
|
|
|
51
|
-
import 'c15t/react/styles.css';
|
|
52
|
-
|
|
53
51
|
const mode = manifest({
|
|
54
52
|
backendURL:
|
|
55
53
|
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
@@ -84,7 +82,8 @@ explains the trade-off.
|
|
|
84
82
|
|
|
85
83
|
Import `IABProvider`, `IABConsentBanner` and `IABConsentDialog` from
|
|
86
84
|
`c15t/react/iab`, render them inside `ConsentProvider` next to
|
|
87
|
-
`ConsentBanner` and `ConsentDialog`, and load `c15t/react/
|
|
85
|
+
`ConsentBanner` and `ConsentDialog`, and load `c15t/react/styles.css` and
|
|
86
|
+
`c15t/react/iab/styles.css` with `styles: false`. The stock banner and dialog stay closed
|
|
88
87
|
under an IAB policy. See
|
|
89
88
|
[IAB TCF](./iab.md).
|
|
90
89
|
|
|
@@ -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,14 @@ 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
|
+
| Browser requests to your backend's `/init` and `/subjects` | `connect-src` with the backend origin |
|
|
20
|
+
| Iframes inside `ConsentGate`, and the frames, images and requests your vendors load | `frame-src`, `img-src`, `connect-src` for each vendor |
|
|
20
21
|
|
|
21
22
|
In a client-rendered app, c15t components set their inline styles through
|
|
22
23
|
React. A policy does not restrict styles set that way, so they need no
|
|
@@ -60,7 +61,8 @@ when a server renders or rewrites your `index.html` per request.
|
|
|
60
61
|
|
|
61
62
|
Pass the nonce as `options.nonce` on `ConsentProvider`. The script loader
|
|
62
63
|
stamps it on every `<script>` it creates. A `nonce` on a single `scripts`
|
|
63
|
-
entry takes precedence for that element.
|
|
64
|
+
entry takes precedence for that element. The stock components put it on the
|
|
65
|
+
`<style>` elements that carry c15t's rules.
|
|
64
66
|
|
|
65
67
|
With Vite, set `html.cspNonce` to a placeholder in `vite.config.ts`, and have
|
|
66
68
|
your server replace it with a new nonce on every response. Vite then adds
|
|
@@ -83,6 +85,18 @@ The provider reads `options.nonce` once, when it mounts. A server-rendered
|
|
|
83
85
|
React app, such as one built with React Router framework mode, reads the nonce
|
|
84
86
|
from its own request and passes it the same way.
|
|
85
87
|
|
|
88
|
+
## Allow c15t's style elements
|
|
89
|
+
|
|
90
|
+
The banner, dialog and other stock components render c15t's rules as
|
|
91
|
+
`<style>` elements. A `style-src` without `'unsafe-inline'` must admit them.
|
|
92
|
+
Either:
|
|
93
|
+
|
|
94
|
+
* Set `options.nonce` on `ConsentProvider`, as in [use a nonce](#use-a-nonce).
|
|
95
|
+
The elements then render next to each component with the nonce. React 19
|
|
96
|
+
would otherwise move them into `<head>` and drop the nonce.
|
|
97
|
+
* Or set `styles: false` in the provider options and import
|
|
98
|
+
`c15t/react/styles.css` from your bundle. `style-src 'self'` admits it.
|
|
99
|
+
|
|
86
100
|
## Allow the theme style element
|
|
87
101
|
|
|
88
102
|
`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 {
|
|
@@ -21,10 +21,11 @@ Install `@c15t/iab` alongside your framework adapter, then mount the IAB
|
|
|
21
21
|
components inside an existing consent provider connected to Inth.
|
|
22
22
|
|
|
23
23
|
Import the components from `c15t/react/iab` and render them inside your
|
|
24
|
-
existing `ConsentProvider` from `c15t/react`.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
existing `ConsentProvider` from `c15t/react`.
|
|
25
|
+
|
|
26
|
+
The IAB banner and dialog render their own styles by default. Leave the
|
|
27
|
+
provider's `styles` option enabled and render the components without a CSS
|
|
28
|
+
import:
|
|
28
29
|
|
|
29
30
|
```tsx title="src/iab-consent.tsx"
|
|
30
31
|
import {
|
|
@@ -55,6 +56,18 @@ IAB presentation follows `presentation.prompt.blocking` and
|
|
|
55
56
|
scroll locking and a backdrop together. See [migration](../../upgrade-v3.md) for
|
|
56
57
|
legacy option behavior.
|
|
57
58
|
|
|
59
|
+
## Mount IABProvider for every IAB policy
|
|
60
|
+
|
|
61
|
+
IAB is opt-in. The standard `ConsentBanner` and `ConsentDialog` do not
|
|
62
|
+
handle the IAB model, so when a visitor's policy uses it, the backend
|
|
63
|
+
sends its vendor list and the app has no `IABProvider`, they throw an
|
|
64
|
+
`IABUnavailableError` (code `C15T_IAB_UNAVAILABLE`):
|
|
65
|
+
`c15t: this visitor's policy uses IAB TCF, but no <IABProvider> is mounted`.
|
|
66
|
+
The error happens during render, on the server and in the browser, so
|
|
67
|
+
your error boundary or the framework's error overlay shows it. Render `IABProvider` from
|
|
68
|
+
`c15t/react/iab` for those visitors, or remove the `iab` model from the
|
|
69
|
+
policy.
|
|
70
|
+
|
|
58
71
|
## Verify vendor and purpose choices
|
|
59
72
|
|
|
60
73
|
Test category choices alongside vendor, purpose, legitimate-interest and special
|
|
@@ -62,6 +75,25 @@ feature controls used by your integration. Confirm the TC String and `__tcfapi`
|
|
|
62
75
|
reflect the saved state, and verify the vendor's actual requests. A category-only
|
|
63
76
|
banner test does not establish that the IAB flow works.
|
|
64
77
|
|
|
78
|
+
## Load an external stylesheet
|
|
79
|
+
|
|
80
|
+
With Tailwind CSS 3, or when you want to put c15t in a named cascade layer,
|
|
81
|
+
import `c15t/react/styles.css` and then `c15t/react/iab/styles.css` at your
|
|
82
|
+
global stylesheet entry. The IAB stylesheet holds the IAB rules and uses the
|
|
83
|
+
base stylesheet's tokens. Set `styles: false` so the components use those
|
|
84
|
+
stylesheets:
|
|
85
|
+
|
|
86
|
+
```tsx title="src/consent.tsx (partial)"
|
|
87
|
+
import 'c15t/react/styles.css';
|
|
88
|
+
import 'c15t/react/iab/styles.css';
|
|
89
|
+
|
|
90
|
+
// In the ConsentProvider options:
|
|
91
|
+
styles: false,
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Tailwind CSS 3 also needs the
|
|
95
|
+
[PostCSS plugin](../../customization/tailwind.md#set-up-tailwind-css-3).
|
|
96
|
+
|
|
65
97
|
## Restrict how vendors use a purpose
|
|
66
98
|
|
|
67
99
|
Publisher restrictions override a vendor's declared use of one purpose. Pass
|
|
@@ -80,7 +80,9 @@ The snapshot is fixed at build time:
|
|
|
80
80
|
|
|
81
81
|
* Rebuild after changing policies, translations or vendors. If your CI caches
|
|
82
82
|
build output, force a fresh build.
|
|
83
|
-
* The build must reach the backend. A failed fetch
|
|
83
|
+
* The build must reach the backend. A failed fetch stops Next.js, TanStack
|
|
84
|
+
Start, SvelteKit and Vite builds. By default, Astro and Nuxt log a warning
|
|
85
|
+
instead and fetch the policy at runtime.
|
|
84
86
|
* Consent choices still go to the backend.
|
|
85
87
|
|
|
86
88
|
Run `vite build` or `vite dev` before a standalone `tsc`, `vue-tsc` or
|
|
@@ -134,8 +136,6 @@ import type { ReactNode } from 'react';
|
|
|
134
136
|
import { consentManifest } from './c15t-manifest';
|
|
135
137
|
import { scripts } from './scripts';
|
|
136
138
|
|
|
137
|
-
import 'c15t/react/styles.css';
|
|
138
|
-
|
|
139
139
|
const mode = manifest({
|
|
140
140
|
backendURL:
|
|
141
141
|
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
@@ -187,8 +187,8 @@ createRoot(root).render(
|
|
|
187
187
|
|
|
188
188
|
Keep `Consent` mounted for the life of the app. If you use a client-side
|
|
189
189
|
router, render the router inside `Consent` so navigation does not remount the
|
|
190
|
-
provider.
|
|
191
|
-
|
|
190
|
+
provider. There is no stylesheet to import: the banner and dialog render their
|
|
191
|
+
own rules as `<style>` elements.
|
|
192
192
|
|
|
193
193
|
## Gate your own features
|
|
194
194
|
|
|
@@ -76,7 +76,9 @@ The snapshot is fixed at build time:
|
|
|
76
76
|
|
|
77
77
|
* Rebuild after changing policies, translations or vendors. If your CI caches
|
|
78
78
|
build output, force a fresh build.
|
|
79
|
-
* The build must reach the backend. A failed fetch
|
|
79
|
+
* The build must reach the backend. A failed fetch stops Next.js, TanStack
|
|
80
|
+
Start, SvelteKit and Vite builds. By default, Astro and Nuxt log a warning
|
|
81
|
+
instead and fetch the policy at runtime.
|
|
80
82
|
* Consent choices still go to the backend.
|
|
81
83
|
|
|
82
84
|
Run `vite build` or `vite dev` before a standalone `tsc`, `vue-tsc` or
|
|
@@ -125,8 +127,8 @@ browser takes over after hydration:
|
|
|
125
127
|
* The server render and the first browser render agree, so hydration does not
|
|
126
128
|
warn or change a stored choice.
|
|
127
129
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
The Vite setup needs no change. The banner renders in the browser and brings
|
|
131
|
+
its own `<style>` element, so there is no stylesheet to import.
|
|
130
132
|
|
|
131
133
|
### Skip the browser's first init request
|
|
132
134
|
|
|
@@ -40,8 +40,6 @@ import type { ReactNode } from 'react';
|
|
|
40
40
|
import { consentManifest } from './c15t-manifest';
|
|
41
41
|
import { scripts } from './scripts';
|
|
42
42
|
|
|
43
|
-
import 'c15t/react/styles.css';
|
|
44
|
-
|
|
45
43
|
const mode = manifest({
|
|
46
44
|
backendURL:
|
|
47
45
|
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
@@ -44,6 +44,28 @@ A policy with `prompt: 'none'` shows no banner by design, and so does a
|
|
|
44
44
|
returning visitor with a valid stored choice. [Policies](../../concepts/policies.md)
|
|
45
45
|
explains why a region may not show one.
|
|
46
46
|
|
|
47
|
+
## The page throws that no IABProvider is mounted
|
|
48
|
+
|
|
49
|
+
The visitor's policy uses the `iab` model and the backend sent its vendor
|
|
50
|
+
list, but no `IABProvider` is mounted. The standard banner and dialog do
|
|
51
|
+
not handle the IAB model, so they throw rather than leave the visitor
|
|
52
|
+
with no consent UI. Server and browser render the same error.
|
|
53
|
+
|
|
54
|
+
Fix it one of two ways:
|
|
55
|
+
|
|
56
|
+
* If the site uses IAB TCF, render `IABProvider` with `IABConsentBanner`
|
|
57
|
+
and `IABConsentDialog` from `c15t/react/iab` inside your consent
|
|
58
|
+
provider. They can sit next to the standard banner.
|
|
59
|
+
* If it does not, remove the `iab` model from the policy for that region
|
|
60
|
+
in your Inth project or policy pack.
|
|
61
|
+
|
|
62
|
+
A backend that answers `gvl: null` turns IAB off for that request. The
|
|
63
|
+
policy then runs as opt-in and nothing throws.
|
|
64
|
+
|
|
65
|
+
The check passes once `c15t/react/iab` has loaded. If you import the IAB
|
|
66
|
+
components with a dynamic `import()`, a render of the standard banner
|
|
67
|
+
that happens before the import finishes still throws.
|
|
68
|
+
|
|
47
69
|
## Inspect the active policy
|
|
48
70
|
|
|
49
71
|
Render this component inside `ConsentProvider`. It reads state and records no
|
|
@@ -91,13 +113,27 @@ covers the options.
|
|
|
91
113
|
## The banner has no styles
|
|
92
114
|
|
|
93
115
|
**Check.** In DevTools Elements, the banner has classes but no rules apply.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
Look for c15t's `<style>` element: `<style data-href="c15t-first-paint">` in
|
|
117
|
+
`<head>` on React 19, or `<style data-c15t-styles>` next to the banner on
|
|
118
|
+
React 18 or with a `nonce`. Check the console for a Content Security Policy
|
|
119
|
+
error.
|
|
120
|
+
|
|
121
|
+
**Fix.**
|
|
122
|
+
|
|
123
|
+
* No c15t `<style>` element: the provider sets `styles: false` or `noStyle`.
|
|
124
|
+
With `styles: false`, import `c15t/react/styles.css` once in the module
|
|
125
|
+
that renders the provider.
|
|
126
|
+
* The console reports a blocked inline style: set the provider's `nonce`, as
|
|
127
|
+
[Content Security Policy](./content-security-policy.md)
|
|
128
|
+
shows.
|
|
129
|
+
* Under Tailwind 3, buttons lose their padding and cards their borders:
|
|
130
|
+
Tailwind 3's unlayered preflight beats c15t's layered rules. Set
|
|
131
|
+
`styles: false`, import `c15t/react/styles.css` above the `@tailwind`
|
|
132
|
+
directives and add `c15t/postcss-tailwind3` before `tailwindcss` in your
|
|
133
|
+
PostCSS config. Without the plugin, Tailwind 3 drops c15t's rules or fails
|
|
134
|
+
the build with
|
|
135
|
+
`` `@layer components` is used but no matching `@tailwind components` directive is present ``.
|
|
136
|
+
See [Tailwind CSS](../../customization/tailwind.md#set-up-tailwind-css-3).
|
|
101
137
|
|
|
102
138
|
## The console warns that theme tokens are no longer turned into CSS
|
|
103
139
|
|
|
@@ -51,13 +51,13 @@ Remove `@c15t/react` and `@c15t/scripts`, then install `c15t` from the
|
|
|
51
51
|
|
|
52
52
|
Drop `@c15t/integrations@alpha` if you don't use its vendor helpers.
|
|
53
53
|
|
|
54
|
-
| v2 import | v3 import
|
|
55
|
-
| --------------------------------------- |
|
|
56
|
-
| `@c15t/react` | `c15t/react`
|
|
57
|
-
| `@c15t/react/headless` | `c15t/react/headless`
|
|
58
|
-
| `@c15t/react/styles.css` | `c15t/react/styles.css`
|
|
59
|
-
| `DevTools` from `@c15t/dev-tools/react` | `DevTools` from `c15t/react/devtools`
|
|
60
|
-
| `@c15t/scripts/*` | `@c15t/integrations/*`
|
|
54
|
+
| v2 import | v3 import |
|
|
55
|
+
| --------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
56
|
+
| `@c15t/react` | `c15t/react` |
|
|
57
|
+
| `@c15t/react/headless` | `c15t/react/headless` |
|
|
58
|
+
| `@c15t/react/styles.css` | Nothing: remove the import. Keep `c15t/react/styles.css` only with `styles: false` |
|
|
59
|
+
| `DevTools` from `@c15t/dev-tools/react` | `DevTools` from `c15t/react/devtools` |
|
|
60
|
+
| `@c15t/scripts/*` | `@c15t/integrations/*` |
|
|
61
61
|
|
|
62
62
|
`@c15t/react` is still published at v3, so its imports keep working if you pin
|
|
63
63
|
it to `@alpha`. These docs use `c15t/react`.
|
|
@@ -448,16 +448,22 @@ A generated theme uses `:root:root`, so your own `--c15t-*` values on plain
|
|
|
448
448
|
|
|
449
449
|
### Stylesheets
|
|
450
450
|
|
|
451
|
-
*
|
|
452
|
-
`@c15t/
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
*
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
451
|
+
* Remove the c15t stylesheet import, such as `@c15t/react/styles.css` or
|
|
452
|
+
`@c15t/nextjs/styles.css`. The stock components in `c15t/react`,
|
|
453
|
+
`c15t/next` and `c15t/tanstack-start` render the rules they use as
|
|
454
|
+
`<style>` elements, so no stylesheet request holds back the first paint. An
|
|
455
|
+
import you keep still styles the components, but the rules ship twice and
|
|
456
|
+
the stylesheet still delays the first paint.
|
|
457
|
+
* Keep an import of the v3 stylesheet, such as `c15t/react/styles.css`, only
|
|
458
|
+
with Tailwind CSS 3 or a named cascade layer, and set
|
|
459
|
+
`styles: false` in the provider options so the components add no second
|
|
460
|
+
copy. See
|
|
461
|
+
[stylesheets and CSS layers](../../customization/stylesheets.md#import-the-stylesheet-yourself).
|
|
462
|
+
* With manual styles, `iab/styles.css` no longer repeats the default tokens.
|
|
463
|
+
Import it after `styles.css`. Automatic IAB styling needs neither import.
|
|
464
|
+
* Tailwind CSS 3 needs a PostCSS plugin for c15t's `styles.css`. Add
|
|
465
|
+
`'c15t/postcss-tailwind3': {}` before `tailwindcss` in `postcss.config`,
|
|
466
|
+
and set `styles: false`. See [Tailwind CSS 3](../../customization/tailwind.md#set-up-tailwind-css-3).
|
|
461
467
|
Create React App can't run the plugin. The `postcss-tailwind3` codemod adds
|
|
462
468
|
it to an object-form `postcss.config` and warns about configs it can't
|
|
463
469
|
edit.
|
|
@@ -22,6 +22,10 @@ TC string instead; see [IAB TCF](./iab.md).
|
|
|
22
22
|
|
|
23
23
|
## Declare the vendors
|
|
24
24
|
|
|
25
|
+
Built-in `@c15t/integrations` helpers already list their vendor by name, so
|
|
26
|
+
you only declare a vendor for a script of your own, or to replace a helper's
|
|
27
|
+
name and privacy policy.
|
|
28
|
+
|
|
25
29
|
Declare the vendors next to the scripts in `src/scripts.ts`, using the `vendor`
|
|
26
30
|
slug each script already carries:
|
|
27
31
|
|
|
@@ -66,11 +70,19 @@ helper sets `vendor` to its script ID, so `xPixel()` is `x-pixel`, `gtag()`
|
|
|
66
70
|
is `gtag` and `cloudflareZaraz()` is `cloudflare-zaraz`. Each
|
|
67
71
|
[vendor guide](../../integrations/overview.md) names its slug.
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
You don't need to declare a helper's vendor. Each helper also sets
|
|
74
|
+
`vendorDetails` on its script: the vendor's name, privacy policy, homepage
|
|
75
|
+
and legal entity. The dialog lists the vendor with its own switch from
|
|
76
|
+
those. Declare the vendor in `vendors` to replace them, for example to link
|
|
77
|
+
your own data processing notice, or when you self-host a tool such as
|
|
78
|
+
Matomo, Umami, Plausible or PostHog and the vendor's privacy policy doesn't
|
|
79
|
+
cover your install. A declaration replaces `vendorDetails` as a whole and
|
|
80
|
+
doesn't merge with it.
|
|
81
|
+
|
|
82
|
+
Your own scripts can set `vendorDetails` too. A script with a `vendor` slug
|
|
83
|
+
and no `name` and `privacyPolicyUrl` from any source still loads with its
|
|
84
|
+
category, but the dialog has no switch for it. In development, c15t logs a
|
|
85
|
+
console warning that names the slug. Production builds skip the warning.
|
|
74
86
|
|
|
75
87
|
A self-hosted backend can declare vendors too. `/init` returns them and c15t
|
|
76
88
|
merges them with the vendors in code. When both declare the same `id`, the
|
|
@@ -165,8 +177,8 @@ the same as withdrawing a category, so code the vendor already ran stops.
|
|
|
165
177
|
Test the production build in a private window with DevTools Network open and
|
|
166
178
|
filtered to `ads-twitter.com`:
|
|
167
179
|
|
|
168
|
-
1.
|
|
169
|
-
|
|
180
|
+
1. Register `xPixel()`. Open Privacy settings. The marketing row lists X
|
|
181
|
+
Pixel with a switch.
|
|
170
182
|
2. Allow marketing and save. `uwt.js` loads.
|
|
171
183
|
3. Open Privacy settings, switch X Pixel off and save. c15t reloads the
|
|
172
184
|
page. After the reload there is no `uwt.js` request, and other marketing
|
|
@@ -32,8 +32,6 @@ import type { ReactNode } from 'react';
|
|
|
32
32
|
|
|
33
33
|
import { scripts } from './scripts';
|
|
34
34
|
|
|
35
|
-
import 'c15t/react/styles.css';
|
|
36
|
-
|
|
37
35
|
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
38
36
|
|
|
39
37
|
// `control` is the stock banner. `wall` blocks the page until the visitor
|
|
@@ -49,14 +49,14 @@ Mixing v2 and v3 packages is not supported.
|
|
|
49
49
|
|
|
50
50
|
No banner is sometimes correct. Find out which case you have:
|
|
51
51
|
|
|
52
|
-
| What DevTools shows | Cause
|
|
53
|
-
| -------------------------------------------------- |
|
|
54
|
-
| The backend request failed or has a CORS error | Wrong backend URL, or your origin is not trusted
|
|
55
|
-
| Requests go to `your-project.inth.app` and fail | The placeholder backend URL from the guides is still in your code
|
|
56
|
-
| No backend request at all | No provider mounted, or the provider runs in offline mode
|
|
57
|
-
| The policy resolved and no prompt is needed | The visitor's location maps to a policy without a prompt, such as a US state without a privacy law in the recommended rules
|
|
58
|
-
| The policy resolved and a choice is stored | A returning visitor
|
|
59
|
-
| The banner is in the DOM but invisible or unstyled |
|
|
52
|
+
| What DevTools shows | Cause | Fix |
|
|
53
|
+
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| The backend request failed or has a CORS error | Wrong backend URL, or your origin is not trusted | Copy the URL from your Inth project exactly, including any path. Add the site's origin, such as `https://www.example.com` or `http://localhost:3000`, to the project's trusted origins. |
|
|
55
|
+
| Requests go to `your-project.inth.app` and fail | The placeholder backend URL from the guides is still in your code | Replace `https://your-project.inth.app` with the URL from your Inth project, including any path prefix. |
|
|
56
|
+
| No backend request at all | No provider mounted, or the provider runs in offline mode | Check `window.c15t`. Confirm the provider receives `hosted()` with your backend URL, or the `backendURL` option your framework uses. |
|
|
57
|
+
| The policy resolved and no prompt is needed | The visitor's location maps to a policy without a prompt, such as a US state without a privacy law in the recommended rules | Expected. Test from a location that needs a prompt. Server helpers such as Next.js `resolveConsent` accept a `country` override for testing; remove it before you deploy. |
|
|
58
|
+
| The policy resolved and a choice is stored | A returning visitor | Expected. Clear site data or use a private window. |
|
|
59
|
+
| The banner is in the DOM but invisible or unstyled | c15t's rules are missing: `styles: false` without an imported stylesheet, a Content Security Policy that blocks c15t's `<style>` elements, Tailwind CSS 3's preflight, or a SvelteKit app without `c15tHandle` | See [stylesheets and CSS layers](../customization/stylesheets.md) for how your framework loads c15t's rules. |
|
|
60
60
|
|
|
61
61
|
Do not "fix" a missing banner by granting every category or turning c15t off.
|
|
62
62
|
While the policy is unresolved, every optional category stays denied. Turning
|
|
@@ -135,7 +135,7 @@ every optional category stays denied.
|
|
|
135
135
|
|
|
136
136
|
## Why does my theme do nothing?
|
|
137
137
|
|
|
138
|
-
Check that
|
|
138
|
+
Check that c15t's rules load, that you set a token or slot the
|
|
139
139
|
component actually reads, and that the state attribute you target is on the
|
|
140
140
|
element you style. A `data-variant` on the banner root is not on its card.
|
|
141
141
|
Check the Tailwind version and CSS layer order before adding specificity. See
|
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.9",
|
|
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",
|
|
@@ -254,16 +254,16 @@
|
|
|
254
254
|
"test:watch": "bun prebuild && vitest"
|
|
255
255
|
},
|
|
256
256
|
"dependencies": {
|
|
257
|
-
"@c15t/core": "3.0.0-alpha.
|
|
258
|
-
"@c15t/dev-tools": "3.0.0-alpha.
|
|
259
|
-
"@c15t/iab": "3.0.0-alpha.
|
|
257
|
+
"@c15t/core": "3.0.0-alpha.9",
|
|
258
|
+
"@c15t/dev-tools": "3.0.0-alpha.9",
|
|
259
|
+
"@c15t/iab": "3.0.0-alpha.9",
|
|
260
260
|
"@c15t/schema": "3.0.0-alpha.7",
|
|
261
261
|
"@c15t/translations": "3.0.0-alpha.6",
|
|
262
|
-
"@c15t/ui": "3.0.0-alpha.
|
|
262
|
+
"@c15t/ui": "3.0.0-alpha.9",
|
|
263
263
|
"@types/google.maps": "3.65.3"
|
|
264
264
|
},
|
|
265
265
|
"devDependencies": {
|
|
266
|
-
"@c15t/backend": "3.0.0-alpha.
|
|
266
|
+
"@c15t/backend": "3.0.0-alpha.9",
|
|
267
267
|
"@c15t/conformance": "0.0.1",
|
|
268
268
|
"@c15t/typescript-config": "0.0.1",
|
|
269
269
|
"@c15t/vitest-config": "1.0.0",
|