@c15t/scripts 3.0.0-alpha.1 → 3.0.0-alpha.3
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 +129 -59
- package/README.md +8 -29
- package/SKILL.md +33 -0
- package/dist/adobe-analytics.js +2 -0
- package/dist/ahrefs-analytics.js +2 -0
- package/dist/amplitude.js +2 -0
- package/dist/clearbit.js +2 -0
- package/dist/cloudflare-web-analytics.js +2 -0
- package/dist/cloudflare-zaraz.js +2 -0
- package/dist/crisp.js +2 -0
- package/dist/databuddy.js +2 -0
- package/dist/e2e-test-utils.js +2 -137
- package/dist/engine/compile.js +2 -89
- package/dist/engine/runtime.js +2 -448
- package/dist/events.js +2 -0
- package/dist/fathom-analytics.js +2 -0
- package/dist/front-chat.js +2 -0
- package/dist/google-tag-manager.js +2 -0
- package/dist/google-tag.js +2 -0
- package/dist/heap.js +2 -0
- package/dist/hightouch.js +2 -0
- package/dist/hotjar.js +2 -0
- package/dist/intercom.js +2 -0
- package/dist/klaviyo.js +2 -0
- package/dist/linkedin-insights.js +2 -0
- package/dist/logrocket.js +2 -0
- package/dist/matomo-analytics.js +2 -0
- package/dist/meta-pixel.js +2 -0
- package/dist/microsoft-clarity.js +2 -0
- package/dist/microsoft-uet.js +2 -0
- package/dist/mixpanel-analytics.js +2 -0
- package/dist/one-dollar-stats.js +2 -0
- package/dist/openai-pixel.js +2 -0
- package/dist/pinterest-tag.js +2 -0
- package/dist/pirsch.js +2 -0
- package/dist/plausible-analytics.js +2 -0
- package/dist/posthog.js +2 -0
- package/dist/promptwatch.js +2 -0
- package/dist/reddit-pixel.js +2 -0
- package/dist/registry.js +2 -392
- package/dist/resolve.js +2 -33
- package/dist/rudderstack.js +2 -0
- package/dist/rybbit-analytics.js +2 -0
- package/dist/segment.js +2 -0
- package/dist/snapchat-pixel.js +2 -0
- package/dist/tiktok-pixel.js +2 -0
- package/dist/types.js +2 -16
- package/dist/umami-analytics.js +2 -0
- package/dist/vendors/_shared/attributes.js +2 -14
- package/dist/vendors/_shared/google-consent.js +2 -27
- package/dist/vendors/_shared/install-builders.js +2 -21
- package/dist/vendors/_shared/required-id.js +2 -0
- package/dist/vendors/_shared/script-url.js +2 -28
- package/dist/vendors/ads-and-pixels/linkedin-insights.js +2 -48
- package/dist/vendors/ads-and-pixels/meta-pixel.js +2 -153
- package/dist/vendors/ads-and-pixels/microsoft-uet.js +2 -110
- package/dist/vendors/ads-and-pixels/openai-pixel.js +2 -88
- package/dist/vendors/ads-and-pixels/pinterest-tag.js +2 -0
- package/dist/vendors/ads-and-pixels/reddit-pixel.js +2 -107
- package/dist/vendors/ads-and-pixels/snapchat-pixel.js +2 -87
- package/dist/vendors/ads-and-pixels/tiktok-pixel.js +2 -89
- package/dist/vendors/ads-and-pixels/x-pixel.js +2 -48
- package/dist/vendors/analytics/adobe-analytics.js +2 -49
- package/dist/vendors/analytics/ahrefs-analytics.js +2 -27
- package/dist/vendors/analytics/amplitude.js +2 -134
- package/dist/vendors/analytics/clearbit.js +2 -28
- package/dist/vendors/analytics/cloudflare-web-analytics.js +2 -32
- package/dist/vendors/analytics/databuddy.js +2 -103
- package/dist/vendors/analytics/fathom-analytics.js +2 -35
- package/dist/vendors/analytics/google-tag.js +2 -66
- package/dist/vendors/analytics/heap.js +2 -134
- package/dist/vendors/analytics/hightouch.js +2 -109
- package/dist/vendors/analytics/hotjar.js +2 -44
- package/dist/vendors/analytics/logrocket.js +2 -58
- package/dist/vendors/analytics/matomo-analytics.js +2 -191
- package/dist/vendors/analytics/microsoft-clarity.js +2 -100
- package/dist/vendors/analytics/mixpanel-analytics.js +2 -93
- package/dist/vendors/analytics/one-dollar-stats.js +2 -0
- package/dist/vendors/analytics/pirsch.js +2 -67
- package/dist/vendors/analytics/plausible-analytics.js +2 -81
- package/dist/vendors/analytics/posthog.js +2 -200
- package/dist/vendors/analytics/promptwatch.js +2 -29
- package/dist/vendors/analytics/rudderstack.js +2 -183
- package/dist/vendors/analytics/rybbit-analytics.js +2 -63
- package/dist/vendors/analytics/segment.js +2 -56
- package/dist/vendors/analytics/umami-analytics.js +2 -39
- package/dist/vendors/analytics/vercel-analytics.js +2 -53
- package/dist/vendors/email-and-sms/klaviyo.js +2 -0
- package/dist/vendors/functional/crisp.js +2 -100
- package/dist/vendors/functional/front-chat.js +2 -0
- package/dist/vendors/functional/intercom.js +2 -45
- package/dist/vendors/tag-managers/cloudflare-zaraz.js +2 -98
- package/dist/vendors/tag-managers/google-tag-manager.js +2 -59
- package/dist/vercel-analytics.js +2 -0
- package/dist/x-pixel.js +2 -0
- package/dist-types/adobe-analytics.d.ts +2 -0
- package/dist-types/ahrefs-analytics.d.ts +2 -0
- package/dist-types/amplitude.d.ts +2 -0
- package/dist-types/clearbit.d.ts +2 -0
- package/dist-types/cloudflare-web-analytics.d.ts +2 -0
- package/dist-types/cloudflare-zaraz.d.ts +2 -0
- package/dist-types/crisp.d.ts +2 -0
- package/dist-types/databuddy.d.ts +2 -0
- package/dist-types/e2e-test-utils.d.ts +2 -0
- package/dist-types/engine/compile.d.ts +2 -3
- package/dist-types/engine/runtime.d.ts +2 -3
- package/dist-types/events.d.ts +2 -0
- package/dist-types/fathom-analytics.d.ts +2 -0
- package/dist-types/front-chat.d.ts +2 -0
- package/dist-types/google-tag-manager.d.ts +2 -0
- package/dist-types/google-tag.d.ts +2 -0
- package/dist-types/heap.d.ts +2 -0
- package/dist-types/hightouch.d.ts +2 -0
- package/dist-types/hotjar.d.ts +2 -0
- package/dist-types/intercom.d.ts +2 -0
- package/dist-types/klaviyo.d.ts +2 -0
- package/dist-types/linkedin-insights.d.ts +2 -0
- package/dist-types/logrocket.d.ts +2 -0
- package/dist-types/matomo-analytics.d.ts +2 -0
- package/dist-types/meta-pixel.d.ts +2 -0
- package/dist-types/microsoft-clarity.d.ts +2 -0
- package/dist-types/microsoft-uet.d.ts +2 -0
- package/dist-types/mixpanel-analytics.d.ts +2 -0
- package/dist-types/one-dollar-stats.d.ts +2 -0
- package/dist-types/openai-pixel.d.ts +2 -0
- package/dist-types/pinterest-tag.d.ts +2 -0
- package/dist-types/pirsch.d.ts +2 -0
- package/dist-types/plausible-analytics.d.ts +2 -0
- package/dist-types/posthog.d.ts +2 -0
- package/dist-types/promptwatch.d.ts +2 -0
- package/dist-types/reddit-pixel.d.ts +2 -0
- package/dist-types/registry.d.ts +2 -458
- package/dist-types/resolve.d.ts +2 -9
- package/dist-types/rudderstack.d.ts +2 -0
- package/dist-types/rybbit-analytics.d.ts +2 -0
- package/dist-types/segment.d.ts +2 -0
- package/dist-types/snapchat-pixel.d.ts +2 -0
- package/dist-types/tiktok-pixel.d.ts +2 -0
- package/dist-types/types.d.ts +2 -314
- package/dist-types/umami-analytics.d.ts +2 -0
- package/dist-types/vendors/_shared/attributes.d.ts +2 -35
- package/dist-types/vendors/_shared/google-consent.d.ts +2 -47
- package/dist-types/vendors/_shared/install-builders.d.ts +2 -30
- package/dist-types/vendors/_shared/required-id.d.ts +2 -0
- package/dist-types/vendors/_shared/script-url.d.ts +2 -75
- package/dist-types/vendors/ads-and-pixels/linkedin-insights.d.ts +2 -92
- package/dist-types/vendors/ads-and-pixels/meta-pixel.d.ts +2 -289
- package/dist-types/vendors/ads-and-pixels/microsoft-uet.d.ts +2 -105
- package/dist-types/vendors/ads-and-pixels/openai-pixel.d.ts +2 -211
- package/dist-types/vendors/ads-and-pixels/pinterest-tag.d.ts +2 -0
- package/dist-types/vendors/ads-and-pixels/reddit-pixel.d.ts +2 -210
- package/dist-types/vendors/ads-and-pixels/snapchat-pixel.d.ts +2 -171
- package/dist-types/vendors/ads-and-pixels/tiktok-pixel.d.ts +2 -106
- package/dist-types/vendors/ads-and-pixels/x-pixel.d.ts +2 -183
- package/dist-types/vendors/analytics/adobe-analytics.d.ts +2 -75
- package/dist-types/vendors/analytics/ahrefs-analytics.d.ts +2 -62
- package/dist-types/vendors/analytics/amplitude.d.ts +2 -234
- package/dist-types/vendors/analytics/clearbit.d.ts +2 -60
- package/dist-types/vendors/analytics/cloudflare-web-analytics.d.ts +2 -67
- package/dist-types/vendors/analytics/databuddy.d.ts +2 -147
- package/dist-types/vendors/analytics/fathom-analytics.d.ts +2 -90
- package/dist-types/vendors/analytics/google-tag.d.ts +2 -93
- package/dist-types/vendors/analytics/heap.d.ts +2 -316
- package/dist-types/vendors/analytics/hightouch.d.ts +2 -285
- package/dist-types/vendors/analytics/hotjar.d.ts +2 -73
- package/dist-types/vendors/analytics/logrocket.d.ts +2 -101
- package/dist-types/vendors/analytics/matomo-analytics.d.ts +2 -41
- package/dist-types/vendors/analytics/microsoft-clarity.d.ts +2 -97
- package/dist-types/vendors/analytics/mixpanel-analytics.d.ts +2 -113
- package/dist-types/vendors/analytics/one-dollar-stats.d.ts +2 -0
- package/dist-types/vendors/analytics/pirsch.d.ts +2 -96
- package/dist-types/vendors/analytics/plausible-analytics.d.ts +2 -122
- package/dist-types/vendors/analytics/posthog.d.ts +2 -175
- package/dist-types/vendors/analytics/promptwatch.d.ts +2 -36
- package/dist-types/vendors/analytics/rudderstack.d.ts +2 -330
- package/dist-types/vendors/analytics/rybbit-analytics.d.ts +2 -82
- package/dist-types/vendors/analytics/segment.d.ts +2 -158
- package/dist-types/vendors/analytics/umami-analytics.d.ts +2 -93
- package/dist-types/vendors/analytics/vercel-analytics.d.ts +2 -66
- package/dist-types/vendors/email-and-sms/klaviyo.d.ts +2 -0
- package/dist-types/vendors/functional/crisp.d.ts +2 -78
- package/dist-types/vendors/functional/front-chat.d.ts +2 -0
- package/dist-types/vendors/functional/intercom.d.ts +2 -135
- package/dist-types/vendors/tag-managers/cloudflare-zaraz.d.ts +2 -39
- package/dist-types/vendors/tag-managers/google-tag-manager.d.ts +2 -94
- package/dist-types/vercel-analytics.d.ts +2 -0
- package/dist-types/x-pixel.d.ts +2 -0
- package/docs/README.md +129 -59
- package/docs/assets/v3/bottom-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/brand-preferences.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/headless-bar-html.png +0 -0
- package/docs/assets/v3/headless-bar-mobile.png +0 -0
- package/docs/assets/v3/headless-bar.png +0 -0
- package/docs/assets/v3/slim-bar.png +0 -0
- package/docs/concepts/choose-your-setup.md +87 -0
- package/docs/concepts/consent-categories.md +84 -0
- package/docs/concepts/consent-state.md +357 -0
- package/docs/{guides → concepts}/data-fetching.md +31 -27
- package/docs/concepts/how-consent-works.md +123 -0
- package/docs/concepts/policies.md +71 -0
- package/docs/customization/class-names.md +202 -0
- package/docs/customization/dark-mode.md +157 -0
- package/docs/customization/motion.md +119 -0
- package/docs/customization/overview.md +67 -33
- package/docs/customization/recipes.md +839 -47
- package/docs/customization/slots.md +216 -35
- package/docs/customization/stylesheets.md +147 -0
- package/docs/customization/tailwind.md +842 -0
- package/docs/customization/tokens.md +166 -36
- package/docs/customization/translations.md +61 -3
- package/docs/frameworks/astro/embeds.md +160 -0
- package/docs/frameworks/astro/network-blocker.md +86 -0
- package/docs/frameworks/astro/scripts.md +146 -0
- package/docs/frameworks/html/embeds.md +142 -0
- package/docs/frameworks/html/network-blocker.md +105 -0
- package/docs/frameworks/html/scripts.md +164 -0
- package/docs/frameworks/javascript/scripts.md +119 -0
- package/docs/frameworks/next/embeds.md +90 -0
- package/docs/frameworks/next/network-blocker.md +153 -0
- package/docs/frameworks/next/scripts.md +196 -0
- package/docs/frameworks/nuxt/embeds.md +81 -0
- package/docs/frameworks/nuxt/network-blocker.md +97 -0
- package/docs/frameworks/nuxt/scripts.md +89 -0
- package/docs/frameworks/react/embeds.md +89 -0
- package/docs/frameworks/react/network-blocker.md +140 -0
- package/docs/frameworks/react/scripts.md +115 -0
- package/docs/frameworks/svelte/embeds.md +96 -0
- package/docs/frameworks/svelte/network-blocker.md +141 -0
- package/docs/frameworks/svelte/scripts.md +137 -0
- package/docs/frameworks/sveltekit/embeds.md +103 -0
- package/docs/frameworks/sveltekit/network-blocker.md +149 -0
- package/docs/frameworks/sveltekit/scripts.md +141 -0
- package/docs/frameworks/tanstack-start/embeds.md +96 -0
- package/docs/frameworks/tanstack-start/network-blocker.md +145 -0
- package/docs/frameworks/tanstack-start/scripts.md +103 -0
- package/docs/frameworks/vue/embeds.md +84 -0
- package/docs/frameworks/vue/network-blocker.md +99 -0
- package/docs/frameworks/vue/scripts.md +93 -0
- package/docs/guides/banner-experiments.md +654 -0
- package/docs/guides/troubleshooting.md +120 -47
- package/docs/guides/verify-consent.md +81 -49
- package/docs/integrations/adobe-analytics.md +168 -160
- package/docs/integrations/ahrefs-analytics.md +153 -155
- package/docs/integrations/amplitude.md +163 -157
- package/docs/integrations/building-integrations.md +136 -37
- package/docs/integrations/clearbit.md +155 -155
- package/docs/integrations/cloudflare-web-analytics.md +157 -157
- package/docs/integrations/cloudflare-zaraz.md +210 -262
- package/docs/integrations/crisp.md +165 -159
- package/docs/integrations/databuddy.md +158 -174
- package/docs/integrations/fathom-analytics.md +159 -157
- package/docs/integrations/front-chat.md +322 -0
- package/docs/integrations/google-maps.md +119 -84
- package/docs/integrations/google-tag-manager.md +179 -164
- package/docs/integrations/google-tag.md +164 -161
- package/docs/integrations/heap.md +164 -156
- package/docs/integrations/hightouch.md +162 -158
- package/docs/integrations/hotjar.md +160 -156
- package/docs/integrations/intercom.md +184 -154
- package/docs/integrations/klaviyo.md +486 -0
- package/docs/integrations/linkedin-insights.md +175 -151
- package/docs/integrations/logrocket.md +161 -157
- package/docs/integrations/matomo-analytics.md +189 -179
- package/docs/integrations/meta-pixel.md +189 -151
- package/docs/integrations/microsoft-clarity.md +164 -156
- package/docs/integrations/microsoft-uet.md +149 -155
- package/docs/integrations/mixpanel-analytics.md +156 -161
- package/docs/integrations/one-dollar-stats.md +306 -0
- package/docs/integrations/openai-pixel.md +205 -302
- package/docs/integrations/overview.md +143 -83
- package/docs/integrations/pinterest-tag.md +329 -0
- package/docs/integrations/pirsch.md +170 -160
- package/docs/integrations/plausible-analytics.md +173 -159
- package/docs/integrations/posthog.md +227 -242
- package/docs/integrations/promptwatch.md +155 -155
- package/docs/integrations/reddit-pixel.md +186 -158
- package/docs/integrations/rudderstack.md +202 -187
- package/docs/integrations/rybbit-analytics.md +172 -161
- package/docs/integrations/segment.md +183 -155
- package/docs/integrations/snapchat-pixel.md +187 -157
- package/docs/integrations/tiktok-pixel.md +172 -151
- package/docs/integrations/umami-analytics.md +164 -159
- package/docs/integrations/vercel-analytics.md +167 -158
- package/docs/integrations/x-pixel.md +177 -151
- package/docs/integrations/youtube.md +122 -87
- package/docs/upgrade-v3.md +490 -354
- package/package.json +12 -236
- package/dist-types/__tests__/helpers.d.ts +0 -141
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/frameworks/javascript/script-loader.md +0 -94
- package/docs/frameworks/next/script-loader.md +0 -210
- package/docs/frameworks/react/script-loader.md +0 -63
- package/docs/guides/consent-state.md +0 -60
- package/docs/guides/deployment-modes.md +0 -75
- package/docs/integrations/clear-on-revocation.md +0 -167
- package/docs/integrations/granular-consent.md +0 -208
|
@@ -1,55 +1,236 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description:
|
|
2
|
+
title: Component parts
|
|
3
|
+
description: Find every part of c15t's banner, dialog, widget, trigger and
|
|
4
|
+
ConsentGate placeholder, its key in your framework's part API, and the data
|
|
5
|
+
attributes to select on.
|
|
4
6
|
group: customization
|
|
5
7
|
---
|
|
6
8
|
|
|
7
|
-
##
|
|
9
|
+
## Which part API your framework uses
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
Each framework has one way to add classes, inline styles or attributes to a
|
|
12
|
+
single part of a stock component. The keys differ between the two
|
|
13
|
+
vocabularies, so a configuration from one does not work in the other.
|
|
14
|
+
|
|
15
|
+
| Framework | Part API | Keys look like | Class key |
|
|
16
|
+
| ----------------------- | ------------------------------------------------------------- | ------------------------- | ------------------------ |
|
|
17
|
+
| Next.js, TanStack Start | `options.components` on `ConsentRoot` | `components.banner.card` | `className` |
|
|
18
|
+
| React | `components` in the `ConsentProvider` options | `components.banner.card` | `className` |
|
|
19
|
+
| Nuxt | `components` in the `c15t` options, or in `app/app.config.ts` | `components.banner.card` | `class` |
|
|
20
|
+
| Vue | `components` in the `c15tVue` options | `components.banner.card` | `class` |
|
|
21
|
+
| Astro | `theme.slots` in the `c15t()` integration options | `slots.consentBannerCard` | A string, or `className` |
|
|
22
|
+
| Svelte, SvelteKit | `theme.slots` on `ConsentManagerProvider` | `slots.consentBannerCard` | A string, or `className` |
|
|
23
|
+
| HTML, JavaScript | `ui.theme.slots` | `slots.consentBannerCard` | A string, or `className` |
|
|
24
|
+
|
|
25
|
+
React and Vue also read `theme.slots` from the theme in their options, and
|
|
26
|
+
apply each slot to the matching `components` part, such as
|
|
27
|
+
`consentDialogCard` to `dialog.card` and `toggle` to `switch.root`. Where both
|
|
28
|
+
set the same part, classes from both apply, inline styles merge with
|
|
29
|
+
`components` winning per property, and any other attribute in `components`
|
|
30
|
+
replaces the theme's. In Vue and Nuxt, each part object is bound with
|
|
31
|
+
`v-bind`, so write `class` and `style` rather than React's `className`.
|
|
32
|
+
|
|
33
|
+
Svelte's stock components, and Astro's `ConsentBanner`, `IABConsentBanner`
|
|
34
|
+
and `ConsentDialogTrigger`, also take a `class` prop. On `ConsentBanner` it
|
|
35
|
+
goes on the banner root.
|
|
36
|
+
|
|
37
|
+
This React fragment belongs in the provider options:
|
|
11
38
|
|
|
12
39
|
```tsx
|
|
13
40
|
components: {
|
|
14
41
|
banner: {
|
|
15
|
-
card: { className: '
|
|
16
|
-
title: {
|
|
17
|
-
footer: { className: 'border-t' },
|
|
42
|
+
card: { className: 'brand-card' },
|
|
43
|
+
title: { style: { fontWeight: 600 } },
|
|
18
44
|
},
|
|
45
|
+
},
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The same parts with `theme.slots`, which every framework reads:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
theme: {
|
|
52
|
+
slots: {
|
|
53
|
+
consentBannerCard: 'brand-card',
|
|
54
|
+
consentBannerTitle: 'brand-title',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
A slot can also be `{ className, style }`. Svelte applies both on every part,
|
|
60
|
+
including the IAB banner and dialog.
|
|
61
|
+
|
|
62
|
+
[Class names and CSS-in-JS](./class-names.md) covers CSS
|
|
63
|
+
Modules, vanilla-extract, StyleX and Emotion, and
|
|
64
|
+
[Tailwind CSS](./tailwind.md) covers utilities on parts.
|
|
65
|
+
|
|
66
|
+
## Banner parts
|
|
67
|
+
|
|
68
|
+
| Part | `components` key | `theme.slots` key | `data-testid` |
|
|
69
|
+
| ------------------------------------------- | ------------------------------------ | ---------------------------------- | --------------------- |
|
|
70
|
+
| Positioning root, with the state attributes | `banner.root` | `consentBanner` | `consent-banner-root` |
|
|
71
|
+
| Card sizing and branding container | `banner.cardShell` | None | |
|
|
72
|
+
| Visible card | `banner.card` | `consentBannerCard` | `consent-banner-card` |
|
|
73
|
+
| Title and description container | `banner.header` | `consentBannerHeader` | |
|
|
74
|
+
| Title | `banner.title` | `consentBannerTitle` | |
|
|
75
|
+
| Description | `description.banner` | `consentBannerDescription` | |
|
|
76
|
+
| Action area | `banner.footer` | `consentBannerFooter` | |
|
|
77
|
+
| Group of action groups | `banner.actions` | None | |
|
|
78
|
+
| One group of equally prominent actions | `banner.actionGroup` | `consentBannerFooterSubGroup` | |
|
|
79
|
+
| Group of right links | `banner.rights` | `consentBannerRights` | |
|
|
80
|
+
| One right link | `banner.rightLink` | `consentBannerRightLink` | |
|
|
81
|
+
| Backdrop of a blocking banner | `banner.overlay` | `consentBannerOverlay` | |
|
|
82
|
+
| "Secured by" tag | `tag.banner` | `consentBannerTag` | |
|
|
83
|
+
| Filled and outlined buttons | `button.primary`, `button.secondary` | `buttonPrimary`, `buttonSecondary` | |
|
|
84
|
+
|
|
85
|
+
The button parts apply to every c15t button of that style, in the banner and
|
|
86
|
+
the dialog. The script tag's banner has no rights group, so
|
|
87
|
+
`consentBannerRights` does not apply there.
|
|
88
|
+
|
|
89
|
+
## Preference dialog parts
|
|
90
|
+
|
|
91
|
+
| Part | `components` key | `theme.slots` key | `data-testid` |
|
|
92
|
+
| ---------------- | -------------------- | -------------------------- | --------------------- |
|
|
93
|
+
| Positioner | `dialog.root` | None | |
|
|
94
|
+
| Dialog container | `dialog.container` | `consentDialog` | `consent-dialog-root` |
|
|
95
|
+
| Card | `dialog.card` | `consentDialogCard` | |
|
|
96
|
+
| Header | `dialog.header` | `consentDialogHeader` | |
|
|
97
|
+
| Title | `dialog.title` | `consentDialogTitle` | |
|
|
98
|
+
| Description | `description.dialog` | `consentDialogDescription` | |
|
|
99
|
+
| Content | `dialog.content` | `consentDialogContent` | |
|
|
100
|
+
| Backdrop | `dialog.overlay` | `consentDialogOverlay` | |
|
|
101
|
+
| "Secured by" tag | `tag.dialog` | `consentDialogTag` | |
|
|
102
|
+
|
|
103
|
+
The stock dialog's footer is the preference widget's footer. Style it with
|
|
104
|
+
`consentWidgetFooter`. There is no `consentDialogFooter` slot.
|
|
105
|
+
|
|
106
|
+
## Preference widget parts
|
|
107
|
+
|
|
108
|
+
The widget is the list of categories inside the dialog. React and Vue call it
|
|
109
|
+
`manager`.
|
|
110
|
+
|
|
111
|
+
| Part | `components` key | `theme.slots` key |
|
|
112
|
+
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
|
|
113
|
+
| Widget root | `manager.root` | `consentWidget` |
|
|
114
|
+
| Footer | `manager.footer` | `consentWidgetFooter` |
|
|
115
|
+
| Group of action groups | `manager.actions` | None |
|
|
116
|
+
| One action group | `manager.actionGroup` | `consentWidgetFooterSubGroup` |
|
|
117
|
+
| Category accordion | `accordion.root`, `accordion.triggerRow`, `accordion.arrow`, `accordion.header`, `accordion.title`, `accordion.control`, `accordion.contentViewport`, `accordion.contentInner` | `consentWidgetAccordion` |
|
|
118
|
+
| One accordion item | `accordion-item.root`, `accordion-item.trigger`, `accordion-item.content` | None |
|
|
119
|
+
| Category switch | `switch.root`, `switch.track`, `switch.thumb` | `toggle` |
|
|
120
|
+
| Vendor list | `vendor-list.root`, `vendor-list.trigger`, `vendor-list.content`, `vendor-list.item`, `vendor-list.header`, `vendor-list.name`, `vendor-list.description`, `vendor-list.link`, `vendor-list.control` | None |
|
|
121
|
+
| "Secured by" tag | `tag.manager` in React, `tag.dialog` in Vue | `consentWidgetTag` |
|
|
122
|
+
|
|
123
|
+
## Floating trigger parts
|
|
124
|
+
|
|
125
|
+
| Part | `components` key | `theme.slots` key |
|
|
126
|
+
| ---------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
127
|
+
| Button | `trigger.root` | `consentDialogTrigger` |
|
|
128
|
+
| Icon | `trigger.icon` | `consentDialogTriggerIcon` |
|
|
129
|
+
| Label | `trigger.text` | None |
|
|
130
|
+
| Toolbar, its items and icons | `trigger.toolbar`, `trigger.toolbarItem`, `trigger.toolbarIcon` | `consentDialogTriggerToolbar`, `consentDialogTriggerToolbarItem`, `consentDialogTriggerToolbarIcon` |
|
|
131
|
+
|
|
132
|
+
Only React renders the toolbar. Vue has no toolbar, and the toolbar slots only
|
|
133
|
+
reach Astro's React dialog.
|
|
134
|
+
|
|
135
|
+
## Legal links and IAB TCF parts
|
|
136
|
+
|
|
137
|
+
| Component | `components` keys | `theme.slots` keys |
|
|
138
|
+
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
139
|
+
| Legal links | `legal-links.root`, and `link.banner`, `link.dialog`, `link.manager` for one link | None |
|
|
140
|
+
| IAB banner | `iab-banner.root`, `cardShell`, `card`, `header`, `title`, `description`, `partnersLink`, `purposeList`, `purposeMore`, `legitimateInterestNotice`, `footer`, `actions`, `actionGroup`, `overlay` | `iabConsentBanner`, `iabConsentBannerCard`, `iabConsentBannerHeader`, `iabConsentBannerFooter`, `iabConsentBannerTag`, `iabConsentBannerOverlay` |
|
|
141
|
+
| IAB dialog | `iab-dialog.root`, `card`, `header`, `headerContent`, `title`, `description`, `closeButton`, `body`, `content`, `loading`, `footer`, `tabs`, `tabsList`, `tabTrigger`, `tabIndicator`, `tabPanel`, `specialPurposes`, `consentNotice`, `actions`, `actionGroup`, `overlay` | `iabConsentDialog`, `iabConsentDialogCard`, `iabConsentDialogHeader`, `iabConsentDialogFooter`, `iabConsentDialogTag`, `iabConsentDialogOverlay` |
|
|
142
|
+
| IAB purpose, stack and vendor rows | `iab-purpose-item.*`, `iab-stack-item.*`, `iab-vendor-list.*` | None |
|
|
143
|
+
|
|
144
|
+
Legal links take no `theme.slots` key. They keep their stock link class, and
|
|
145
|
+
a description slot's classes stay on the description around them.
|
|
146
|
+
|
|
147
|
+
## ConsentGate placeholder parts
|
|
148
|
+
|
|
149
|
+
`ConsentGate` shows a placeholder card while its category is denied. React,
|
|
150
|
+
Next.js, TanStack Start, Vue, Nuxt, Svelte and SvelteKit render the same
|
|
151
|
+
three parts:
|
|
152
|
+
|
|
153
|
+
| Part | `components` key | `theme.slots` key | `data-testid` |
|
|
154
|
+
| ----------------------------- | --------------------- | ------------------- | -------------------------- |
|
|
155
|
+
| Placeholder card | `consent-gate.root` | `consentGate` | `consent-gate-placeholder` |
|
|
156
|
+
| Title | `consent-gate.title` | `consentGateTitle` | `consent-gate-title` |
|
|
157
|
+
| Button that opens preferences | `consent-gate.button` | `consentGateButton` | `consent-gate-button` |
|
|
158
|
+
|
|
159
|
+
The button part applies on top of `button.primary`, or `buttonPrimary`. The
|
|
160
|
+
parts only reach the built-in placeholder. A placeholder you pass yourself
|
|
161
|
+
takes your own classes, and the wrapper around the gate takes `className` in
|
|
162
|
+
React or `class` in Svelte. Astro, HTML and JavaScript have no `ConsentGate`.
|
|
163
|
+
|
|
164
|
+
## Style parts from outside the script tag's shadow root
|
|
165
|
+
|
|
166
|
+
The script tag and `init()` render into a shadow root. Every part that has a
|
|
167
|
+
`theme.slots` key carries it in a `part` attribute, so page CSS can reach it
|
|
168
|
+
with `::part()`:
|
|
169
|
+
|
|
170
|
+
```css
|
|
171
|
+
[data-c15t-ui]::part(consentBannerCard) {
|
|
172
|
+
border: 3px solid #6943a3;
|
|
19
173
|
}
|
|
20
174
|
```
|
|
21
175
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
176
|
+
## Select on state attributes
|
|
177
|
+
|
|
178
|
+
Parts carry `data-*` attributes that describe their state. Select on these
|
|
179
|
+
instead of guessing at markup:
|
|
180
|
+
|
|
181
|
+
| Element | Attributes |
|
|
182
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
183
|
+
| Banner root | `data-prompt`, `data-model`, `data-variant`, `data-position`, `data-blocking` |
|
|
184
|
+
| Action buttons | `data-action` (`accept`, `reject`, `customize`, `dismiss` or `save`), `data-variant`, `data-mode` |
|
|
185
|
+
| Footer and action groups | `data-direction`, `data-fill`, `data-split` |
|
|
186
|
+
| Right links | `data-action="right"`, `data-right` |
|
|
187
|
+
| Preference dialog | `data-state` (`open` or `closed`), on the elements listed in [motion](./motion.md#animate-your-own-rules-on-dialog-state) |
|
|
188
|
+
| Category switch | `data-state`, `data-disabled` |
|
|
189
|
+
|
|
190
|
+
The script tag's banner root has `data-variant`, `data-position` and
|
|
191
|
+
`data-blocking` only, with `data-blocking` set to `"true"` or `"false"`. Its
|
|
192
|
+
right links carry `data-action="customize"`.
|
|
193
|
+
|
|
194
|
+
The banner card does not inherit the root's attributes. With Tailwind, give
|
|
195
|
+
the root `group` and read the root's attribute from a child part:
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
components: {
|
|
199
|
+
banner: {
|
|
200
|
+
root: { className: 'group' },
|
|
201
|
+
card: { className: 'group-data-[variant=bar]:rounded-none' },
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
```
|
|
25
205
|
|
|
26
|
-
|
|
206
|
+
Test notices as well as choice prompts. A notice has an acknowledge action,
|
|
207
|
+
`data-action="dismiss"`, instead of accept and reject.
|
|
27
208
|
|
|
28
|
-
|
|
29
|
-
`data-position` and `data-blocking`. Its child card does not inherit those HTML
|
|
30
|
-
attributes. In Tailwind, give the root `className: 'group'` and use
|
|
31
|
-
`group-data-[variant=bar]:...` on a child slot.
|
|
209
|
+
## Do not target c15t's class names
|
|
32
210
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
| `header`, `title`, `description` | Heading and explanatory copy |
|
|
39
|
-
| `footer`, `actions`, `actionGroup` | Action layout |
|
|
40
|
-
| `rights`, `rightLink` | Preferences access controls |
|
|
41
|
-
| `overlay` | Backdrop for blocking presentation |
|
|
211
|
+
c15t's stock class names are generated from CSS Modules and end in a hash, such
|
|
212
|
+
as `c15t-ui-card-lgjVq`. The hash changes whenever the source CSS changes, and
|
|
213
|
+
the classes disappear under `noStyle`. A rule that targets one breaks on an
|
|
214
|
+
upgrade without warning. Target a part API, `data-testid`, a `data-*`
|
|
215
|
+
attribute or `::part()` instead.
|
|
42
216
|
|
|
43
|
-
|
|
44
|
-
choice prompts; a notice uses acknowledgement rather than accept/reject.
|
|
217
|
+
## Remove c15t's classes with noStyle
|
|
45
218
|
|
|
46
|
-
|
|
219
|
+
`noStyle` renders the same markup and behavior without c15t's stock classes. It
|
|
220
|
+
keeps your part classes and styles, `data-testid` and the `data-*` attributes.
|
|
221
|
+
It does not replace layout, spacing, focus indicators or responsive behavior,
|
|
222
|
+
so use it when you intend to write all of that yourself.
|
|
47
223
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
224
|
+
| Framework | Where |
|
|
225
|
+
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
226
|
+
| Next.js, TanStack Start, React | `noStyle` in the provider options for every component, or the `noStyle` prop on `ConsentBanner`, `ConsentDialog`, `ConsentWidget`, `ConsentDialogTrigger` and the IAB components |
|
|
227
|
+
| Svelte, SvelteKit | `noStyle` in the provider options, or the prop on a stock component |
|
|
228
|
+
| Astro | `noStyle` prop on `ConsentBanner` and `IABConsentBanner` |
|
|
229
|
+
| HTML, JavaScript | `ui.noStyle`, which also drops the bundled stylesheet |
|
|
230
|
+
| Vue, Nuxt | The `noStyle` prop on `ConsentWidget`, and on the `PreferenceItemRoot` and `PreferenceItemContent` primitives, whose other parts follow the root. The banner, dialog and trigger have no `noStyle` |
|
|
52
231
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
slot
|
|
232
|
+
In `theme.slots`, `{ noStyle: true }` on one slot replaces that part's stock
|
|
233
|
+
classes in Svelte, Astro's banner and the script tag. React and Vue, including
|
|
234
|
+
Astro's React and Vue dialog islands, ignore a slot's `noStyle`, so its classes
|
|
235
|
+
apply on top of the stock ones. If the markup itself must change, use your framework's compound
|
|
236
|
+
components or headless API.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Stylesheets and CSS layers
|
|
3
|
+
description: Load the right c15t stylesheet for your framework, see when the
|
|
4
|
+
dialog's CSS loads, order c15t's cascade layer against your own, and run c15t
|
|
5
|
+
without its styles.
|
|
6
|
+
group: customization
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Load one stylesheet for your framework
|
|
10
|
+
|
|
11
|
+
| Framework | What to load | Where |
|
|
12
|
+
| ----------------- | -------------------------------- | -------------------------------------------------------------------- |
|
|
13
|
+
| Next.js | `c15t/next/styles.css` | Your global stylesheet, or the layout that renders the consent root |
|
|
14
|
+
| TanStack Start | `c15t/tanstack-start/styles.css` | A `<link>` from the root route's `head()`, or your global stylesheet |
|
|
15
|
+
| React | `c15t/react/styles.css` | The module that renders `ConsentProvider`, or your global stylesheet |
|
|
16
|
+
| Nuxt, Vue | Nothing | Each Vue component imports its own stylesheet |
|
|
17
|
+
| Astro | Nothing | The integration adds `c15t/astro/styles.css` to every page |
|
|
18
|
+
| Svelte, SvelteKit | `@c15t/svelte/styles.css` | Your entry module or root layout |
|
|
19
|
+
| HTML | Nothing | `c15t.js` carries its stylesheet into the UI's shadow root |
|
|
20
|
+
| JavaScript | Nothing | `init()` carries its stylesheet into the UI's shadow root |
|
|
21
|
+
|
|
22
|
+
Load it once. With IAB TCF in Next.js, TanStack Start, React, Svelte or
|
|
23
|
+
SvelteKit, also load the adapter's `iab/styles.css`, such as
|
|
24
|
+
`c15t/next/iab/styles.css`, after `styles.css`. Astro adds its IAB stylesheet
|
|
25
|
+
when the integration sets `iab`. Tailwind 3 uses the same files and adds a
|
|
26
|
+
PostCSS plugin; [Tailwind CSS](./tailwind.md#set-up-tailwind-css-3)
|
|
27
|
+
shows the setup.
|
|
28
|
+
|
|
29
|
+
## What loads with the first paint
|
|
30
|
+
|
|
31
|
+
A stylesheet that blocks rendering should hold only what the first paint can
|
|
32
|
+
show. c15t's main stylesheet holds the default tokens, every c15t CSS variable,
|
|
33
|
+
and the rules for the banner, the floating trigger and the `ConsentGate`
|
|
34
|
+
placeholder. The preference dialog's rules load separately in most frameworks:
|
|
35
|
+
|
|
36
|
+
| Framework | The preference dialog's rules |
|
|
37
|
+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
38
|
+
| Next.js, TanStack Start, React | The dialog's code imports `@c15t/ui/styles/dialog.css`. Your bundler emits it with the dialog's lazy chunk and loads it before that chunk runs, so the dialog never renders unstyled |
|
|
39
|
+
| Nuxt, Vue | The dialog component imports its stylesheet, so the rules load with the dialog's code, not the banner's |
|
|
40
|
+
| Astro | c15t links the dialog's stylesheets when a visitor first points at, focuses or opens a control that opens the dialog, and keeps them across `ClientRouter` navigation |
|
|
41
|
+
| Svelte, SvelteKit | Part of `@c15t/svelte/styles.css`, so they load up front |
|
|
42
|
+
| HTML, JavaScript | Part of the stylesheet in the shadow root, which holds only the rules the stock surfaces use |
|
|
43
|
+
|
|
44
|
+
In React, Next.js and TanStack Start, do not import `dialog.css` yourself. The
|
|
45
|
+
`@c15t/react/components/consent-dialog`, `/components/consent-widget`,
|
|
46
|
+
`/primitives`, `/primitives/*` and `/iab` entry points import it as soon as
|
|
47
|
+
you import them, because they render dialog parts outside the lazy chunk.
|
|
48
|
+
|
|
49
|
+
These modules import the stylesheet through `@c15t/ui/styles/dialog`. Under
|
|
50
|
+
the `node` export condition that module imports nothing, so server code that
|
|
51
|
+
loads `@c15t/react` with plain Node, such as the Pages Router or an SSR build
|
|
52
|
+
that keeps dependencies external, does not fail on the `.css` file. In your own
|
|
53
|
+
components, import `@c15t/ui/styles/dialog` rather than the `.css` file if the
|
|
54
|
+
module can run on the server.
|
|
55
|
+
|
|
56
|
+
## Order c15t's layer against your CSS
|
|
57
|
+
|
|
58
|
+
c15t puts its component rules in the cascade layer `components`. Tokens,
|
|
59
|
+
variables and keyframes stay unlayered. Each stylesheet opens with Tailwind
|
|
60
|
+
CSS 4's layer order:
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
@layer properties, theme, base, components, utilities;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Cascade layers rank by the order they are first named, so `components` stays
|
|
67
|
+
above Tailwind's preflight in `base` and below `utilities`, whichever
|
|
68
|
+
stylesheet loads first. Without Tailwind the other layers stay empty. Vue's
|
|
69
|
+
per-component stylesheets open with the same statement.
|
|
70
|
+
|
|
71
|
+
What this means for your overrides:
|
|
72
|
+
|
|
73
|
+
* Any unlayered rule of yours outranks every c15t component rule, whatever its
|
|
74
|
+
specificity or load order. You do not need `!important`.
|
|
75
|
+
* A rule in one of your own layers wins only if that layer comes after
|
|
76
|
+
`components` in the layer order.
|
|
77
|
+
* Tokens are not layered. Set them as described in
|
|
78
|
+
[theme tokens](./tokens.md).
|
|
79
|
+
|
|
80
|
+
If your CSS declares its own layer order, load that statement before c15t's
|
|
81
|
+
stylesheet. If you import c15t's stylesheet into a named layer, such as
|
|
82
|
+
`@import 'c15t/react/styles.css' layer(c15t)`, the dialog's lazy rules still
|
|
83
|
+
join the top-level `components` layer. List `components` in your statement,
|
|
84
|
+
for example `@layer c15t, components, app;`, so it does not land after your
|
|
85
|
+
own layers.
|
|
86
|
+
|
|
87
|
+
## Load Astro's stylesheets yourself
|
|
88
|
+
|
|
89
|
+
The Astro integration adds `c15t/astro/styles.css` to every page ahead of your
|
|
90
|
+
own CSS. To control the order yourself, for example from a global stylesheet
|
|
91
|
+
that names its own layers, set `styles: false` in the `c15t()` options and
|
|
92
|
+
import the files after your layer order statement. With `styles: false`, c15t
|
|
93
|
+
links no dialog stylesheet either, so import the dialog's rules too. The
|
|
94
|
+
Svelte dialog, the default `ui`, also needs the primitives stylesheet:
|
|
95
|
+
|
|
96
|
+
```css title="src/styles/global.css"
|
|
97
|
+
@import 'c15t/astro/styles.css';
|
|
98
|
+
@import 'c15t/astro/dialog.css';
|
|
99
|
+
/* Only with ui: 'svelte'. */
|
|
100
|
+
@import 'c15t/astro/primitives.css';
|
|
101
|
+
/* Only when the integration sets iab. */
|
|
102
|
+
@import 'c15t/astro/iab/styles.css';
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Keep c15t's stylesheet when you restyle the surfaces. The browser hides the
|
|
106
|
+
Astro banner with the `hidden` attribute, and the stylesheet makes that
|
|
107
|
+
attribute beat the banner's own `display` rule.
|
|
108
|
+
|
|
109
|
+
## Style the script tag's shadow root
|
|
110
|
+
|
|
111
|
+
The script tag and `init()` from `@c15t/browser` render into a shadow root with
|
|
112
|
+
their own copy of the stylesheet. Your page's CSS does not reach the UI, and
|
|
113
|
+
the UI's CSS does not reach your page. To style it:
|
|
114
|
+
|
|
115
|
+
| Option | What it does |
|
|
116
|
+
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
117
|
+
| `ui.theme` | Tokens, written after the stylesheet inside the shadow root |
|
|
118
|
+
| `ui.css` | A string of CSS added after the stylesheet and the theme |
|
|
119
|
+
| `ui.stylesheetURLs` | Stylesheets linked inside the shadow root, after c15t's, with the client's `nonce`. They load asynchronously, so the first frame can render without them |
|
|
120
|
+
| `::part()` | Page CSS that reaches a part by its slot key, as in `[data-c15t-ui]::part(consentBannerCard)` |
|
|
121
|
+
| `ui.shadow: false`, or `data-shadow="false"` | Renders into the page, so your stylesheets apply. c15t still injects its stylesheet next to the UI |
|
|
122
|
+
| `ui.styles: false` | Drops the injected stylesheet. With `shadow: false`, load `@c15t/browser/styles.css` from your bundle, or link `dist/c15t.css` from the same package version as the script |
|
|
123
|
+
|
|
124
|
+
A stylesheet in `ui.stylesheetURLs` should also load on the page. Some CSS,
|
|
125
|
+
such as Tailwind 4's `@property` rules, only takes effect in the page's
|
|
126
|
+
stylesheets. Of these options, the script tag has an attribute for `shadow`
|
|
127
|
+
only. Set the others with `c15t.push(['config', { ui: { ... } }])`.
|
|
128
|
+
|
|
129
|
+
## Run without c15t's styles
|
|
130
|
+
|
|
131
|
+
`noStyle` removes c15t's stock classes from the markup, and in the script tag
|
|
132
|
+
also the injected stylesheet. Your part classes, `data-testid` and the `data-*`
|
|
133
|
+
attributes stay. [Component parts](./slots.md#remove-c15ts-classes-with-nostyle)
|
|
134
|
+
lists where each framework takes it.
|
|
135
|
+
|
|
136
|
+
`noStyle` does not supply layout, spacing, focus indicators or responsive
|
|
137
|
+
behavior. If a token seems to do nothing, check the layer order and your
|
|
138
|
+
selector before you reach for `noStyle`.
|
|
139
|
+
|
|
140
|
+
## Check the result
|
|
141
|
+
|
|
142
|
+
1. Open DevTools Network, clear site data and reload. Your framework's c15t
|
|
143
|
+
stylesheet loads once, and no second copy appears.
|
|
144
|
+
2. Open the preference dialog. It is styled on its first frame, with no flash
|
|
145
|
+
of unstyled content.
|
|
146
|
+
3. Select a banner part and read the Styles panel. c15t's rules appear under
|
|
147
|
+
`@layer components`, and your unlayered rules for the same property win.
|