@c15t/react 3.0.0-alpha.1 → 3.0.0-alpha.10

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.
Files changed (406) hide show
  1. package/AGENTS.md +96 -70
  2. package/README.md +21 -17
  3. package/SKILL.md +34 -0
  4. package/dist/aggregate-components.js +1 -1
  5. package/dist/chunk-warming.js +1 -1
  6. package/dist/component-hooks/use-headless-consent-ui.js +1 -1
  7. package/dist/component-hooks/use-headless-iab-consent-ui.js +1 -1
  8. package/dist/component-hooks/use-panel-trigger.js +1 -1
  9. package/dist/components/consent-gate/atoms.js +1 -0
  10. package/dist/components/consent-gate/consent-gate.js +2 -0
  11. package/dist/components/consent-gate/frame.js +2 -0
  12. package/dist/components/consent-gate/index.js +2 -0
  13. package/dist/components/consent-preferences-link/consent-preferences-link.js +1 -1
  14. package/dist/components/iab-panel/atoms/card.js +1 -1
  15. package/dist/components/iab-panel/atoms/feature-item.js +2 -0
  16. package/dist/components/iab-panel/atoms/header.js +1 -1
  17. package/dist/components/iab-panel/atoms/purpose-item.js +1 -1
  18. package/dist/components/iab-panel/atoms/root.js +1 -1
  19. package/dist/components/iab-panel/atoms/stack-item.js +1 -1
  20. package/dist/components/iab-panel/atoms/vendor-list.js +1 -1
  21. package/dist/components/iab-panel/hooks/use-gvl-data.js +1 -1
  22. package/dist/components/iab-panel/iab-panel.js +1 -1
  23. package/dist/components/iab-panel/index.js +1 -1
  24. package/dist/components/iab-prompt/atoms/overlay.js +1 -1
  25. package/dist/components/iab-prompt/atoms/root.js +1 -1
  26. package/dist/components/panel/atoms/card.js +1 -1
  27. package/dist/components/panel/atoms/overlay.js +1 -1
  28. package/dist/components/panel/atoms/root.js +1 -1
  29. package/dist/components/panel/panel.js +1 -1
  30. package/dist/components/panel-trigger/atoms/button.js +1 -1
  31. package/dist/components/panel-trigger/atoms/icon.js +1 -1
  32. package/dist/components/panel-trigger/atoms/root.js +1 -1
  33. package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
  34. package/dist/components/panel-trigger/atoms/trigger-icons.js +1 -0
  35. package/dist/components/panel-trigger/panel-trigger-toolbar.js +1 -1
  36. package/dist/components/panel-trigger/panel-trigger.js +1 -1
  37. package/dist/components/preferences/atoms/accordion.js +1 -1
  38. package/dist/components/preferences/atoms/root.js +1 -1
  39. package/dist/components/preferences/atoms/vendor-list.js +1 -0
  40. package/dist/components/preferences/index.js +1 -1
  41. package/dist/components/prompt/atoms/early-tap-script.js +2 -0
  42. package/dist/components/prompt/atoms/overlay.js +1 -1
  43. package/dist/components/prompt/atoms/root.js +1 -1
  44. package/dist/components/prompt/components.js +1 -1
  45. package/dist/components/prompt/policy-actions.js +1 -1
  46. package/dist/components/prompt/prompt.js +1 -1
  47. package/dist/components/shared/dialog-sheets.js +1 -0
  48. package/dist/components/shared/first-paint-sheets.js +1 -0
  49. package/dist/components/shared/iab-dialog-sheets.js +1 -0
  50. package/dist/components/shared/iab-first-paint-sheets.js +1 -0
  51. package/dist/components/shared/libs/compose-refs.js +1 -0
  52. package/dist/components/shared/libs/slot.js +1 -1
  53. package/dist/components/shared/primitives/button.js +1 -1
  54. package/dist/components/shared/primitives/legal-links/index.js +1 -1
  55. package/dist/components/shared/streamed-surface.js +2 -0
  56. package/dist/components/shared/surface-styles.js +2 -0
  57. package/dist/components/shared/ui/dialog/dialog.js +1 -1
  58. package/dist/components/shared/ui/icon.js +1 -1
  59. package/dist/components/shared/ui/logo.js +1 -1
  60. package/dist/components/shared/ui/preference-item/preference-item.js +1 -1
  61. package/dist/consent-gate.js +2 -0
  62. package/dist/consent-theme.js +1 -0
  63. package/dist/context/consent-tracking-context.js +1 -1
  64. package/dist/context/index.js +1 -1
  65. package/dist/context.js +1 -1
  66. package/dist/devtools-launcher.js +2 -0
  67. package/dist/devtools.js +1 -1
  68. package/dist/draft-context.js +2 -0
  69. package/dist/draft.js +1 -1
  70. package/dist/external-iab-context.js +1 -1
  71. package/dist/gpp.js +2 -0
  72. package/dist/headless.js +1 -1
  73. package/dist/hooks/use-color-scheme.js +1 -1
  74. package/dist/hooks/use-committed-ref.js +2 -0
  75. package/dist/hooks/use-focus-trap.js +1 -1
  76. package/dist/hooks/use-headless-iab-consent-ui.js +1 -1
  77. package/dist/hooks/use-iab-policy-guard.js +1 -0
  78. package/dist/hooks/use-late-entry.js +2 -0
  79. package/dist/hooks.js +1 -1
  80. package/dist/iab/styles.tw3.css +5 -45
  81. package/dist/iab-context.js +1 -1
  82. package/dist/index-parts/consent-banner.js +1 -0
  83. package/dist/index-parts/consent-dialog-link.js +1 -0
  84. package/dist/index-parts/consent-dialog-trigger.js +1 -0
  85. package/dist/index-parts/consent-dialog.js +1 -0
  86. package/dist/index-parts/consent-gate.js +1 -0
  87. package/dist/index-parts/core.js +1 -0
  88. package/dist/index-parts/draft.js +1 -0
  89. package/dist/index-parts/frame.js +1 -0
  90. package/dist/index-parts/hooks.js +1 -0
  91. package/dist/index-parts/hosted.js +1 -0
  92. package/dist/index-parts/module-hooks.js +1 -0
  93. package/dist/index-parts/offline.js +1 -0
  94. package/dist/index-parts/presets.js +1 -0
  95. package/dist/index-parts/provider.js +1 -0
  96. package/dist/index-parts/theme.js +1 -0
  97. package/dist/index-parts/translations.js +1 -0
  98. package/dist/index.js +1 -1
  99. package/dist/kernel-selector.js +1 -0
  100. package/dist/modes.js +1 -0
  101. package/dist/module-hooks/iframe-blocker.js +1 -1
  102. package/dist/module-hooks/network-blocker.js +1 -1
  103. package/dist/module-hooks/network-hold.js +2 -0
  104. package/dist/module-hooks/persistence.js +1 -1
  105. package/dist/panel-link.js +1 -1
  106. package/dist/panel-trigger.js +1 -1
  107. package/dist/panel.js +1 -1
  108. package/dist/postcss-tailwind3.js +1 -0
  109. package/dist/preferences.js +1 -2
  110. package/dist/provider.js +1 -1
  111. package/dist/server/fetch-ssr-data.js +1 -1
  112. package/dist/server/headers.js +1 -1
  113. package/dist/server/normalize-url.js +1 -1
  114. package/dist/styles.tw3.css +33 -51
  115. package/dist/transports/hosted.js +1 -0
  116. package/dist/transports/manifest.js +1 -0
  117. package/dist/transports/offline.js +1 -1
  118. package/dist/utils/deferred-module.js +2 -0
  119. package/dist/utils/merge-slot-props.js +1 -1
  120. package/dist/utils/theme-utils.js +1 -1
  121. package/dist/version.js +1 -1
  122. package/dist-types/aggregate-components.d.ts +2 -2
  123. package/dist-types/chunk-warming.d.ts +45 -8
  124. package/dist-types/component-hooks/use-headless-consent-ui.d.ts +5 -5
  125. package/dist-types/component-hooks/use-headless-iab-consent-ui.d.ts +2 -2
  126. package/dist-types/components/consent-gate/atoms.d.ts +11 -0
  127. package/dist-types/components/consent-gate/consent-gate.d.ts +2 -0
  128. package/dist-types/components/consent-gate/frame.d.ts +19 -0
  129. package/dist-types/components/consent-gate/index.d.ts +25 -0
  130. package/dist-types/components/{frame → consent-gate}/types.d.ts +7 -7
  131. package/dist-types/components/consent-preferences-link/consent-preferences-link.d.ts +1 -1
  132. package/dist-types/components/consent-preferences-link/index.d.ts +1 -1
  133. package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
  134. package/dist-types/components/iab-panel/atoms/purpose-item.d.ts +5 -2
  135. package/dist-types/components/iab-panel/atoms/stack-item.d.ts +7 -2
  136. package/dist-types/components/iab-panel/atoms/vendor-list.d.ts +1 -1
  137. package/dist-types/components/iab-panel/iab-panel.d.ts +3 -3
  138. package/dist-types/components/iab-panel/index.d.ts +29 -26
  139. package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
  140. package/dist-types/components/iab-prompt/iab-prompt.d.ts +3 -3
  141. package/dist-types/components/iab-prompt/index.d.ts +19 -19
  142. package/dist-types/components/panel/atoms/card.d.ts +5 -4
  143. package/dist-types/components/panel/atoms/overlay.d.ts +1 -1
  144. package/dist-types/components/panel/index.d.ts +8 -8
  145. package/dist-types/components/panel/panel.d.ts +3 -3
  146. package/dist-types/components/panel-link/index.d.ts +1 -1
  147. package/dist-types/components/panel-trigger/atoms/button.d.ts +1 -1
  148. package/dist-types/components/panel-trigger/atoms/icon.d.ts +1 -1
  149. package/dist-types/components/panel-trigger/atoms/root.d.ts +2 -2
  150. package/dist-types/components/panel-trigger/atoms/toolbar.d.ts +2 -2
  151. package/dist-types/components/panel-trigger/atoms/trigger-icons.d.ts +25 -0
  152. package/dist-types/components/panel-trigger/index.d.ts +4 -4
  153. package/dist-types/components/panel-trigger/panel-trigger-toolbar.d.ts +1 -1
  154. package/dist-types/components/panel-trigger/panel-trigger.d.ts +9 -17
  155. package/dist-types/components/panel-trigger/types.d.ts +1 -1
  156. package/dist-types/components/preferences/atoms/accordion.d.ts +6 -4
  157. package/dist-types/components/preferences/atoms/button.d.ts +1 -1
  158. package/dist-types/components/preferences/atoms/footer.d.ts +1 -1
  159. package/dist-types/components/preferences/atoms/root.d.ts +1 -1
  160. package/dist-types/components/preferences/atoms/vendor-list.d.ts +23 -0
  161. package/dist-types/components/preferences/index.d.ts +14 -12
  162. package/dist-types/components/preferences/policy-actions.d.ts +2 -2
  163. package/dist-types/components/preferences/preferences.d.ts +1 -1
  164. package/dist-types/components/preferences/types.d.ts +1 -1
  165. package/dist-types/components/prompt/atoms/early-tap-script.d.ts +17 -0
  166. package/dist-types/components/prompt/atoms/root.d.ts +4 -0
  167. package/dist-types/components/prompt/components.d.ts +9 -3
  168. package/dist-types/components/prompt/index.d.ts +12 -12
  169. package/dist-types/components/prompt/policy-actions.d.ts +2 -2
  170. package/dist-types/components/prompt/prompt.d.ts +5 -1
  171. package/dist-types/components/shared/dialog-sheets.d.ts +9 -0
  172. package/dist-types/components/shared/first-paint-sheets.d.ts +8 -0
  173. package/dist-types/components/shared/iab-dialog-sheets.d.ts +3 -0
  174. package/dist-types/components/shared/iab-first-paint-sheets.d.ts +3 -0
  175. package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
  176. package/dist-types/components/shared/policy-actions.d.ts +2 -2
  177. package/dist-types/components/shared/primitives/box.d.ts +1 -1
  178. package/dist-types/components/shared/primitives/button.d.ts +2 -2
  179. package/dist-types/components/shared/primitives/button.types.d.ts +1 -1
  180. package/dist-types/components/shared/streamed-surface.d.ts +23 -0
  181. package/dist-types/components/shared/surface-styles.d.ts +36 -0
  182. package/dist-types/components/shared/ui/accordion/accordion.d.ts +2 -2
  183. package/dist-types/components/shared/ui/accordion/index.d.ts +2 -2
  184. package/dist-types/components/shared/ui/animated-collapse/index.d.ts +2 -2
  185. package/dist-types/components/shared/ui/branding.d.ts +1 -1
  186. package/dist-types/components/shared/ui/button/button.d.ts +1 -1
  187. package/dist-types/components/shared/ui/button/index.d.ts +2 -2
  188. package/dist-types/components/shared/ui/collapsible/index.d.ts +1 -1
  189. package/dist-types/components/shared/ui/dialog/index.d.ts +1 -1
  190. package/dist-types/components/shared/ui/icon.d.ts +2 -1
  191. package/dist-types/components/shared/ui/logo.d.ts +0 -10
  192. package/dist-types/components/shared/ui/preference-item/index.d.ts +1 -1
  193. package/dist-types/components/shared/ui/preference-item/preference-item.d.ts +13 -0
  194. package/dist-types/components/shared/ui/switch/index.d.ts +2 -2
  195. package/dist-types/components/shared/ui/switch/switch.d.ts +1 -1
  196. package/dist-types/components/shared/ui/tabs/index.d.ts +1 -1
  197. package/dist-types/consent-gate.d.ts +1 -0
  198. package/dist-types/consent-theme.d.ts +38 -0
  199. package/dist-types/context/consent-tracking-context.d.ts +10 -0
  200. package/dist-types/context/index.d.ts +3 -3
  201. package/dist-types/context/theme-context.d.ts +3 -3
  202. package/dist-types/context.d.ts +25 -1
  203. package/dist-types/devtools-launcher.d.ts +29 -0
  204. package/dist-types/devtools.d.ts +13 -2
  205. package/dist-types/draft-context.d.ts +31 -0
  206. package/dist-types/draft.d.ts +81 -9
  207. package/dist-types/gpp.d.ts +27 -0
  208. package/dist-types/headless.d.ts +6 -7
  209. package/dist-types/hooks/use-committed-ref.d.ts +24 -0
  210. package/dist-types/hooks/use-focus-trap.d.ts +3 -1
  211. package/dist-types/hooks/use-headless-iab-consent-ui.d.ts +1 -1
  212. package/dist-types/hooks/use-iab-manager.d.ts +5 -5
  213. package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
  214. package/dist-types/hooks/use-late-entry.d.ts +14 -0
  215. package/dist-types/hooks/use-theme.d.ts +1 -1
  216. package/dist-types/hooks.d.ts +106 -11
  217. package/dist-types/iab.d.ts +7 -7
  218. package/dist-types/index-parts/consent-banner.d.ts +7 -0
  219. package/dist-types/index-parts/consent-dialog-link.d.ts +7 -0
  220. package/dist-types/index-parts/consent-dialog-trigger.d.ts +7 -0
  221. package/dist-types/index-parts/consent-dialog.d.ts +7 -0
  222. package/dist-types/index-parts/consent-gate.d.ts +7 -0
  223. package/dist-types/index-parts/core.d.ts +7 -0
  224. package/dist-types/index-parts/draft.d.ts +7 -0
  225. package/dist-types/index-parts/frame.d.ts +7 -0
  226. package/dist-types/index-parts/hooks.d.ts +7 -0
  227. package/dist-types/index-parts/hosted.d.ts +7 -0
  228. package/dist-types/index-parts/module-hooks.d.ts +7 -0
  229. package/dist-types/index-parts/offline.d.ts +7 -0
  230. package/dist-types/index-parts/presets.d.ts +7 -0
  231. package/dist-types/index-parts/provider.d.ts +7 -0
  232. package/dist-types/index-parts/theme.d.ts +8 -0
  233. package/dist-types/index-parts/translations.d.ts +7 -0
  234. package/dist-types/index.d.ts +32 -28
  235. package/dist-types/kernel-selector.d.ts +68 -0
  236. package/dist-types/modes.d.ts +26 -0
  237. package/dist-types/module-hooks/iframe-blocker.d.ts +33 -1
  238. package/dist-types/module-hooks/network-blocker.d.ts +23 -0
  239. package/dist-types/module-hooks/network-hold.d.ts +47 -0
  240. package/dist-types/module-hooks.d.ts +4 -4
  241. package/dist-types/panel-link.d.ts +1 -1
  242. package/dist-types/panel-trigger.d.ts +1 -1
  243. package/dist-types/panel.d.ts +13 -1
  244. package/dist-types/postcss-tailwind3.d.ts +21 -0
  245. package/dist-types/preferences.d.ts +12 -1
  246. package/dist-types/primitives/accordion.d.ts +1 -1
  247. package/dist-types/primitives/button.d.ts +1 -1
  248. package/dist-types/primitives/collapsible.d.ts +1 -1
  249. package/dist-types/primitives/dialog.d.ts +1 -1
  250. package/dist-types/primitives/preference-item.d.ts +1 -1
  251. package/dist-types/primitives/switch.d.ts +1 -1
  252. package/dist-types/primitives/tabs.d.ts +1 -1
  253. package/dist-types/primitives.d.ts +7 -7
  254. package/dist-types/prompt.d.ts +1 -1
  255. package/dist-types/provider.d.ts +169 -28
  256. package/dist-types/server/fetch-ssr-data.d.ts +1 -1
  257. package/dist-types/server/headers.d.ts +14 -4
  258. package/dist-types/server/index.d.ts +5 -5
  259. package/dist-types/server/normalize-url.d.ts +14 -7
  260. package/dist-types/server/types.d.ts +12 -1
  261. package/dist-types/theme-provider.d.ts +2 -2
  262. package/dist-types/transports/hosted.d.ts +36 -0
  263. package/dist-types/transports/manifest.d.ts +48 -0
  264. package/dist-types/transports/offline.d.ts +7 -16
  265. package/dist-types/types/index.d.ts +3 -3
  266. package/dist-types/types/manager.d.ts +1 -1
  267. package/dist-types/types/theme/index.d.ts +1 -1
  268. package/dist-types/ui-config-context.d.ts +14 -2
  269. package/dist-types/utils/deferred-module.d.ts +13 -0
  270. package/dist-types/utils/index.d.ts +4 -4
  271. package/dist-types/utils/merge-slot-props.d.ts +17 -3
  272. package/dist-types/utils/merge-styles.d.ts +1 -1
  273. package/dist-types/utils/theme-utils.d.ts +18 -3
  274. package/dist-types/version.d.ts +1 -1
  275. package/docs/README.md +96 -70
  276. package/docs/assets/v3/bottom-bar.png +0 -0
  277. package/docs/assets/v3/brand-card.png +0 -0
  278. package/docs/assets/v3/brand-preferences.png +0 -0
  279. package/docs/assets/v3/choice-wall.png +0 -0
  280. package/docs/assets/v3/headless-bar-html.png +0 -0
  281. package/docs/assets/v3/headless-bar-mobile.png +0 -0
  282. package/docs/assets/v3/headless-bar.png +0 -0
  283. package/docs/assets/v3/slim-bar.png +0 -0
  284. package/docs/concepts/choose-your-setup.md +138 -0
  285. package/docs/concepts/consent-categories.md +84 -0
  286. package/docs/concepts/consent-state.md +421 -0
  287. package/docs/concepts/data-fetching.md +270 -0
  288. package/docs/concepts/how-consent-works.md +123 -0
  289. package/docs/concepts/modes.md +278 -0
  290. package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +8 -60
  291. package/docs/customization/class-names.md +202 -0
  292. package/docs/customization/dark-mode.md +157 -0
  293. package/docs/customization/motion.md +128 -0
  294. package/docs/customization/overview.md +68 -33
  295. package/docs/customization/recipes.md +838 -47
  296. package/docs/customization/slots.md +217 -35
  297. package/docs/customization/stylesheets.md +248 -0
  298. package/docs/customization/tailwind.md +863 -0
  299. package/docs/customization/tokens.md +167 -36
  300. package/docs/customization/translations.md +87 -3
  301. package/docs/frameworks/react/callbacks.md +118 -0
  302. package/docs/frameworks/react/clear-on-revocation.md +106 -0
  303. package/docs/frameworks/react/components/consent-banner.md +48 -27
  304. package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
  305. package/docs/frameworks/react/components/consent-dialog-trigger.md +86 -76
  306. package/docs/frameworks/react/components/consent-dialog.md +111 -58
  307. package/docs/frameworks/react/components/{frame.md → consent-gate.md} +70 -49
  308. package/docs/frameworks/react/components/consent-provider.md +140 -0
  309. package/docs/frameworks/react/components/consent-widget.md +69 -24
  310. package/docs/frameworks/react/components/dev-tools.md +76 -85
  311. package/docs/frameworks/react/components.md +113 -0
  312. package/docs/frameworks/react/compose.md +354 -0
  313. package/docs/frameworks/react/content-security-policy.md +143 -0
  314. package/docs/frameworks/react/customize.md +258 -0
  315. package/docs/frameworks/react/embeds.md +89 -0
  316. package/docs/frameworks/react/gpp.md +163 -0
  317. package/docs/frameworks/react/headless.md +4 -4
  318. package/docs/frameworks/react/hooks.md +70 -0
  319. package/docs/frameworks/react/iab.md +259 -0
  320. package/docs/frameworks/react/network-blocker.md +140 -0
  321. package/docs/frameworks/react/quickstart.md +220 -102
  322. package/docs/frameworks/react/rendering.md +263 -0
  323. package/docs/frameworks/react/scripts.md +114 -0
  324. package/docs/frameworks/react/translations.md +155 -0
  325. package/docs/frameworks/react/troubleshooting.md +188 -61
  326. package/docs/frameworks/react/upgrade-v3.md +651 -0
  327. package/docs/frameworks/react/vendor-consent.md +188 -0
  328. package/docs/guides/banner-experiments.md +672 -0
  329. package/docs/guides/troubleshooting.md +192 -54
  330. package/docs/guides/verify-consent.md +96 -49
  331. package/docs/integrations/adobe-analytics.md +177 -183
  332. package/docs/integrations/ahrefs-analytics.md +162 -178
  333. package/docs/integrations/amplitude.md +172 -180
  334. package/docs/integrations/building-integrations.md +137 -33
  335. package/docs/integrations/clearbit.md +164 -178
  336. package/docs/integrations/cloudflare-web-analytics.md +166 -180
  337. package/docs/integrations/cloudflare-zaraz.md +333 -0
  338. package/docs/integrations/crisp.md +174 -182
  339. package/docs/integrations/databuddy.md +167 -197
  340. package/docs/integrations/fathom-analytics.md +168 -180
  341. package/docs/integrations/front-chat.md +308 -0
  342. package/docs/integrations/google-maps.md +142 -108
  343. package/docs/integrations/google-tag-manager.md +258 -185
  344. package/docs/integrations/google-tag.md +226 -182
  345. package/docs/integrations/heap.md +173 -179
  346. package/docs/integrations/hightouch.md +171 -181
  347. package/docs/integrations/hotjar.md +169 -179
  348. package/docs/integrations/intercom.md +193 -177
  349. package/docs/integrations/klaviyo.md +473 -0
  350. package/docs/integrations/linkedin-insights.md +184 -174
  351. package/docs/integrations/logrocket.md +170 -180
  352. package/docs/integrations/matomo-analytics.md +198 -202
  353. package/docs/integrations/meta-pixel.md +198 -174
  354. package/docs/integrations/microsoft-clarity.md +173 -179
  355. package/docs/integrations/microsoft-uet.md +158 -178
  356. package/docs/integrations/mixpanel-analytics.md +165 -184
  357. package/docs/integrations/one-dollar-stats.md +292 -0
  358. package/docs/integrations/openai-pixel.md +214 -325
  359. package/docs/integrations/overview.md +152 -83
  360. package/docs/integrations/pinterest-tag.md +315 -0
  361. package/docs/integrations/pirsch.md +179 -183
  362. package/docs/integrations/plausible-analytics.md +182 -182
  363. package/docs/integrations/posthog.md +323 -264
  364. package/docs/integrations/promptwatch.md +164 -178
  365. package/docs/integrations/reddit-pixel.md +195 -181
  366. package/docs/integrations/rudderstack.md +211 -210
  367. package/docs/integrations/rybbit-analytics.md +181 -184
  368. package/docs/integrations/segment.md +192 -178
  369. package/docs/integrations/sentry.md +402 -0
  370. package/docs/integrations/snapchat-pixel.md +196 -180
  371. package/docs/integrations/tiktok-pixel.md +181 -174
  372. package/docs/integrations/umami-analytics.md +173 -182
  373. package/docs/integrations/vercel-analytics.md +176 -181
  374. package/docs/integrations/x-pixel.md +186 -174
  375. package/docs/integrations/youtube.md +150 -111
  376. package/package.json +48 -17
  377. package/dist/component-hooks/use-manager.js +0 -2
  378. package/dist/components/frame/atoms.js +0 -1
  379. package/dist/components/frame/frame.js +0 -2
  380. package/dist/components/frame/index.js +0 -2
  381. package/dist/frame.js +0 -2
  382. package/dist/ui-save.js +0 -1
  383. package/dist-types/component-hooks/use-manager.d.ts +0 -40
  384. package/dist-types/components/frame/atoms.d.ts +0 -11
  385. package/dist-types/components/frame/frame.d.ts +0 -2
  386. package/dist-types/components/frame/index.d.ts +0 -24
  387. package/dist-types/frame.d.ts +0 -1
  388. package/dist-types/ui-save.d.ts +0 -5
  389. package/docs/assets/v3/brand-bar.png +0 -0
  390. package/docs/assets/v3/mobile-card.png +0 -0
  391. package/docs/assets/v3/preferences.png +0 -0
  392. package/docs/frameworks/react/components/consent-manager-provider.md +0 -71
  393. package/docs/frameworks/react/concepts/consent-categories.md +0 -33
  394. package/docs/frameworks/react/hooks/use-consent-manager/overview.md +0 -58
  395. package/docs/frameworks/react/iab/overview.md +0 -53
  396. package/docs/frameworks/react/script-loader.md +0 -63
  397. package/docs/frameworks/react/styling/overview.md +0 -217
  398. package/docs/guides/consent-state.md +0 -60
  399. package/docs/guides/data-fetching.md +0 -163
  400. package/docs/guides/deployment-modes.md +0 -63
  401. package/docs/integrations/clear-on-revocation.md +0 -167
  402. package/docs/upgrade-v3.md +0 -334
  403. package/readme.json +0 -48
  404. package/src/iab/styles.css +0 -11
  405. package/src/styles.css +0 -10
  406. /package/dist/components/{frame → consent-gate}/types.js +0 -0
@@ -0,0 +1,114 @@
1
+ ---
2
+ title: Scripts
3
+ description: Load vendor scripts by consent category in a React app with
4
+ ConsentProvider, and clear stored data or reload the page when a visitor
5
+ withdraws consent.
6
+ group: frameworks
7
+ ---
8
+
9
+ ## Register vendor scripts
10
+
11
+ Pass vendor loaders to `ConsentProvider` through `options.scripts`. The
12
+ provider loads each script when its category is allowed and removes it when
13
+ the category is denied. The [quickstart](./quickstart.md)
14
+ registers PostHog this way in `src/consent.tsx`:
15
+
16
+ ```tsx title="src/consent.tsx"
17
+ import { posthog } from '@c15t/integrations/posthog';
18
+ import {
19
+ ConsentBanner,
20
+ ConsentDialog,
21
+ ConsentDialogLink,
22
+ ConsentProvider,
23
+ manifest,
24
+ } from 'c15t/react';
25
+ import type { ReactNode } from 'react';
26
+
27
+ const options = {
28
+ // The policy the build downloaded from VITE_C15T_BACKEND_URL.
29
+ mode: manifest(),
30
+ scripts: [
31
+ posthog({
32
+ id: 'phc_your_project_key',
33
+ initOptions: { cookieless_mode: 'never' },
34
+ loadMode: 'after-consent',
35
+ }),
36
+ ],
37
+ };
38
+
39
+ export const Consent = ({ children }: { children: ReactNode }) => (
40
+ <ConsentProvider options={options}>
41
+ {children}
42
+ <ConsentBanner />
43
+ <ConsentDialog />
44
+ <footer>
45
+ <ConsentDialogLink>Privacy settings</ConsentDialogLink>
46
+ </footer>
47
+ </ConsentProvider>
48
+ );
49
+ ```
50
+
51
+ Each helper from `@c15t/integrations` sets its own category and a stable `id`.
52
+ Remove every other loader for the same vendor, such as a `<script>` tag in
53
+ `index.html` or an SDK you initialize at module level, so the vendor loads
54
+ once and only through c15t. [Integrations](../../integrations/overview.md) lists
55
+ every helper, and [building integrations](../../integrations/building-integrations.md)
56
+ covers a vendor without one.
57
+
58
+ ## What happens when consent changes
59
+
60
+ * **Allowed.** The script loads, or its SDK is started, the first time its
61
+ category is allowed.
62
+ * **Denied later.** The provider removes the script element. Code that already
63
+ ran keeps running, so after the visitor turns off a category they had
64
+ allowed, the provider reloads the page once the save finishes. Set
65
+ `reloadOnConsentRevoked: false` only if every gated vendor stops itself.
66
+ * **`alwaysLoad` helpers.** Some integrations, such as the Google Consent Mode
67
+ helpers by default, load before consent and pass the visitor's choice to the
68
+ vendor. Read the vendor's guide; a category on a script does not always mean
69
+ zero requests.
70
+
71
+ ## When the script loader downloads
72
+
73
+ The script loader is a separate chunk, downloaded only when `scripts` is not
74
+ empty. `ConsentProvider` loads it when it mounts. The Next.js and TanStack
75
+ Start `ConsentRoot` start the download earlier, during their first render,
76
+ when the visitor's consent already lets a script run.
77
+
78
+ ## Embeds and other requests
79
+
80
+ Scripts cover vendor code c15t loads for you. For the rest:
81
+
82
+ * [Embeds](./embeds.md) keeps iframes out of the page with
83
+ `ConsentGate` or the iframe blocker.
84
+ * [Network blocker](./network-blocker.md) holds `fetch` and
85
+ XHR calls that match a rule until their category is allowed.
86
+
87
+ ## Clear stored data after revocation
88
+
89
+ Removing a script does not delete the cookies or storage entries it wrote. Add
90
+ `clearOnRevocation` to the provider options to delete the entries you list for
91
+ each category when it is denied. The option is read once, when the provider
92
+ mounts. [Clear on revocation](./clear-on-revocation.md) covers
93
+ configuration and browser limits.
94
+
95
+ ## Let visitors turn off one vendor
96
+
97
+ A visitor can allow marketing and still switch off one vendor in it. Pass
98
+ `vendors` to the provider options. Helpers from `@c15t/integrations` already carry
99
+ their vendor slug. See [vendor consent](./vendor-consent.md).
100
+
101
+ To send your own events only to allowed integrations, see
102
+ [send events only to allowed integrations](../../integrations/overview.md#send-events-only-to-allowed-integrations).
103
+
104
+ ## Check the scripts
105
+
106
+ Open DevTools Network in a private window, filter by each vendor's domain and
107
+ reload.
108
+
109
+ 1. Before a choice under an opt-in policy, no vendor script loads.
110
+ 2. Allow one category. Only that category's vendors load.
111
+ 3. Turn the category off. The page reloads and the vendor stays absent.
112
+ 4. Reload again. The rejection holds.
113
+
114
+ [Verify consent](../../guides/verify-consent.md) has the full checklist.
@@ -0,0 +1,155 @@
1
+ ---
2
+ title: Translations
3
+ description: Where c15t banner and dialog copy comes from in a React app, how
4
+ the browser picks the visitor's language, and how to override copy and switch
5
+ languages with the provider's i18n option and hooks.
6
+ group: frameworks
7
+ ---
8
+
9
+ ## Where the copy comes from
10
+
11
+ The banner, dialog, widget and gate placeholder read their text from one set
12
+ of translations for the visitor's language. Which set depends on the
13
+ provider's `mode`:
14
+
15
+ | Mode | Copy comes from |
16
+ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
+ | `hosted()` | The backend's `/init` response for the visitor's language, from the translations in your Inth project or your self-hosted backend's configuration, with your `i18n` messages for that language on top |
18
+ | `offline()` | Your `i18n` messages, merged over bundled English |
19
+
20
+ With a backend, edit wording in your Inth project first, so it changes without
21
+ a deploy. Code can override that copy in two places:
22
+
23
+ * `i18n` in the `ConsentProvider` options changes a message everywhere it
24
+ appears.
25
+ * Text props on `ConsentBanner` change one banner.
26
+
27
+ [Copy and translations](../../customization/translations.md) lists the message
28
+ keys and explains how code messages combine with the project's copy.
29
+
30
+ ## How c15t picks the language
31
+
32
+ In `hosted()` mode the browser's `/init` request carries its own
33
+ `Accept-Language` header, and the backend answers with copy in that language.
34
+ When your project has no copy for it, the backend returns its fallback
35
+ language. Set `overrides.language` in the provider options to request a
36
+ specific language instead.
37
+
38
+ In `offline()` mode, `i18n.locale` picks the language, `en` by default. The
39
+ browser's language is not read.
40
+
41
+ The banner, dialog and widget set `dir` from the active language. Right-to-left
42
+ languages such as Arabic and Hebrew render with `dir="rtl"`, and a floating
43
+ banner you did not position yourself moves to the opposite side.
44
+
45
+ ## Change the copy in code
46
+
47
+ Keep the messages in their own module:
48
+
49
+ ```ts title="src/consent-i18n.ts"
50
+ import type { ConsentProviderOptions } from 'c15t/react';
51
+
52
+ // Keys you leave out keep the copy from your Inth project.
53
+ export const i18n = {
54
+ messages: {
55
+ de: {
56
+ common: { rejectAll: 'Optionale ablehnen' },
57
+ cookieBanner: { title: 'Cookies auf dieser Website' },
58
+ },
59
+ en: {
60
+ common: { rejectAll: 'Reject optional' },
61
+ cookieBanner: { title: 'Cookies on this site' },
62
+ },
63
+ },
64
+ } satisfies ConsentProviderOptions['i18n'];
65
+ ```
66
+
67
+ Pass them to the provider in the file that renders it, such as
68
+ `src/consent.tsx` from the [quickstart](./quickstart.md):
69
+
70
+ ```tsx title="src/consent.tsx"
71
+ <ConsentProvider options={{ mode, scripts, i18n }}>
72
+ ```
73
+
74
+ For the visitor's language, your messages replace the backend's copy key by
75
+ key. Keys you leave out keep the project's wording, and messages for other
76
+ languages are not applied. In `offline()` mode c15t bundles only English, so
77
+ keys you leave out for another language show in English.
78
+
79
+ The provider reads `i18n` once, when it mounts. In development it logs a
80
+ warning if `i18n` changes later. Define the object at module level, as above,
81
+ rather than inside a component.
82
+
83
+ ## Change one banner's copy
84
+
85
+ `ConsentBanner` takes `title`, `description`, `acceptButtonText`,
86
+ `rejectButtonText`, `customizeButtonText` and `dismissButtonText`. The props
87
+ replace the text in every language, so pass values in the page's language:
88
+
89
+ ```tsx
90
+ <ConsentBanner
91
+ title="Cookies on this site"
92
+ rejectButtonText="Reject optional"
93
+ />;
94
+ ```
95
+
96
+ ## Switch the language at runtime
97
+
98
+ `useSetLanguage()` stores the new language, and `useInit()` resolves the policy
99
+ again, which fetches the copy for that language. Call both from your language
100
+ switcher:
101
+
102
+ ```tsx title="src/language-switcher.tsx"
103
+ import { useInit, useSetLanguage, useSnapshot } from 'c15t/react';
104
+
105
+ const languages = [
106
+ { code: 'en', label: 'English' },
107
+ { code: 'de', label: 'Deutsch' },
108
+ ];
109
+
110
+ export const LanguageSwitcher = () => {
111
+ const setLanguage = useSetLanguage();
112
+ const init = useInit();
113
+ const language = useSnapshot().translations?.language ?? 'en';
114
+
115
+ return (
116
+ <select
117
+ aria-label="Consent language"
118
+ value={language}
119
+ onChange={(event) => {
120
+ setLanguage(event.target.value);
121
+ // Setting the language alone keeps the current copy. Init fetches
122
+ // the policy and copy for the new language.
123
+ void init();
124
+ }}
125
+ >
126
+ {languages.map(({ code, label }) => (
127
+ <option key={code} value={code}>
128
+ {label}
129
+ </option>
130
+ ))}
131
+ </select>
132
+ );
133
+ };
134
+ ```
135
+
136
+ Setting the language without calling `init()` changes nothing on screen. Your
137
+ `i18n` messages for the new language apply on top of the copy that arrives.
138
+ Render the switcher anywhere inside `ConsentProvider`.
139
+
140
+ Switching needs a backend. In `offline()` mode the copy stays in the
141
+ `i18n.locale` language.
142
+
143
+ If your site changes language through its own i18n library, you can instead
144
+ pass its locale as `overrides.language` in the provider options. When that
145
+ value changes, the provider resolves the policy again in the new language.
146
+
147
+ ## Verify
148
+
149
+ 1. Set your browser language to one your project translates, clear site data
150
+ and reload under a policy that shows a banner. DevTools Network shows the
151
+ `/init` request with that `Accept-Language` header, and the banner uses
152
+ that language.
153
+ 2. Check that a message you set in `i18n` shows in the banner.
154
+ 3. Switch the language with your switcher. A new `/init` request runs, and the
155
+ banner and dialog text change without a reload.
@@ -1,67 +1,194 @@
1
1
  ---
2
- title: Troubleshoot React consent
3
- description: Diagnose policy resolution, early scripts, storage and rendering problems.
2
+ title: Troubleshooting
3
+ description: Fix a missing banner, early vendor requests, unstyled components
4
+ and theme warnings in a React app that uses c15t/react.
4
5
  group: frameworks
5
6
  ---
6
7
 
7
- ## Why is there no banner?
8
+ ## Why does the build fail to download the manifest?
8
9
 
9
- Inspect `resolution` and `promptRequirement` before changing styles. Pending or
10
- failed initialization, no matching rule, a valid stored choice and a rule that
11
- requires no prompt can all produce no banner for different reasons. A missing
12
- stylesheet can also make rendered controls appear incorrectly.
10
+ **Check.** `vite build` stops with an error from `consentManifest` that
11
+ starts with the plugin's name, such as
12
+ `@c15t/core/build: could not fetch the consent manifest from <url> during the
13
+ build`. The name is `@c15t/core/build` for `c15t/build` and `@c15t/vue/vite`
14
+ for `c15t/vue/vite`. `vite dev` logs the same message as a warning and keeps
15
+ going. The part in parentheses names the cause:
13
16
 
14
- Check the backend URL and Network response, then confirm the active policy for
15
- the visitor's location. Do not solve missing UI by granting every category or
16
- setting `enabled: false`: disabling the runtime permits optional loading.
17
-
18
- ## Why does the UI disappear with a content blocker?
19
-
20
- Check the browser Network panel for `ERR_BLOCKED_BY_CLIENT` or a failed dynamic
21
- import. Older c15t builds used component filenames such as
22
- `consent-dialog-*.js`, which some cookie-annoyance lists block. Update the c15t
23
- packages and rebuild the app. Current component modules use neutral filenames;
24
- public component imports stay the same. This also covers Vite development
25
- requests used by TanStack Start and other Vite integrations.
26
-
27
- Extensions can separately hide elements with cosmetic filters or block a
28
- configured backend URL. Check the failed request or hidden element to distinguish
29
- those cases from a missing component module.
30
-
31
- ## Why does analytics run before a choice?
32
-
33
- Check effective permission under the selected policy, then find every loader
34
- for that vendor. Remove unconditional script tags, framework analytics plugins
35
- and duplicate tag-manager entries. c15t's script registration only controls the
36
- scripts registered with it.
37
-
38
- Google helpers intentionally load with Consent Mode defaults. A Google request
39
- is not by itself proof that its storage consent was granted. If your requirement
40
- is no request at all, do not use an always-loaded helper unchanged.
41
-
42
- ## Why does a choice disappear on reload?
43
-
44
- Check whether persistence is disabled, browser storage is blocked, the origin
45
- changed, or the receipt expired or no longer matches the current policy.
46
- A development example with `persistence: false` deliberately resets on reload.
47
- Do not "repair" persistence by saving permissions automatically on mount.
48
-
49
- ## Why does hydration differ from server HTML?
50
-
51
- Use the adapter's request helper and pass the returned configuration unchanged
52
- to its boundary. Check that server and browser use the same backend and policy
53
- inputs. A module-level mutable runtime on a server can share one visitor's state
54
- with another request; create request-owned state instead.
55
-
56
- ## Why does static hosting fail when development works?
57
-
58
- A static host has no app server for init routes, proxies or server functions.
59
- Use absolute external consent URLs or an explicitly local policy. Test the
60
- production output with a static file server, not the framework dev server.
61
-
62
- ## Why does customization do nothing?
63
-
64
- Check the imported stylesheet, the correct token or slot, and which element
65
- carries the state attribute. `data-variant` on a banner root is not a matching
66
- attribute on its child card. Check cascade layers and the Tailwind version
67
- before adding specificity. See [customization](../../customization/overview.md).
17
+ | Message | Cause | Fix |
18
+ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
19
+ | `fetch failed`, with `ENOTFOUND`, `ECONNREFUSED` or another network error | The build cannot reach the backend | Build where the backend is reachable |
20
+ | `no response within 10 seconds` | The backend did not answer in time | Check the backend, or build where it is reachable |
21
+ | `/manifest responded 404` | The URL is not your project's backend, such as the `https://your-project.inth.app` placeholder or a URL missing its path prefix | Copy the backend URL exactly as Inth shows it, or set `VITE_C15T_BACKEND_URL` |
22
+ | `/manifest returned an invalid consent manifest.` | The URL answered with something other than a consent manifest, such as an HTML page | Point `backendURL` at the backend itself, not your site or a dashboard page |
23
+
24
+ A failed download never reuses an old snapshot. To deploy while the backend
25
+ is down, run the build with `C15T_ON_BUILD_ERROR=runtime`. `snapshot` is then
26
+ `undefined`, and the browser fetches the policy from the backend at runtime.
27
+
28
+ Only a build that uses `manifest()` downloads the manifest. The plugin
29
+ fetches after Vite has dropped the code the app does not use, so a `hosted()`
30
+ or `offline()` build never contacts the backend and never fails this way.
31
+
32
+ An error or warning that says `no backend URL is set` means the plugin found
33
+ no `backendURL` option and no variable. Set `VITE_C15T_BACKEND_URL` (or
34
+ `VITE_INTH_PROJECT_URL`) in `.env` or the build environment, or pass the absolute backend URL from your Inth
35
+ project. The [troubleshooting guide](../../guides/troubleshooting.md#why-does-the-build-fail-to-download-the-manifest)
36
+ lists every message.
37
+
38
+ A notice that the build `skipped the consent manifest fetch` means the backend
39
+ URL is relative, such as `/api/c15t`. Pass the absolute backend URL instead.
40
+ With `onBuildError: 'fail'`, this stops the build with `build-time manifests
41
+ require an absolute upstream URL`.
42
+
43
+ ## Why is snapshot undefined?
44
+
45
+ **Check.** `snapshot` from `c15t/generated` is `undefined`, and the browser
46
+ requests `${backendURL}/manifest` on page load.
47
+
48
+ **Fix.** `snapshot` is `undefined` when Vite has no policy to serve:
49
+
50
+ * `consentManifest` is missing from `plugins` in `vite.config.ts`. Without the
51
+ plugin, `c15t/generated` still resolves, but exports `undefined`.
52
+ * The fetch failed in `vite dev`, or in a build with
53
+ `C15T_ON_BUILD_ERROR=runtime`. The terminal shows a `could not fetch the
54
+ consent manifest` warning.
55
+ * The backend URL is relative, so the plugin skipped the fetch.
56
+ * `consentManifest({ source: 'runtime' })` is set, so the plugin never
57
+ fetches.
58
+
59
+ Fix the cause, then restart `vite dev` or rebuild. The plugin fetches once
60
+ when Vite starts.
61
+
62
+ ## There is no banner
63
+
64
+ **Check.** In DevTools Network, find the `GET` request to `/init` on your
65
+ backend URL. With the bundled manifest, the browser makes no request before
66
+ the banner unless the policy depends on a country or region it does not know.
67
+
68
+ | What you see | Cause | Fix |
69
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
70
+ | No request and no banner | `ConsentProvider` is not mounted, an error stopped `src/consent.tsx` from rendering, or the bundled policy asks for no banner | Check the console for errors, render one provider at the app root as in the [quickstart](./quickstart.md), and inspect the active policy with the component below |
71
+ | `/init` fails with a CORS error | Your site's origin is not trusted | Add the exact origin, including port in development, to the trusted origins in your Inth project |
72
+ | `/init` returns 200 | The policy for this visitor asks for no banner, or a stored choice is still valid | Inspect the active policy with the component below, or clear site data |
73
+
74
+ A policy with `prompt: 'none'` shows no banner by design, and so does a
75
+ returning visitor with a valid stored choice. [Policies](../../concepts/policies.md)
76
+ explains why a region may not show one.
77
+
78
+ ## The page throws that no IABProvider is mounted
79
+
80
+ The visitor's policy uses the `iab` model and the backend sent its vendor
81
+ list, but no `IABProvider` is mounted. The standard banner and dialog do
82
+ not handle the IAB model, so they throw rather than leave the visitor
83
+ with no consent UI. Server and browser render the same error.
84
+
85
+ Fix it one of two ways:
86
+
87
+ * If the site uses IAB TCF, render `IABProvider` with `IABConsentBanner`
88
+ and `IABConsentDialog` from `c15t/react/iab` inside your consent
89
+ provider. They can sit next to the standard banner.
90
+ * If it does not, remove the `iab` model from the policy for that region
91
+ in your Inth project or policy pack.
92
+
93
+ A backend that answers `gvl: null` turns IAB off for that request. The
94
+ policy then runs as opt-in and nothing throws.
95
+
96
+ The check passes once `c15t/react/iab` has loaded. If you import the IAB
97
+ components with a dynamic `import()`, a render of the standard banner
98
+ that happens before the import finishes still throws.
99
+
100
+ ## Inspect the active policy
101
+
102
+ Render this component inside `ConsentProvider`. It reads state and records no
103
+ choice:
104
+
105
+ ```tsx title="src/consent-policy-debug.tsx"
106
+ import { useSnapshot } from 'c15t/react';
107
+
108
+ export function ConsentPolicyDebug() {
109
+ const snapshot = useSnapshot();
110
+ const resolution = snapshot.resolution;
111
+
112
+ return (
113
+ <pre>
114
+ {JSON.stringify(
115
+ {
116
+ status: resolution.status,
117
+ policy: resolution.status === 'matched' ? resolution.policy.id : null,
118
+ prompt: snapshot.promptRequirement,
119
+ permissions: snapshot.effectivePermissions,
120
+ location: snapshot.location,
121
+ privacySignals: snapshot.privacySignals,
122
+ },
123
+ null,
124
+ 2
125
+ )}
126
+ </pre>
127
+ );
128
+ }
129
+ ```
130
+
131
+ The component re-renders on every consent change. Remove it after you finish.
132
+ For a feature gate, use `useConsent('marketing')` or the category you need.
133
+
134
+ ## A vendor loads before the visitor chooses
135
+
136
+ **Check.** Search `index.html`, your entry module and any tag manager for the
137
+ vendor's script or SDK initializer.
138
+
139
+ **Fix.** Remove every loader except the one in `options.scripts`. c15t only
140
+ gates scripts registered with it, and the network blocker cannot stop code that
141
+ runs before the provider renders. [Scripts and embeds](./scripts.md)
142
+ covers the options.
143
+
144
+ ## The banner has no styles
145
+
146
+ **Check.** In DevTools Elements, the banner has classes but no rules apply.
147
+ Look for c15t's `<style>` element: `<style data-href="c15t-first-paint">` in
148
+ `<head>` on React 19, or `<style data-c15t-styles>` next to the banner on
149
+ React 18 or with a `nonce`. Check the console for a Content Security Policy
150
+ error.
151
+
152
+ **Fix.**
153
+
154
+ * No c15t `<style>` element: the provider sets `styles: false` or `noStyle`.
155
+ With `styles: false`, import `c15t/react/styles.css` once in the module
156
+ that renders the provider.
157
+ * The console reports a blocked inline style: set the provider's `nonce`, as
158
+ [Content Security Policy](./content-security-policy.md)
159
+ shows.
160
+ * Under Tailwind 3, buttons lose their padding and cards their borders:
161
+ Tailwind 3's unlayered preflight beats c15t's layered rules. Set
162
+ `styles: false`, import `c15t/react/styles.css` above the `@tailwind`
163
+ directives and add `c15t/postcss-tailwind3` before `tailwindcss` in your
164
+ PostCSS config. Without the plugin, Tailwind 3 drops c15t's rules or fails
165
+ the build with
166
+ `` `@layer components` is used but no matching `@tailwind components` directive is present ``.
167
+ See [Tailwind CSS](../../customization/tailwind.md#set-up-tailwind-css-3).
168
+
169
+ ## The console warns that theme tokens are no longer turned into CSS
170
+
171
+ **Check.** `options.theme` holds colors, radius or other tokens, and the page
172
+ has no `c15t-theme` style element. The provider only reads `consentActions`
173
+ and slot styles from `theme`.
174
+
175
+ **Fix.** Move the tokens to your CSS or render `ConsentTheme`, as shown in
176
+ [customize](./customize.md#change-colors-fonts-and-radius).
177
+
178
+ ## The banner is missing from server-rendered HTML
179
+
180
+ **Check.** Your app uses React Router framework mode, Remix or another
181
+ server-rendered setup without a c15t adapter. There this is expected: the
182
+ browser resolves consent after hydration.
183
+
184
+ **Fix.** None is needed for consent to work.
185
+ [Rendering](./rendering.md#react-router-remix-and-other-server-rendered-apps)
186
+ explains the options.
187
+
188
+ ## More help
189
+
190
+ [Troubleshoot consent](../../guides/troubleshooting.md) covers problems shared by
191
+ every framework, such as a missing banner, analytics that load before a choice,
192
+ imports that fail because npm installed c15t v2, choices that disappear on
193
+ reload, server HTML that differs from the browser, static builds that fail and
194
+ content blockers that hide the consent UI.