@c15t/react 3.0.0-alpha.7 → 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/primitives/legal-links/index.js +1 -1
- package/dist/components/shared/streamed-surface.js +2 -0
- package/dist/components/shared/surface-styles.js +2 -0
- package/dist/context.js +1 -1
- package/dist/hooks/use-iab-policy-guard.js +1 -0
- package/dist/hooks.js +1 -1
- package/dist/iab/styles.tw3.css +1 -1
- package/dist/iab-context.js +1 -1
- package/dist/kernel-selector.js +1 -1
- package/dist/provider.js +1 -1
- package/dist/version.js +1 -1
- package/dist-types/components/prompt/atoms/root.d.ts +4 -0
- package/dist-types/components/prompt/prompt.d.ts +4 -0
- 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/streamed-surface.d.ts +23 -0
- package/dist-types/components/shared/surface-styles.d.ts +36 -0
- package/dist-types/context.d.ts +17 -1
- package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
- package/dist-types/kernel-selector.d.ts +10 -0
- package/dist-types/provider.d.ts +36 -4
- 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 +4 -2
- 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 +7 -4
- package/docs/frameworks/react/components/consent-dialog.md +8 -5
- package/docs/frameworks/react/components/consent-provider.md +41 -36
- package/docs/frameworks/react/components.md +9 -5
- 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 +84 -85
- package/docs/frameworks/react/rendering.md +24 -12
- package/docs/frameworks/react/scripts.md +7 -4
- package/docs/frameworks/react/troubleshooting.md +70 -19
- package/docs/frameworks/react/upgrade-v3.md +23 -17
- package/docs/frameworks/react/vendor-consent.md +19 -7
- package/docs/guides/banner-experiments.md +2 -4
- package/docs/guides/troubleshooting.md +9 -9
- package/package.json +7 -7
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Tailwind CSS
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
c15t.
|
|
3
|
+
description: Use c15t's styles with Tailwind CSS 4 or 3 in every framework, put
|
|
4
|
+
utilities on c15t component parts, and use Tailwind's dark variant with c15t.
|
|
6
5
|
group: customization
|
|
7
6
|
---
|
|
8
7
|
|
|
@@ -21,7 +20,10 @@ directive and fails the build on a stylesheet that uses it without a matching
|
|
|
21
20
|
`@tailwind components`. c15t's Tailwind 3 PostCSS plugin removes the layer
|
|
22
21
|
wrappers from c15t's stylesheets before Tailwind 3 runs. c15t's rules then
|
|
23
22
|
win by specificity, as they did in c15t v2, so a utility on a c15t part needs
|
|
24
|
-
Tailwind's important modifier, such as `!p-2`.
|
|
23
|
+
Tailwind's important modifier, such as `!p-2`. The plugin cannot reach the
|
|
24
|
+
`<style>` elements c15t renders itself, so on Tailwind 3 you turn those off
|
|
25
|
+
with `styles: false` and import the stylesheet instead. The Astro integration
|
|
26
|
+
does this for you when it finds Tailwind 3.
|
|
25
27
|
|
|
26
28
|
The setups below come from fixtures that CI builds for each framework and
|
|
27
29
|
checks in Chromium. The Next.js snippets come from the Next.js 16 Turbopack
|
|
@@ -34,9 +36,11 @@ without a backend, so they use `offline()` mode or a local `backendURL`. Keep th
|
|
|
34
36
|
|
|
35
37
|
## Set up Tailwind CSS 4
|
|
36
38
|
|
|
37
|
-
Install Tailwind's plugin for your build tool
|
|
38
|
-
|
|
39
|
-
c15t's
|
|
39
|
+
Install Tailwind's plugin for your build tool and add it to the build. c15t
|
|
40
|
+
loads its own styles in every framework, so your CSS entry holds only
|
|
41
|
+
Tailwind. Do not import c15t's stylesheet next to Tailwind 4: the stock
|
|
42
|
+
components already render the same rules, and the import would hold back the
|
|
43
|
+
first paint.
|
|
40
44
|
|
|
41
45
|
**Next.js**
|
|
42
46
|
|
|
@@ -46,20 +50,18 @@ Next.js runs Tailwind 4 through `@tailwindcss/postcss`:
|
|
|
46
50
|
export default { plugins: { '@tailwindcss/postcss': {} } };
|
|
47
51
|
```
|
|
48
52
|
|
|
49
|
-
Import
|
|
50
|
-
|
|
53
|
+
Import Tailwind in the global stylesheet that `app/layout.tsx` or
|
|
54
|
+
`pages/_app.tsx` loads:
|
|
51
55
|
|
|
52
56
|
```css title="app/globals.css"
|
|
53
57
|
@import 'tailwindcss';
|
|
54
|
-
@import 'c15t/next/styles.css';
|
|
55
58
|
|
|
56
59
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
57
60
|
```
|
|
58
61
|
|
|
59
62
|
**TanStack Start**
|
|
60
63
|
|
|
61
|
-
Add `@tailwindcss/vite` before the TanStack Start plugin
|
|
62
|
-
Tailwind and c15t from the stylesheet your root route links:
|
|
64
|
+
Add `@tailwindcss/vite` before the TanStack Start plugin:
|
|
63
65
|
|
|
64
66
|
```ts title="vite.config.ts"
|
|
65
67
|
import tailwindcss from '@tailwindcss/vite';
|
|
@@ -76,11 +78,10 @@ export default defineConfig({
|
|
|
76
78
|
});
|
|
77
79
|
```
|
|
78
80
|
|
|
79
|
-
Import Tailwind
|
|
81
|
+
Import Tailwind from the stylesheet your root route links:
|
|
80
82
|
|
|
81
83
|
```css title="src/styles.css"
|
|
82
84
|
@import 'tailwindcss';
|
|
83
|
-
@import 'c15t/tanstack-start/styles.css';
|
|
84
85
|
|
|
85
86
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
86
87
|
```
|
|
@@ -95,12 +96,10 @@ import { defineConfig } from 'vite';
|
|
|
95
96
|
export default defineConfig({ plugins: [react(), tailwindcss()] });
|
|
96
97
|
```
|
|
97
98
|
|
|
98
|
-
Import this stylesheet from your entry module
|
|
99
|
-
`c15t/react/styles.css` import:
|
|
99
|
+
Import this stylesheet from your entry module:
|
|
100
100
|
|
|
101
101
|
```css title="src/app.css"
|
|
102
102
|
@import 'tailwindcss';
|
|
103
|
-
@import 'c15t/react/styles.css';
|
|
104
103
|
|
|
105
104
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
106
105
|
```
|
|
@@ -155,8 +154,9 @@ Import this stylesheet from `src/main.ts`:
|
|
|
155
154
|
|
|
156
155
|
**Astro**
|
|
157
156
|
|
|
158
|
-
|
|
159
|
-
entry holds only Tailwind. Add
|
|
157
|
+
c15t inlines the banner's rules into each page and links the dialog's
|
|
158
|
+
when it opens, so the CSS entry holds only Tailwind. Add
|
|
159
|
+
`@tailwindcss/vite` under `vite.plugins`:
|
|
160
160
|
|
|
161
161
|
```js title="astro.config.mjs"
|
|
162
162
|
import svelte from '@astrojs/svelte';
|
|
@@ -202,12 +202,10 @@ import { defineConfig } from 'vite';
|
|
|
202
202
|
export default defineConfig({ plugins: [svelte(), tailwindcss()] });
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
-
Import this stylesheet from `src/main.ts
|
|
206
|
-
`@c15t/svelte/styles.css` import:
|
|
205
|
+
Import this stylesheet from `src/main.ts`:
|
|
207
206
|
|
|
208
207
|
```css title="src/app.css"
|
|
209
208
|
@import 'tailwindcss';
|
|
210
|
-
@import '@c15t/svelte/styles.css';
|
|
211
209
|
|
|
212
210
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
213
211
|
```
|
|
@@ -226,7 +224,6 @@ Import this stylesheet from your root `+layout.svelte`:
|
|
|
226
224
|
|
|
227
225
|
```css title="src/app.css"
|
|
228
226
|
@import 'tailwindcss';
|
|
229
|
-
@import '@c15t/svelte/styles.css';
|
|
230
227
|
|
|
231
228
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
232
229
|
```
|
|
@@ -256,8 +253,12 @@ c15t's parts, pass the URL of your built stylesheet in
|
|
|
256
253
|
|
|
257
254
|
## Set up Tailwind CSS 3
|
|
258
255
|
|
|
259
|
-
Tailwind 3
|
|
260
|
-
|
|
256
|
+
Tailwind 3's preflight is unlayered, so it beats the layered rules c15t
|
|
257
|
+
renders itself and strips the banner's padding and borders. On Tailwind 3,
|
|
258
|
+
turn those rules off with `styles: false` and import c15t's `styles.css`
|
|
259
|
+
through a PostCSS plugin. The Astro integration needs only the plugin: it
|
|
260
|
+
detects Tailwind 3 and links `c15t/astro/styles.css` itself. Every c15t
|
|
261
|
+
package that ships a stylesheet exports the plugin as
|
|
261
262
|
`<package>/postcss-tailwind3`, so use the one from the package you installed:
|
|
262
263
|
|
|
263
264
|
| You installed | Plugin name |
|
|
@@ -269,21 +270,26 @@ plugin. Every c15t package that ships a stylesheet exports it as
|
|
|
269
270
|
They are the same plugin. A config that already lists
|
|
270
271
|
`@c15t/ui/postcss-tailwind3` keeps working.
|
|
271
272
|
|
|
272
|
-
Make
|
|
273
|
+
Make four changes:
|
|
273
274
|
|
|
274
|
-
1.
|
|
275
|
+
1. Set `styles: false` where you configure c15t: `options` on `ConsentRoot`
|
|
276
|
+
in Next.js and TanStack Start, `options` on `ConsentProvider` in React,
|
|
277
|
+
and `styles={false}` on `ConsentManagerProvider` in Svelte and SvelteKit.
|
|
278
|
+
Vue, Nuxt and Astro need no change.
|
|
279
|
+
2. Add the plugin to your PostCSS plugins, before `tailwindcss`. Write the plugins as an object, as the examples below do.
|
|
275
280
|
PostCSS runs them in the order of the keys. Next.js also accepts an array
|
|
276
281
|
of plugin names, but Vite's PostCSS loader rejects that form.
|
|
277
|
-
|
|
278
|
-
|
|
282
|
+
3. Import c15t's stylesheet above the `@tailwind` directives, whatever your
|
|
283
|
+
build tool. Vue, Nuxt and Astro skip this step. Vite drops an `@import`
|
|
279
284
|
that follows another rule, with the warning
|
|
280
285
|
`@import must precede all other statements`, and the banner renders
|
|
281
286
|
unstyled. Next.js 16 with Turbopack fails the build.
|
|
282
|
-
|
|
287
|
+
4. Set `darkMode: 'class'` so Tailwind's `dark:` variant follows the same
|
|
283
288
|
`dark` class c15t reads.
|
|
284
289
|
|
|
285
|
-
The plugin also processes the stylesheets
|
|
286
|
-
|
|
290
|
+
The plugin also processes the stylesheets the Vue and Nuxt components import,
|
|
291
|
+
and the one the Astro integration adds on a Tailwind 3 site. Without it,
|
|
292
|
+
Tailwind 3 stops
|
|
287
293
|
the build with "`@layer components` is used but no matching
|
|
288
294
|
`@tailwind components` directive is present", or purges c15t's rules, because
|
|
289
295
|
c15t's class names never appear in your source.
|
|
@@ -293,8 +299,9 @@ class. Add the important modifier to utilities you pass to c15t parts:
|
|
|
293
299
|
`!bg-red-500`, `hover:!bg-red-500`. A bare `bg-red-500` has no effect. Theme
|
|
294
300
|
tokens work the same on Tailwind 3 and 4.
|
|
295
301
|
|
|
296
|
-
In React and Next.js apps, `c15t setup`
|
|
297
|
-
finds Tailwind 3
|
|
302
|
+
In React and Next.js apps, `c15t setup` adds the plugin and the stylesheet
|
|
303
|
+
import when it finds Tailwind 3, but does not set `styles: false`. Add that
|
|
304
|
+
yourself. It replaces an existing
|
|
298
305
|
`styles.tw3.css` import from an earlier setup with `styles.css`. When it
|
|
299
306
|
cannot edit your PostCSS config, it prints the step to do by hand. See
|
|
300
307
|
[setup](https://c15t.com/docs/cli/commands/setup#set-up-styles-and-tailwind-css).
|
|
@@ -327,7 +334,7 @@ export default {
|
|
|
327
334
|
|
|
328
335
|
Import `c15t/next/styles.css` above the directives. Turbopack fails the
|
|
329
336
|
build when the import sits below them. The same order works with
|
|
330
|
-
webpack:
|
|
337
|
+
webpack. Set `styles: false` in `ConsentRoot`'s `options` as well:
|
|
331
338
|
|
|
332
339
|
```css title="app/globals.css"
|
|
333
340
|
/* Turbopack rejects an @import below other rules, so it goes first. */
|
|
@@ -358,7 +365,8 @@ export default {
|
|
|
358
365
|
```
|
|
359
366
|
|
|
360
367
|
Import `c15t/tanstack-start/styles.css` above the directives, in the
|
|
361
|
-
stylesheet your root route links:
|
|
368
|
+
stylesheet your root route links, and set `styles: false` in
|
|
369
|
+
`ConsentRoot`'s `options`:
|
|
362
370
|
|
|
363
371
|
```css title="src/styles.css"
|
|
364
372
|
/* Vite ignores an @import below other rules, so it goes first. */
|
|
@@ -388,8 +396,9 @@ export default {
|
|
|
388
396
|
} satisfies Config;
|
|
389
397
|
```
|
|
390
398
|
|
|
391
|
-
Import `c15t/react/styles.css` above the directives,
|
|
392
|
-
stylesheet from your entry module:
|
|
399
|
+
Import `c15t/react/styles.css` above the directives, import this
|
|
400
|
+
stylesheet from your entry module, and set `styles: false` in the
|
|
401
|
+
`ConsentProvider` options:
|
|
393
402
|
|
|
394
403
|
```css title="src/app.css"
|
|
395
404
|
/* Vite ignores an @import below other rules, so it goes first. */
|
|
@@ -489,8 +498,12 @@ export default {
|
|
|
489
498
|
} satisfies Config;
|
|
490
499
|
```
|
|
491
500
|
|
|
492
|
-
|
|
493
|
-
|
|
501
|
+
When the integration finds Tailwind 3 in the project, it adds
|
|
502
|
+
`c15t/astro/styles.css` to every page through Astro's CSS pipeline
|
|
503
|
+
instead of inlining the banner's rules, so the plugin processes it. You
|
|
504
|
+
do not set `styles: false` or import c15t's stylesheet, and the CSS
|
|
505
|
+
entry holds only the directives. The first paint still waits for that
|
|
506
|
+
stylesheet:
|
|
494
507
|
|
|
495
508
|
```css title="src/styles/global.css"
|
|
496
509
|
@tailwind base;
|
|
@@ -521,8 +534,9 @@ export default {
|
|
|
521
534
|
} satisfies Config;
|
|
522
535
|
```
|
|
523
536
|
|
|
524
|
-
Import `@c15t/svelte/styles.css` above the directives,
|
|
525
|
-
stylesheet from `src/main.ts
|
|
537
|
+
Import `@c15t/svelte/styles.css` above the directives, import this
|
|
538
|
+
stylesheet from `src/main.ts`, and pass `styles={false}` to
|
|
539
|
+
`ConsentManagerProvider`:
|
|
526
540
|
|
|
527
541
|
```css title="src/app.css"
|
|
528
542
|
/* Vite ignores an @import below other rules, so it goes first. */
|
|
@@ -556,8 +570,9 @@ export default {
|
|
|
556
570
|
} satisfies Config;
|
|
557
571
|
```
|
|
558
572
|
|
|
559
|
-
Import `@c15t/svelte/styles.css` above the directives,
|
|
560
|
-
stylesheet from your root `+layout.svelte
|
|
573
|
+
Import `@c15t/svelte/styles.css` above the directives, import this
|
|
574
|
+
stylesheet from your root `+layout.svelte`, and pass `styles={false}` to
|
|
575
|
+
`ConsentManagerProvider`:
|
|
561
576
|
|
|
562
577
|
```css title="src/app.css"
|
|
563
578
|
/* Vite ignores an @import below other rules, so it goes first. */
|
|
@@ -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
|
|
@@ -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
|
|
|
@@ -12,20 +12,23 @@ The [quickstart](../quickstart.md) mounts both in
|
|
|
12
12
|
`src/consent.tsx`:
|
|
13
13
|
|
|
14
14
|
```tsx title="src/consent.tsx"
|
|
15
|
+
import { manifest } from '@c15t/browser/headless';
|
|
15
16
|
import {
|
|
16
17
|
ConsentBanner,
|
|
17
18
|
ConsentDialog,
|
|
18
19
|
ConsentDialogLink,
|
|
19
20
|
ConsentProvider,
|
|
20
|
-
hosted,
|
|
21
21
|
} from 'c15t/react';
|
|
22
22
|
import type { ReactNode } from 'react';
|
|
23
23
|
|
|
24
|
+
import { consentManifest } from './c15t-manifest';
|
|
24
25
|
import { scripts } from './scripts';
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const mode = manifest({
|
|
28
|
+
backendURL:
|
|
29
|
+
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
30
|
+
manifest: consentManifest,
|
|
31
|
+
});
|
|
29
32
|
|
|
30
33
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
31
34
|
<ConsentProvider options={{ mode, scripts }}>
|
|
@@ -14,20 +14,23 @@ group: frameworks
|
|
|
14
14
|
code.
|
|
15
15
|
|
|
16
16
|
```tsx title="src/consent.tsx"
|
|
17
|
+
import { manifest } from '@c15t/browser/headless';
|
|
17
18
|
import {
|
|
18
19
|
ConsentBanner,
|
|
19
20
|
ConsentDialog,
|
|
20
21
|
ConsentDialogLink,
|
|
21
22
|
ConsentProvider,
|
|
22
|
-
hosted,
|
|
23
23
|
} from 'c15t/react';
|
|
24
24
|
import type { ReactNode } from 'react';
|
|
25
25
|
|
|
26
|
+
import { consentManifest } from './c15t-manifest';
|
|
26
27
|
import { scripts } from './scripts';
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const mode = manifest({
|
|
30
|
+
backendURL:
|
|
31
|
+
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
32
|
+
manifest: consentManifest,
|
|
33
|
+
});
|
|
31
34
|
|
|
32
35
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
33
36
|
<ConsentProvider options={{ mode, scripts }}>
|
|
@@ -130,7 +133,7 @@ If a preload fails, for example because the visitor is offline, nothing is
|
|
|
130
133
|
cached: the next hover, focus or open tries the download again.
|
|
131
134
|
|
|
132
135
|
The dialog's CSS travels in the same chunk and is applied before the dialog
|
|
133
|
-
renders, so
|
|
136
|
+
renders, so the first page load carries only the banner's rules.
|
|
134
137
|
|
|
135
138
|
Without an `open` prop, Escape closes the dialog without saving. If the
|
|
136
139
|
policy still owes a choice, the banner comes back. Save Settings, Accept All and
|
|
@@ -14,20 +14,23 @@ The [quickstart](../quickstart.md) does this in
|
|
|
14
14
|
`src/consent.tsx`:
|
|
15
15
|
|
|
16
16
|
```tsx title="src/consent.tsx"
|
|
17
|
+
import { manifest } from '@c15t/browser/headless';
|
|
17
18
|
import {
|
|
18
19
|
ConsentBanner,
|
|
19
20
|
ConsentDialog,
|
|
20
21
|
ConsentDialogLink,
|
|
21
22
|
ConsentProvider,
|
|
22
|
-
hosted,
|
|
23
23
|
} from 'c15t/react';
|
|
24
24
|
import type { ReactNode } from 'react';
|
|
25
25
|
|
|
26
|
+
import { consentManifest } from './c15t-manifest';
|
|
26
27
|
import { scripts } from './scripts';
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const mode = manifest({
|
|
30
|
+
backendURL:
|
|
31
|
+
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
32
|
+
manifest: consentManifest,
|
|
33
|
+
});
|
|
31
34
|
|
|
32
35
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
33
36
|
<ConsentProvider options={{ mode, scripts }}>
|
|
@@ -41,9 +44,11 @@ export const Consent = ({ children }: { children: ReactNode }) => (
|
|
|
41
44
|
);
|
|
42
45
|
```
|
|
43
46
|
|
|
44
|
-
`
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
`manifest()` from `@c15t/browser/headless` resolves the policy from the
|
|
48
|
+
snapshot the build bundled, and sends consent choices to `backendURL`. Replace
|
|
49
|
+
the demo project URL with the URL from your Inth project, or set
|
|
50
|
+
`VITE_C15T_BACKEND_URL`. To fetch the policy from the backend on every page
|
|
51
|
+
load instead, pass `hosted({ url })` from `c15t/react`. The Next.js and TanStack Start adapters export `ConsentRoot` instead, which wraps
|
|
47
52
|
this provider and passes it server-resolved state.
|
|
48
53
|
|
|
49
54
|
## Provider options
|
|
@@ -56,35 +61,35 @@ the provider to change them. `scripts`, `vendors`, `networkBlocker`,
|
|
|
56
61
|
`iframeBlocker`, `consentCategories`, `overrides`, `user`, `callbacks` and
|
|
57
62
|
`enabled` apply when they change.
|
|
58
63
|
|
|
59
|
-
| Option | Purpose
|
|
60
|
-
| ----------------------------- |
|
|
61
|
-
| `mode` | Required. `hosted({ url })` for a backend, `offline()` for local policies, or `custom()` for your own transport
|
|
62
|
-
| `prefetch` | Server-resolved state, or a promise of it, from a framework adapter's server helper
|
|
63
|
-
| `scripts` | Consent-gated vendor scripts. See [scripts and embeds](../scripts.md)
|
|
64
|
-
| `vendors` | Vendors listed under their category with their own switch. See [vendor consent](../vendor-consent.md)
|
|
65
|
-
| `scriptLoader` | Options for the script loader module
|
|
66
|
-
| `networkBlocker` | Rules that hold `fetch` and `XMLHttpRequest` calls until their category is allowed, or `false`
|
|
67
|
-
| `iframeBlocker` | Gates DOM iframes that carry `data-category`. On by default; `false` turns it off
|
|
68
|
-
| `persistence` | Stores the visitor's choice in a cookie and localStorage. On by default
|
|
69
|
-
| `storageConfig` | Storage key and cookie settings for the stored choice
|
|
70
|
-
| `clearOnRevocation` | Cookies and storage keys to delete when a category is denied
|
|
71
|
-
| `reloadOnConsentRevoked` | Reload the page after the visitor turns off a granted category or vendor. Defaults to `true`
|
|
72
|
-
| `consentCategories` | Categories the preference dialog offers alongside those your scripts use, within the policy's scope
|
|
73
|
-
| `overrides` | Force the country, region or language the policy is resolved for, for testing
|
|
74
|
-
| `user` | Link consent records to a signed-in user
|
|
75
|
-
| `callbacks` | Choice, permission and error events
|
|
76
|
-
| `i18n` | Languages and message overrides
|
|
77
|
-
| `legalLinks` | Privacy policy and other links shown in the banner and dialog
|
|
78
|
-
| `theme` | `consentActions` and slot styles. Tokens go through `ConsentTheme`; see [customize](../customize.md)
|
|
79
|
-
| `components` | Slot attributes per component part
|
|
80
|
-
| `presentation` | Banner and dialog shape, position and blocking
|
|
81
|
-
| `experiment` | A/B test of `presentation`, read once at mount. See [banner experiments](../../../guides/banner-experiments.md)
|
|
82
|
-
| `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)
|
|
83
|
-
| `colorScheme` | `'light'`, `'dark'`, `'system'`, or `null` to leave the `c15t-dark` class alone
|
|
84
|
-
| `noStyle`, `disableAnimation` | Drop the built-in styles, or turn off animations
|
|
85
|
-
| `preloadDialog` | When the deferred `ConsentDialog` starts loading: `'idle'` (default) or `'intent'`; see [ConsentDialog](./consent-dialog.md#behavior)
|
|
86
|
-
| `nonce` | Content Security Policy nonce for script elements c15t inserts
|
|
87
|
-
| `enabled` | Set `false` only when you deliberately bypass consent enforcement
|
|
64
|
+
| Option | Purpose |
|
|
65
|
+
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
66
|
+
| `mode` | Required. `hosted({ url })` for a backend, `manifest()` from `@c15t/browser/headless` for a bundled policy, `offline()` for local policies, or `custom()` for your own transport |
|
|
67
|
+
| `prefetch` | Server-resolved state, or a promise of it, from a framework adapter's server helper |
|
|
68
|
+
| `scripts` | Consent-gated vendor scripts. See [scripts and embeds](../scripts.md) |
|
|
69
|
+
| `vendors` | Vendors listed under their category with their own switch. See [vendor consent](../vendor-consent.md) |
|
|
70
|
+
| `scriptLoader` | Options for the script loader module |
|
|
71
|
+
| `networkBlocker` | Rules that hold `fetch` and `XMLHttpRequest` calls until their category is allowed, or `false` |
|
|
72
|
+
| `iframeBlocker` | Gates DOM iframes that carry `data-category`. On by default; `false` turns it off |
|
|
73
|
+
| `persistence` | Stores the visitor's choice in a cookie and localStorage. On by default |
|
|
74
|
+
| `storageConfig` | Storage key and cookie settings for the stored choice |
|
|
75
|
+
| `clearOnRevocation` | Cookies and storage keys to delete when a category is denied |
|
|
76
|
+
| `reloadOnConsentRevoked` | Reload the page after the visitor turns off a granted category or vendor. Defaults to `true` |
|
|
77
|
+
| `consentCategories` | Categories the preference dialog offers alongside those your scripts use, within the policy's scope |
|
|
78
|
+
| `overrides` | Force the country, region or language the policy is resolved for, for testing |
|
|
79
|
+
| `user` | Link consent records to a signed-in user |
|
|
80
|
+
| `callbacks` | Choice, permission and error events |
|
|
81
|
+
| `i18n` | Languages and message overrides |
|
|
82
|
+
| `legalLinks` | Privacy policy and other links shown in the banner and dialog |
|
|
83
|
+
| `theme` | `consentActions` and slot styles. Tokens go through `ConsentTheme`; see [customize](../customize.md) |
|
|
84
|
+
| `components` | Slot attributes per component part |
|
|
85
|
+
| `presentation` | Banner and dialog shape, position and blocking |
|
|
86
|
+
| `experiment` | A/B test of `presentation`, read once at mount. See [banner experiments](../../../guides/banner-experiments.md) |
|
|
87
|
+
| `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) |
|
|
88
|
+
| `colorScheme` | `'light'`, `'dark'`, `'system'`, or `null` to leave the `c15t-dark` class alone |
|
|
89
|
+
| `noStyle`, `disableAnimation` | Drop the built-in styles, or turn off animations |
|
|
90
|
+
| `preloadDialog` | When the deferred `ConsentDialog` starts loading: `'idle'` (default) or `'intent'`; see [ConsentDialog](./consent-dialog.md#behavior) |
|
|
91
|
+
| `nonce` | Content Security Policy nonce for script elements c15t inserts |
|
|
92
|
+
| `enabled` | Set `false` only when you deliberately bypass consent enforcement |
|
|
88
93
|
|
|
89
94
|
`enabled: false` grants categories and allows gated loading while suppressing
|
|
90
95
|
consent UI. It is not a way to fix failed initialization or hide a banner in
|
|
@@ -36,20 +36,23 @@ 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 { manifest } from '@c15t/browser/headless';
|
|
39
40
|
import {
|
|
40
41
|
ConsentBanner,
|
|
41
42
|
ConsentDialog,
|
|
42
43
|
ConsentDialogLink,
|
|
43
44
|
ConsentProvider,
|
|
44
|
-
hosted,
|
|
45
45
|
} from 'c15t/react';
|
|
46
46
|
import type { ReactNode } from 'react';
|
|
47
47
|
|
|
48
|
+
import { consentManifest } from './c15t-manifest';
|
|
48
49
|
import { scripts } from './scripts';
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const mode = manifest({
|
|
52
|
+
backendURL:
|
|
53
|
+
import.meta.env.VITE_C15T_BACKEND_URL ?? 'https://benchmarks-inth.inth.app',
|
|
54
|
+
manifest: consentManifest,
|
|
55
|
+
});
|
|
53
56
|
|
|
54
57
|
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
55
58
|
<ConsentProvider options={{ mode, scripts }}>
|
|
@@ -79,7 +82,8 @@ explains the trade-off.
|
|
|
79
82
|
|
|
80
83
|
Import `IABProvider`, `IABConsentBanner` and `IABConsentDialog` from
|
|
81
84
|
`c15t/react/iab`, render them inside `ConsentProvider` next to
|
|
82
|
-
`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
|
|
83
87
|
under an IAB policy. See
|
|
84
88
|
[IAB TCF](./iab.md).
|
|
85
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 {
|