@c15t/nextjs 2.1.0 → 2.2.1
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 +155 -0
- package/README.md +31 -15
- package/client/components/integrations.js +3 -0
- package/dist/components/integrations/index.cjs +1 -0
- package/dist/components/integrations/index.js +1 -0
- package/dist/headless.cjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/libs/browser-initial-data.cjs +1 -1
- package/dist/libs/initial-data.cjs +1 -1
- package/dist/styles.tw3.css +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist-types/components/integrations/index.d.ts +1 -0
- package/dist-types/libs/browser-initial-data.d.ts +1 -1
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +155 -73
- package/docs/{building-headless-components.md → frameworks/next/building-headless-components.md} +3 -1
- package/docs/{callbacks.md → frameworks/next/callbacks.md} +3 -1
- package/docs/{components → frameworks/next/components}/consent-banner.md +10 -21
- package/docs/{components → frameworks/next/components}/consent-dialog-link.md +8 -5
- package/docs/frameworks/next/components/consent-dialog-trigger.md +202 -0
- package/docs/{components → frameworks/next/components}/consent-dialog.md +7 -15
- package/docs/frameworks/next/components/consent-manager-provider.md +327 -0
- package/docs/{components → frameworks/next/components}/consent-widget.md +8 -6
- package/docs/{components → frameworks/next/components}/dev-tools.md +9 -6
- package/docs/{components → frameworks/next/components}/frame.md +8 -9
- package/docs/{concepts → frameworks/next/concepts}/client-modes.md +4 -2
- package/docs/{concepts → frameworks/next/concepts}/consent-categories.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/consent-models.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/cookie-management.md +3 -3
- package/docs/{concepts → frameworks/next/concepts}/glossary.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/initialization-flow.md +1 -0
- package/docs/{concepts → frameworks/next/concepts}/policy-packs.md +1 -0
- package/docs/{headless.md → frameworks/next/headless.md} +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-color-scheme.md +1 -0
- package/docs/{hooks → frameworks/next/hooks}/use-consent-manager/checking-consent.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-consent-manager/location-info.md +3 -1
- package/docs/frameworks/next/hooks/use-consent-manager/overview.md +185 -0
- package/docs/{hooks → frameworks/next/hooks}/use-consent-manager/setting-consent.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-draggable.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-focus-trap.md +1 -0
- package/docs/{hooks → frameworks/next/hooks}/use-reduced-motion.md +3 -1
- package/docs/{hooks → frameworks/next/hooks}/use-ssr-status.md +6 -5
- package/docs/{hooks → frameworks/next/hooks}/use-text-direction.md +1 -0
- package/docs/frameworks/next/hooks/use-translations.md +55 -0
- package/docs/{iab → frameworks/next/iab}/consent-banner.md +9 -12
- package/docs/{iab → frameworks/next/iab}/consent-dialog.md +9 -14
- package/docs/{iab → frameworks/next/iab}/overview.md +4 -2
- package/docs/{iab → frameworks/next/iab}/use-gvl-data.md +3 -2
- package/docs/{iframe-blocking.md → frameworks/next/iframe-blocking.md} +8 -9
- package/docs/{internationalization.md → frameworks/next/internationalization.md} +13 -3
- package/docs/{network-blocker.md → frameworks/next/network-blocker.md} +13 -51
- package/docs/{optimization.md → frameworks/next/optimization.md} +5 -4
- package/docs/{policy-packs.md → frameworks/next/policy-packs.md} +3 -1
- package/docs/{quickstart.md → frameworks/next/quickstart.md} +26 -42
- package/docs/{script-loader.md → frameworks/next/script-loader.md} +72 -90
- package/docs/{server-side.md → frameworks/next/server-side.md} +12 -15
- package/docs/{styling → frameworks/next/styling}/classnames.md +3 -1
- package/docs/{styling → frameworks/next/styling}/color-scheme.md +3 -1
- package/docs/frameworks/next/styling/css-variables.md +53 -0
- package/docs/frameworks/next/styling/overview.md +299 -0
- package/docs/frameworks/next/styling/slots.md +94 -0
- package/docs/{styling → frameworks/next/styling}/tailwind.md +3 -1
- package/docs/frameworks/next/styling/tokens.md +156 -0
- package/docs/{troubleshooting.md → frameworks/next/troubleshooting.md} +3 -1
- package/docs/integrations/adobe-analytics.md +160 -0
- package/docs/integrations/ahrefs-analytics.md +15 -82
- package/docs/integrations/amplitude.md +230 -0
- package/docs/integrations/building-integrations.md +15 -181
- package/docs/integrations/clearbit.md +130 -0
- package/docs/integrations/cloudflare-web-analytics.md +15 -83
- package/docs/integrations/crisp.md +13 -87
- package/docs/integrations/databuddy.md +16 -85
- package/docs/integrations/fathom-analytics.md +15 -86
- package/docs/integrations/google-maps.md +263 -0
- package/docs/integrations/google-tag-manager.md +18 -86
- package/docs/integrations/google-tag.md +15 -84
- package/docs/integrations/heap.md +219 -0
- package/docs/integrations/hightouch.md +199 -0
- package/docs/integrations/hotjar.md +15 -83
- package/docs/integrations/intercom.md +13 -83
- package/docs/integrations/linkedin-insights.md +15 -82
- package/docs/integrations/logrocket.md +175 -0
- package/docs/integrations/matomo-analytics.md +13 -88
- package/docs/integrations/meta-pixel.md +33 -316
- package/docs/integrations/microsoft-clarity.md +15 -83
- package/docs/integrations/microsoft-uet.md +16 -83
- package/docs/integrations/mixpanel-analytics.md +15 -83
- package/docs/integrations/overview.md +55 -6
- package/docs/integrations/pirsch.md +142 -0
- package/docs/integrations/plausible-analytics.md +14 -97
- package/docs/integrations/posthog.md +26 -98
- package/docs/integrations/promptwatch.md +16 -82
- package/docs/integrations/reddit-pixel.md +27 -122
- package/docs/integrations/rudderstack.md +271 -0
- package/docs/integrations/rybbit-analytics.md +15 -94
- package/docs/integrations/segment.md +15 -82
- package/docs/integrations/snapchat-pixel.md +21 -102
- package/docs/integrations/tiktok-pixel.md +13 -81
- package/docs/integrations/umami-analytics.md +16 -88
- package/docs/integrations/vercel-analytics.md +13 -85
- package/docs/integrations/x-pixel.md +27 -102
- package/docs/integrations/youtube.md +193 -0
- package/docs/shared/concepts/client-modes.md +103 -0
- package/docs/shared/concepts/consent-categories.md +41 -0
- package/docs/shared/concepts/consent-models.md +72 -0
- package/docs/shared/concepts/cookie-management.md +88 -0
- package/docs/shared/concepts/glossary.md +24 -0
- package/docs/shared/concepts/initialization-flow.md +105 -0
- package/docs/shared/concepts/policy-packs.md +225 -0
- package/docs/shared/react/components/consent-banner.md +242 -0
- package/docs/shared/react/components/consent-dialog-link.md +45 -0
- package/docs/shared/react/components/consent-dialog-trigger.md +185 -0
- package/docs/shared/react/components/consent-dialog.md +119 -0
- package/docs/shared/react/components/consent-manager-provider.md +225 -0
- package/docs/shared/react/components/consent-widget.md +121 -0
- package/docs/shared/react/components/dev-tools.md +81 -0
- package/docs/shared/react/components/frame.md +52 -0
- package/docs/shared/react/guides/building-headless-components.md +110 -0
- package/docs/shared/react/guides/callbacks.md +89 -0
- package/docs/shared/react/guides/headless.md +31 -0
- package/docs/shared/react/guides/iframe-blocking.md +65 -0
- package/docs/shared/react/guides/internationalization.md +123 -0
- package/docs/shared/react/guides/network-blocker.md +72 -0
- package/docs/shared/react/guides/optimization.md +44 -0
- package/docs/shared/react/guides/policy-packs.md +173 -0
- package/docs/shared/react/guides/script-loader.md +311 -0
- package/docs/shared/react/hooks/use-color-scheme.md +31 -0
- package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +95 -0
- package/docs/shared/react/hooks/use-consent-manager/location-info.md +96 -0
- package/docs/shared/react/hooks/use-consent-manager/overview.md +74 -0
- package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +93 -0
- package/docs/shared/react/hooks/use-draggable.md +30 -0
- package/docs/shared/react/hooks/use-focus-trap.md +20 -0
- package/docs/shared/react/hooks/use-reduced-motion.md +33 -0
- package/docs/shared/react/hooks/use-ssr-status.md +16 -0
- package/docs/shared/react/hooks/use-text-direction.md +38 -0
- package/docs/shared/react/hooks/use-translations.md +15 -0
- package/docs/shared/react/iab/consent-banner.md +60 -0
- package/docs/shared/react/iab/consent-dialog.md +76 -0
- package/docs/shared/react/iab/overview.md +80 -0
- package/docs/shared/react/iab/use-gvl-data.md +21 -0
- package/docs/shared/react/styling/classnames.md +93 -0
- package/docs/shared/react/styling/color-scheme.md +35 -0
- package/docs/shared/react/styling/css-variables.md +53 -0
- package/docs/shared/react/styling/overview.md +261 -0
- package/docs/shared/react/styling/slots.md +93 -0
- package/docs/shared/react/styling/stylesheet-entrypoint.md +8 -0
- package/docs/shared/react/styling/tailwind.md +88 -0
- package/docs/shared/react/styling/tokens.md +155 -0
- package/docs/shared/troubleshooting.md +82 -0
- package/package.json +19 -10
- package/readme.json +14 -8
- package/docs/ai-agents.md +0 -111
- package/docs/components/consent-dialog-trigger.md +0 -103
- package/docs/components/consent-manager-provider.md +0 -425
- package/docs/hooks/use-consent-manager/overview.md +0 -420
- package/docs/hooks/use-translations.md +0 -118
- package/docs/styling/css-variables.md +0 -92
- package/docs/styling/overview.md +0 -457
- package/docs/styling/slots.md +0 -128
- package/docs/styling/tokens.md +0 -216
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Classnames
|
|
3
|
+
description: Reference page for classnames.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
## Prefer Slots for Stock Components
|
|
7
|
+
|
|
8
|
+
There is no single top-level `className` contract across every pre-built consent component.
|
|
9
|
+
|
|
10
|
+
For the stock `ConsentBanner`, `ConsentDialog`, and `ConsentWidget`, prefer `theme.slots` first. That keeps the markup intact and lets you target the exact part you need.
|
|
11
|
+
|
|
12
|
+
## Per-Slot className
|
|
13
|
+
|
|
14
|
+
Target individual component parts via the theme's `slots` object. Each slot accepts a string (className) or an object with `className` and `style`:
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
const theme = {
|
|
18
|
+
slots: {
|
|
19
|
+
consentBannerTitle: 'text-xl font-semibold',
|
|
20
|
+
consentBannerDescription: 'text-sm text-gray-600',
|
|
21
|
+
consentBannerFooter: 'flex gap-3',
|
|
22
|
+
buttonPrimary: 'rounded-full px-6',
|
|
23
|
+
},
|
|
24
|
+
} satisfies Theme;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Combining with CSS Modules
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import styles from './consent.module.css';
|
|
31
|
+
|
|
32
|
+
const theme = {
|
|
33
|
+
slots: {
|
|
34
|
+
consentBannerCard: styles.bannerCard,
|
|
35
|
+
consentBannerTitle: styles.bannerTitle,
|
|
36
|
+
buttonPrimary: styles.primaryButton,
|
|
37
|
+
},
|
|
38
|
+
} satisfies Theme;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```css title="consent.module.css"
|
|
42
|
+
.bannerCard {
|
|
43
|
+
backdrop-filter: blur(12px);
|
|
44
|
+
background: rgba(255, 255, 255, 0.9);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.bannerTitle {
|
|
48
|
+
font-size: 1.25rem;
|
|
49
|
+
font-weight: 700;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.primaryButton {
|
|
53
|
+
border-radius: 9999px;
|
|
54
|
+
text-transform: uppercase;
|
|
55
|
+
letter-spacing: 0.05em;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## When to Use Raw className
|
|
60
|
+
|
|
61
|
+
Use raw className-level styling when:
|
|
62
|
+
|
|
63
|
+
* your styling system is already class-driven
|
|
64
|
+
* tokens are too broad for the change
|
|
65
|
+
* slots already identify the correct element
|
|
66
|
+
|
|
67
|
+
If the request is "make the banner footer darker", prefer `theme.colors.surfaceHover` first. If the request is "add a border and spacing only to the footer", prefer `theme.slots.consentBannerFooter`.
|
|
68
|
+
|
|
69
|
+
## Advanced: `noStyle`
|
|
70
|
+
|
|
71
|
+
Use `noStyle` only when you want to remove defaults and style from scratch while still keeping c15t's component structure:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
{/* Remove all styles from a specific component */}
|
|
75
|
+
<ConsentBanner noStyle />
|
|
76
|
+
|
|
77
|
+
{/* Remove all styles globally */}
|
|
78
|
+
<ConsentManagerProvider options={{ noStyle: true, ... }}>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
You can also set `noStyle` per-slot:
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
const theme = {
|
|
85
|
+
slots: {
|
|
86
|
+
consentBannerCard: { noStyle: true, className: 'my-custom-card' },
|
|
87
|
+
},
|
|
88
|
+
} satisfies Theme;
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Treat `noStyle` as an advanced escape hatch. Do not jump to it just because a token or slot needs debugging.
|
|
92
|
+
|
|
93
|
+
For full custom markup and behavior, continue to [Headless Mode](../headless).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Color Scheme
|
|
3
|
+
description: Reference page for color scheme.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
c15t supports light and dark mode through the theme's `colors` and `dark` token groups. The active color scheme is determined by one of three methods:
|
|
7
|
+
|
|
8
|
+
1. **Explicit setting** via the `colorScheme` option
|
|
9
|
+
2. **CSS class detection** - c15t checks for `.dark` on the document element
|
|
10
|
+
3. **System preference** - matches `prefers-color-scheme` media query
|
|
11
|
+
|
|
12
|
+
|Value|Behavior|
|
|
13
|
+
|--|--|
|
|
14
|
+
|`'light'`|Force light mode|
|
|
15
|
+
|`'dark'`|Force dark mode|
|
|
16
|
+
|`'system'`|Follow `prefers-color-scheme` media query|
|
|
17
|
+
|`null`|Disable - c15t won't manage color scheme|
|
|
18
|
+
|
|
19
|
+
## How Dark Mode Works
|
|
20
|
+
|
|
21
|
+
When dark mode is active, c15t applies the `dark` token values as CSS variable overrides. Only tokens specified in `dark` are overridden - unset tokens fall back to the `colors` values. This also applies to `textOnPrimary`: if you omit it, c15t derives a readable foreground from the active `primary` color in that scheme.
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
const theme = {
|
|
25
|
+
colors: {
|
|
26
|
+
surface: '#ffffff', // Light mode
|
|
27
|
+
text: '#1f2937', // Light mode
|
|
28
|
+
},
|
|
29
|
+
dark: {
|
|
30
|
+
surface: '#1f2937', // Dark mode override
|
|
31
|
+
text: '#f9fafb', // Dark mode override
|
|
32
|
+
// primary is NOT set - inherits from colors.primary
|
|
33
|
+
},
|
|
34
|
+
} satisfies Theme;
|
|
35
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CSS Variables
|
|
3
|
+
description: Reference page for css variables.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
Every theme token is converted to a `--c15t-*` CSS custom property at runtime. You can override these variables in your stylesheet without using the JavaScript theme API.
|
|
7
|
+
|
|
8
|
+
## Variable Reference
|
|
9
|
+
|
|
10
|
+
|Property|Value|
|
|
11
|
+
|:--|:--|
|
|
12
|
+
|Type Name|\`ThemeCSSVariables\`|
|
|
13
|
+
|Source Path|\`./packages/ui/src/theme/types.ts\`|
|
|
14
|
+
|
|
15
|
+
\*ExtractedTypeTable: Could not extract "ThemeCSSVariables" from "./packages/ui/src/theme/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
16
|
+
|
|
17
|
+
## Overriding Variables
|
|
18
|
+
|
|
19
|
+
Override in your stylesheet:
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
:root {
|
|
23
|
+
--c15t-primary: #8b5cf6;
|
|
24
|
+
--c15t-surface: #fafafa;
|
|
25
|
+
--c15t-radius-md: 1rem;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Dark mode overrides */
|
|
29
|
+
.dark,
|
|
30
|
+
.c15t-dark {
|
|
31
|
+
--c15t-primary: #a78bfa;
|
|
32
|
+
--c15t-surface: #18181b;
|
|
33
|
+
--c15t-text: #fafafa;
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Scoped Overrides
|
|
38
|
+
|
|
39
|
+
Target specific components by scoping variables:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<div className="checkout-consent">
|
|
43
|
+
<ConsentBanner />
|
|
44
|
+
</div>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```css
|
|
48
|
+
/* Only affect c15t components inside .checkout-consent */
|
|
49
|
+
.checkout-consent {
|
|
50
|
+
--c15t-surface: #f0f9ff;
|
|
51
|
+
--c15t-radius-lg: 1.5rem;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Overview
|
|
3
|
+
description: Reference page for overview.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
c15t's theming system gives you multiple levels of control, but most customization should stay inside the pre-built components.
|
|
7
|
+
|
|
8
|
+
Start with the lowest-power tool that solves the problem:
|
|
9
|
+
|
|
10
|
+
1. **Pre-built component APIs** — provider options and component props such as `layout`, `direction`, `primaryButton`, `legalLinks`, and `theme.consentActions`
|
|
11
|
+
2. **Design tokens** — global colors, typography, spacing, radius, shadows, and motion
|
|
12
|
+
3. **Slots** — targeted styling for specific parts such as the banner card, footer, or title
|
|
13
|
+
4. **CSS variables or className-level overrides** — when you need to integrate with external CSS systems
|
|
14
|
+
5. **Compound components** — when you must rearrange markup while still using c15t primitives
|
|
15
|
+
6. **`noStyle`** — when you want c15t structure but you need to own all visual styling
|
|
16
|
+
7. **Headless** — when you want fully custom markup and behavior
|
|
17
|
+
|
|
18
|
+
Keep styling and escalation as separate decisions:
|
|
19
|
+
|
|
20
|
+
* If you are still using the stock banner, dialog, or widget, stay with props, tokens, and slots.
|
|
21
|
+
* Escalate to compound components, `noStyle`, or headless only when the structure or behavior itself must change.
|
|
22
|
+
|
|
23
|
+
## Styling Approaches
|
|
24
|
+
|
|
25
|
+
|Approach|Control|Use When|
|
|
26
|
+
|--|--|--|
|
|
27
|
+
|**Component and provider APIs**|High|Reordering actions, changing button emphasis, configuring links, hiding branding, changing copy via `i18n`|
|
|
28
|
+
|**Tokens**|High|Changing global colors, typography, spacing, radius, shadows, or motion|
|
|
29
|
+
|**Slots**|Medium|Targeting specific component parts (for example `consentBannerFooter` or `consentDialogCard`)|
|
|
30
|
+
|**CSS variables / className**|Medium|Integrating with an existing stylesheet or utility classes after tokens and slots|
|
|
31
|
+
|**Compound components**|Structure|Rearranging existing c15t primitives without going fully custom|
|
|
32
|
+
|**noStyle**|Full visuals|Keeping c15t structure but replacing all visual defaults|
|
|
33
|
+
|**Headless**|Full|Replacing both markup and behavior|
|
|
34
|
+
|
|
35
|
+
## Styling Inside Pre-Built Components
|
|
36
|
+
|
|
37
|
+
Start here before you consider compound components or headless mode.
|
|
38
|
+
|
|
39
|
+
### 1. Provider and component configuration
|
|
40
|
+
|
|
41
|
+
Use the stock APIs first:
|
|
42
|
+
|
|
43
|
+
* `layout`, `direction`, and `primaryButton` for banner action arrangement
|
|
44
|
+
* `legalLinks` for link visibility
|
|
45
|
+
* `hideBranding` and `showTrigger` for dialog and widget behavior
|
|
46
|
+
* `theme.consentActions` for stock banner and dialog button treatment
|
|
47
|
+
* `i18n` on `ConsentManagerProvider` for copy changes
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<ConsentBanner layout={['customize', ['reject', 'accept']]} primaryButton="accept" />
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Design tokens
|
|
54
|
+
|
|
55
|
+
Set global values for colors, typography, spacing, radius, shadows, and motion:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
options={{ theme: { colors: { primary: '#6366f1' } } }}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Use tokens first when the change is semantic:
|
|
62
|
+
|
|
63
|
+
* Banner card background -> `theme.colors.surface`
|
|
64
|
+
* Banner footer background -> `theme.colors.surfaceHover`
|
|
65
|
+
* Shared copy color -> `theme.colors.text` and `theme.colors.textMuted`
|
|
66
|
+
* Primary-filled surfaces such as stock branding tags and filled actions -> `theme.colors.primary` with `theme.colors.textOnPrimary` as the matching foreground override
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
options={{
|
|
70
|
+
theme: {
|
|
71
|
+
colors: {
|
|
72
|
+
surface: '#ffffff',
|
|
73
|
+
surfaceHover: '#f6f3ee',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
}}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If you set `theme.colors.primary` but omit `theme.colors.textOnPrimary`, c15t derives a readable foreground automatically. Add `textOnPrimary` only when you need to force a specific branded foreground color.
|
|
80
|
+
|
|
81
|
+
### 3. Component slots
|
|
82
|
+
|
|
83
|
+
Target specific component parts via the `slots` object:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
options={{
|
|
87
|
+
theme: {
|
|
88
|
+
slots: {
|
|
89
|
+
consentBannerCard: 'rounded-[28px] shadow-xl',
|
|
90
|
+
consentBannerFooter: 'border-t border-black/10',
|
|
91
|
+
consentBannerTitle: 'tracking-tight',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
}}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Use slots when the component part is right but the local styling needs adjustment.
|
|
98
|
+
|
|
99
|
+
### 4. CSS variables and className-level overrides
|
|
100
|
+
|
|
101
|
+
Override `--c15t-*` custom properties in your stylesheet or attach classes through slots when your app styling is driven externally.
|
|
102
|
+
|
|
103
|
+
Reach for this after tokens and slots, not before.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
options={{
|
|
107
|
+
theme: {
|
|
108
|
+
slots: {
|
|
109
|
+
consentBannerFooter: 'bg-[var(--banner-footer)]',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
}}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Escalating Beyond Pre-Built Components
|
|
116
|
+
|
|
117
|
+
Only move up this ladder when the lower rung cannot satisfy the request.
|
|
118
|
+
|
|
119
|
+
### 5. Compound components
|
|
120
|
+
|
|
121
|
+
Use compound components when you need to rearrange existing c15t primitives:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
<ConsentBanner.Root>
|
|
125
|
+
<ConsentBanner.Card>
|
|
126
|
+
<ConsentBanner.Header>
|
|
127
|
+
<ConsentBanner.Title />
|
|
128
|
+
<ConsentBanner.Description />
|
|
129
|
+
</ConsentBanner.Header>
|
|
130
|
+
<ConsentBanner.Footer>
|
|
131
|
+
<ConsentBanner.CustomizeButton />
|
|
132
|
+
<ConsentBanner.FooterSubGroup>
|
|
133
|
+
<ConsentBanner.RejectButton />
|
|
134
|
+
<ConsentBanner.AcceptButton />
|
|
135
|
+
</ConsentBanner.FooterSubGroup>
|
|
136
|
+
</ConsentBanner.Footer>
|
|
137
|
+
</ConsentBanner.Card>
|
|
138
|
+
</ConsentBanner.Root>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 6. `noStyle`
|
|
142
|
+
|
|
143
|
+
Use `noStyle` only when the c15t structure is still correct but you want to replace all visual defaults:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
<ConsentBanner noStyle />
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 7. Headless
|
|
150
|
+
|
|
151
|
+
Go headless only when you are replacing both markup and behavior. For that path, continue to [Headless Mode](../headless).
|
|
152
|
+
|
|
153
|
+
## Common Styling Tasks
|
|
154
|
+
|
|
155
|
+
### Change the banner footer background
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
options={{
|
|
159
|
+
theme: {
|
|
160
|
+
colors: {
|
|
161
|
+
surfaceHover: '#f6f3ee',
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
}}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Use `theme.colors.surfaceHover` before trying raw CSS.
|
|
168
|
+
|
|
169
|
+
### Change the banner card background
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
options={{
|
|
173
|
+
theme: {
|
|
174
|
+
colors: {
|
|
175
|
+
surface: '#fffdf8',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
}}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Use `theme.colors.surface` before overriding banner CSS variables directly.
|
|
182
|
+
|
|
183
|
+
### Tweak the banner card, footer, or title styling without changing markup
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
options={{
|
|
187
|
+
theme: {
|
|
188
|
+
slots: {
|
|
189
|
+
consentBannerCard: 'rounded-[28px] shadow-xl',
|
|
190
|
+
consentBannerFooter: 'border-t border-black/10 px-6',
|
|
191
|
+
consentBannerTitle: 'text-xl tracking-tight',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
}}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Change stock consent action button styles semantically
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
options={{
|
|
201
|
+
theme: {
|
|
202
|
+
consentActions: {
|
|
203
|
+
default: { mode: 'stroke' },
|
|
204
|
+
accept: { variant: 'primary', mode: 'stroke' },
|
|
205
|
+
customize: { variant: 'neutral', mode: 'ghost' },
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
}}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Use `theme.consentActions` when you want to change the stock banner/dialog button treatment without rewriting the component layout. Policy packs still control action arrangement and primary-action hints. The theme controls whether those actions render as `stroke`, `filled`, `ghost`, or `lighter`.
|
|
212
|
+
|
|
213
|
+
### Change banner copy without replacing the component
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
options={{
|
|
217
|
+
i18n: {
|
|
218
|
+
locale: 'en',
|
|
219
|
+
messages: {
|
|
220
|
+
en: {
|
|
221
|
+
cookieBanner: {
|
|
222
|
+
title: 'We value your privacy',
|
|
223
|
+
description: 'We use cookies to improve the site and measure performance.',
|
|
224
|
+
},
|
|
225
|
+
common: {
|
|
226
|
+
acceptAll: 'Accept all',
|
|
227
|
+
rejectAll: 'Reject all',
|
|
228
|
+
customize: 'Manage preferences',
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
}}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Enable dark mode safely
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
options={{
|
|
240
|
+
colorScheme: 'system',
|
|
241
|
+
theme: {
|
|
242
|
+
colors: { surface: '#ffffff', text: '#1f2937' },
|
|
243
|
+
dark: { surface: '#111827', text: '#f9fafb' },
|
|
244
|
+
},
|
|
245
|
+
}}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
> ℹ️ **Info:**
|
|
249
|
+
> If a token change does not show up where you expect, check how that component maps tokens to CSS variables before escalating. For example, the stock banner footer background comes from colors.surfaceHover, not a separate footer token.
|
|
250
|
+
>
|
|
251
|
+
> ⚠️ **Warning:**
|
|
252
|
+
> Do not jump to CSS overrides or !important because a token did not appear to work at first glance.noStyle: true removes layout and visual defaults. Treat it as an advanced opt-out, not a normal theming step.Headless mode is for replacing markup and behavior, not for styling-only requests.Use either tokens/slots or raw CSS variable overrides intentionally to avoid conflicting style sources.For dark mode, c15t supports .dark and .c15t-dark.
|
|
253
|
+
|
|
254
|
+
## API Reference
|
|
255
|
+
|
|
256
|
+
|Property|Value|
|
|
257
|
+
|:--|:--|
|
|
258
|
+
|Type Name|\`Theme\`|
|
|
259
|
+
|Source Path|\`./packages/ui/src/theme/types.ts\`|
|
|
260
|
+
|
|
261
|
+
\*ExtractedTypeTable: Could not extract "Theme" from "./packages/ui/src/theme/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Slots
|
|
3
|
+
description: Reference page for slots.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
## What are Slots?
|
|
7
|
+
|
|
8
|
+
Slots let you target specific parts of consent components with styles. Each component is built from named slots such as `consentBannerTitle` and `consentDialogTag`.
|
|
9
|
+
|
|
10
|
+
Use slots after the stock component APIs and design tokens:
|
|
11
|
+
|
|
12
|
+
* If the change is semantic, prefer tokens first. For example, the stock banner footer background comes from `theme.colors.surfaceHover`.
|
|
13
|
+
* If the component part is correct but you need a local tweak, use a slot.
|
|
14
|
+
|
|
15
|
+
Common banner slot choices:
|
|
16
|
+
|
|
17
|
+
* `consentBannerCard` for card radius, shadow, width, and local background treatment
|
|
18
|
+
* `consentBannerFooter` for spacing, borders, and local footer styling
|
|
19
|
+
* `consentBannerTitle` for title typography
|
|
20
|
+
* `buttonPrimary` and `buttonSecondary` for shared button classes
|
|
21
|
+
|
|
22
|
+
## Using Slots
|
|
23
|
+
|
|
24
|
+
Pass slot styles in the theme's `slots` object:
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
const theme = {
|
|
28
|
+
slots: {
|
|
29
|
+
consentBannerFooter: 'border-t border-black/10 px-6',
|
|
30
|
+
consentBannerTitle: 'text-xl font-bold tracking-tight',
|
|
31
|
+
|
|
32
|
+
// Object value = className + inline styles
|
|
33
|
+
consentBannerCard: {
|
|
34
|
+
className: 'rounded-xl shadow-lg',
|
|
35
|
+
style: { maxWidth: '600px' },
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
} satisfies Theme;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Slot Style Types
|
|
42
|
+
|
|
43
|
+
Each slot accepts either a `string` (treated as className) or a `SlotStyle` object:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
// String: treated as className
|
|
47
|
+
consentBannerTitle: 'my-custom-class'
|
|
48
|
+
|
|
49
|
+
// Object: className + style + noStyle
|
|
50
|
+
consentBannerFooter: {
|
|
51
|
+
className: 'border-t border-black/10',
|
|
52
|
+
style: { paddingBlock: '1rem' },
|
|
53
|
+
noStyle: false, // Set true only when you want to remove this slot's default styling
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`noStyle` on a slot is an advanced escape hatch. Start with className and style overrides first.
|
|
58
|
+
|
|
59
|
+
## Example: Style the stock banner without changing markup
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
const theme = {
|
|
63
|
+
colors: {
|
|
64
|
+
surface: '#fffdf8',
|
|
65
|
+
surfaceHover: '#f6f3ee',
|
|
66
|
+
},
|
|
67
|
+
slots: {
|
|
68
|
+
consentBannerCard: 'rounded-[28px] shadow-xl',
|
|
69
|
+
consentBannerFooter: 'border-t border-black/10 px-6',
|
|
70
|
+
consentBannerTitle: 'tracking-tight',
|
|
71
|
+
},
|
|
72
|
+
} satisfies Theme;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Available Slots
|
|
76
|
+
|
|
77
|
+
Use the typed API reference below for the full slot list and descriptions. It stays in sync with the actual component slot surface.
|
|
78
|
+
|
|
79
|
+
## API Reference
|
|
80
|
+
|
|
81
|
+
|Property|Value|
|
|
82
|
+
|:--|:--|
|
|
83
|
+
|Type Name|\`ComponentSlots\`|
|
|
84
|
+
|Source Path|\`./packages/ui/src/theme/types.ts\`|
|
|
85
|
+
|
|
86
|
+
\*ExtractedTypeTable: Could not extract "ComponentSlots" from "./packages/ui/src/theme/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
87
|
+
|
|
88
|
+
|Property|Value|
|
|
89
|
+
|:--|:--|
|
|
90
|
+
|Type Name|\`SlotStyle\`|
|
|
91
|
+
|Source Path|\`./packages/ui/src/theme/types.ts\`|
|
|
92
|
+
|
|
93
|
+
\*ExtractedTypeTable: Could not extract "SlotStyle" from "./packages/ui/src/theme/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Stylesheet Entrypoint
|
|
3
|
+
description: Reference page for stylesheet entrypoint.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
Keeping the c15t stylesheet in your global CSS entrypoint makes layer and cascade order explicit. JS/TSX side-effect imports can load in a different order across framework and Tailwind tooling, which makes style regressions harder to debug.
|
|
7
|
+
|
|
8
|
+
With Tailwind v4, keep c15t at the end of the top-level `@import` block so Fumadocs, `tw-animate-css`, and other preset imports do not override c15t theme tokens.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Tailwind
|
|
3
|
+
description: Reference page for tailwind.
|
|
4
|
+
group: reference
|
|
5
|
+
---
|
|
6
|
+
c15t works with Tailwind CSS out of the box. Use the `slots` theme option to apply Tailwind utility classes to any component part.
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
Import the standard c15t stylesheet once in your app-level CSS entrypoint:
|
|
11
|
+
|
|
12
|
+
```css
|
|
13
|
+
/* React: src/index.css */
|
|
14
|
+
@import "@c15t/react/styles.css";
|
|
15
|
+
|
|
16
|
+
/* Next.js: app/globals.css */
|
|
17
|
+
@import "@c15t/nextjs/styles.css";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Keeping the c15t stylesheet in your global CSS entrypoint makes layer and cascade order explicit. JS/TSX side-effect imports can load in a different order across framework and Tailwind tooling, which makes style regressions harder to debug.
|
|
21
|
+
|
|
22
|
+
With Tailwind v4, keep c15t at the end of the top-level `@import` block so Fumadocs, `tw-animate-css`, and other preset imports do not override c15t theme tokens.
|
|
23
|
+
|
|
24
|
+
### Tailwind v4
|
|
25
|
+
|
|
26
|
+
Tailwind v4 automatically scans your source files. Import Tailwind normally, then keep the c15t stylesheet last in the top-level `@import` block so Fumadocs, `tw-animate-css`, or other preset styles load first. c15t component styles join Tailwind's `components` layer automatically, so no extra c15t-specific layer declaration is needed:
|
|
27
|
+
|
|
28
|
+
```css title="src/index.css"
|
|
29
|
+
@import "tailwindcss";
|
|
30
|
+
@import "tw-animate-css";
|
|
31
|
+
@import "@c15t/react/styles.css";
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```css title="app/globals.css"
|
|
35
|
+
@import "tailwindcss";
|
|
36
|
+
@import "tw-animate-css";
|
|
37
|
+
@import "@c15t/nextjs/styles.css";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Tailwind v3
|
|
41
|
+
|
|
42
|
+
Import the Tailwind 3-compatible c15t stylesheet after `@tailwind components;` and before `@tailwind utilities;`:
|
|
43
|
+
|
|
44
|
+
```css title="src/index.css"
|
|
45
|
+
@tailwind base;
|
|
46
|
+
@tailwind components;
|
|
47
|
+
@import "@c15t/react/styles.tw3.css";
|
|
48
|
+
@tailwind utilities;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```css title="app/globals.css"
|
|
52
|
+
@tailwind base;
|
|
53
|
+
@tailwind components;
|
|
54
|
+
@import "@c15t/nextjs/styles.tw3.css";
|
|
55
|
+
@tailwind utilities;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Dark Mode with Tailwind
|
|
59
|
+
|
|
60
|
+
Combine Tailwind's dark mode with c15t's `dark` tokens:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
const theme = {
|
|
64
|
+
colors: {
|
|
65
|
+
primary: '#6366f1',
|
|
66
|
+
surface: '#ffffff',
|
|
67
|
+
text: '#1f2937',
|
|
68
|
+
},
|
|
69
|
+
dark: {
|
|
70
|
+
primary: '#818cf8',
|
|
71
|
+
surface: '#1f2937',
|
|
72
|
+
text: '#f9fafb',
|
|
73
|
+
},
|
|
74
|
+
slots: {
|
|
75
|
+
consentBannerCard: 'bg-white dark:bg-gray-900 shadow-lg dark:shadow-gray-900/30',
|
|
76
|
+
consentBannerTitle: 'text-gray-900 dark:text-gray-100',
|
|
77
|
+
},
|
|
78
|
+
} satisfies Theme;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Optional: noStyle Mode
|
|
82
|
+
|
|
83
|
+
If you want Tailwind to own all layout and visual styling, use `noStyle: true`.
|
|
84
|
+
|
|
85
|
+
> ℹ️ **Info:**
|
|
86
|
+
> When using noStyle: true with Tailwind, you're responsible for all layout and visual styling. Start with slots first, then switch to noStyle only when you need full control.
|
|
87
|
+
|
|
88
|
+
For full custom markup (not just styles), see [Headless Mode](../headless).
|