@c15t/react 2.0.0-rc.6 → 2.0.0-rc.7
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/dist/components/consent-banner/atoms/root.cjs +1 -1
- package/dist/components/consent-banner/atoms/root.js +1 -1
- package/dist/components/consent-dialog/atoms/root.cjs +1 -1
- package/dist/components/consent-dialog/atoms/root.js +1 -1
- package/dist/components/consent-widget/atoms/accordion.cjs +1 -1
- package/dist/components/consent-widget/atoms/accordion.js +1 -1
- package/dist/components/iab-consent-banner/atoms/card.cjs +1 -1
- package/dist/components/iab-consent-banner/atoms/card.js +1 -1
- package/dist/components/iab-consent-banner/atoms/footer.cjs +1 -1
- package/dist/components/iab-consent-banner/atoms/footer.js +1 -1
- package/dist/components/iab-consent-banner/atoms/header.cjs +1 -1
- package/dist/components/iab-consent-banner/atoms/header.js +1 -1
- package/dist/components/iab-consent-banner/atoms/root.cjs +1 -1
- package/dist/components/iab-consent-banner/atoms/root.js +1 -1
- package/dist/components/iab-consent-dialog/atoms/card.cjs +1 -1
- package/dist/components/iab-consent-dialog/atoms/card.js +1 -1
- package/dist/components/iab-consent-dialog/atoms/footer.cjs +1 -1
- package/dist/components/iab-consent-dialog/atoms/footer.js +1 -1
- package/dist/components/iab-consent-dialog/atoms/header.cjs +1 -1
- package/dist/components/iab-consent-dialog/atoms/header.js +1 -1
- package/dist/components/iab-consent-dialog/atoms/root.cjs +1 -1
- package/dist/components/iab-consent-dialog/atoms/root.js +1 -1
- package/dist/components/shared/primitives/box.cjs +1 -1
- package/dist/components/shared/primitives/box.js +1 -1
- package/dist/iab/styles.tw3.css +1 -0
- package/dist/styles.tw3.css +1 -0
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist-types/components/consent-banner/atoms/root.d.ts +43 -12
- package/dist-types/components/consent-banner/index.d.ts +44 -24
- package/dist-types/components/consent-dialog/index.d.ts +29 -8
- package/dist-types/components/consent-preferences-link/consent-preferences-link.d.ts +0 -1
- package/dist-types/components/consent-widget/atoms/accordion.d.ts +4 -3
- package/dist-types/components/consent-widget/index.d.ts +23 -6
- package/dist-types/version.d.ts +1 -1
- package/docs/building-headless-components.md +3 -0
- package/docs/components/consent-banner.md +68 -18
- package/docs/components/consent-dialog.md +31 -2
- package/docs/components/consent-widget.md +31 -2
- package/docs/headless.md +13 -7
- package/docs/styling/classnames.md +17 -9
- package/docs/styling/overview.md +166 -29
- package/docs/styling/slots.md +37 -7
- package/docs/styling/tailwind.md +12 -20
- package/package.json +6 -2
- package/src/iab/styles.tw3.css +10 -0
- package/src/styles.tw3.css +10 -0
|
@@ -34,8 +34,9 @@ export interface ConsentBannerCompoundComponent extends FC<ConsentBannerProps> {
|
|
|
34
34
|
*
|
|
35
35
|
* @remarks
|
|
36
36
|
* This component serves as the main entry point for rendering a consent banner.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* Start with the pre-built component and its existing configuration surface.
|
|
38
|
+
* For most customization, use `ConsentManagerProvider` options, theme tokens,
|
|
39
|
+
* slots, and `theme.consentActions` before reaching for compound composition.
|
|
39
40
|
*
|
|
40
41
|
* Key features:
|
|
41
42
|
* - Fully accessible by default
|
|
@@ -43,7 +44,7 @@ export interface ConsentBannerCompoundComponent extends FC<ConsentBannerProps> {
|
|
|
43
44
|
* - Customizable appearance
|
|
44
45
|
* - Responsive design
|
|
45
46
|
* - Error boundary protection
|
|
46
|
-
* -
|
|
47
|
+
* - Advanced compound component support when markup must change
|
|
47
48
|
*
|
|
48
49
|
* @example
|
|
49
50
|
* Simple usage with default settings:
|
|
@@ -52,35 +53,54 @@ export interface ConsentBannerCompoundComponent extends FC<ConsentBannerProps> {
|
|
|
52
53
|
* ```
|
|
53
54
|
*
|
|
54
55
|
* @example
|
|
55
|
-
*
|
|
56
|
+
* Preferred customization via provider `i18n`, theme tokens, and slots:
|
|
56
57
|
* ```tsx
|
|
57
|
-
* <
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
58
|
+
* <ConsentManagerProvider
|
|
59
|
+
* options={{
|
|
60
|
+
* i18n: {
|
|
61
|
+
* locale: 'en',
|
|
62
|
+
* messages: {
|
|
63
|
+
* en: {
|
|
64
|
+
* cookieBanner: { title: 'Privacy choices' },
|
|
65
|
+
* },
|
|
66
|
+
* },
|
|
67
|
+
* },
|
|
68
|
+
* theme: {
|
|
69
|
+
* colors: {
|
|
70
|
+
* surface: '#fffdf8',
|
|
71
|
+
* surfaceHover: '#f6f3ee',
|
|
72
|
+
* },
|
|
73
|
+
* slots: {
|
|
74
|
+
* consentBannerCard: 'rounded-3xl',
|
|
75
|
+
* consentBannerFooter: 'border-t border-black/10',
|
|
76
|
+
* },
|
|
77
|
+
* },
|
|
78
|
+
* }}
|
|
79
|
+
* >
|
|
80
|
+
* <ConsentBanner primaryButton="accept" />
|
|
81
|
+
* </ConsentManagerProvider>
|
|
64
82
|
* ```
|
|
65
83
|
*
|
|
66
84
|
* @example
|
|
85
|
+
* Advanced custom markup with compound components:
|
|
67
86
|
* ```tsx
|
|
68
87
|
* <ConsentBanner.Root>
|
|
69
|
-
* <ConsentBanner.
|
|
70
|
-
* <ConsentBanner.
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* </ConsentBanner.
|
|
74
|
-
* <ConsentBanner.
|
|
75
|
-
* <ConsentBanner.
|
|
76
|
-
* <ConsentBanner.
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
88
|
+
* <ConsentBanner.Card>
|
|
89
|
+
* <ConsentBanner.Header>
|
|
90
|
+
* <ConsentBanner.Title />
|
|
91
|
+
* <ConsentBanner.Description />
|
|
92
|
+
* </ConsentBanner.Header>
|
|
93
|
+
* <ConsentBanner.Footer>
|
|
94
|
+
* <ConsentBanner.CustomizeButton />
|
|
95
|
+
* <ConsentBanner.FooterSubGroup>
|
|
96
|
+
* <ConsentBanner.RejectButton />
|
|
97
|
+
* <ConsentBanner.AcceptButton />
|
|
98
|
+
* </ConsentBanner.FooterSubGroup>
|
|
99
|
+
* </ConsentBanner.Footer>
|
|
100
|
+
* </ConsentBanner.Card>
|
|
80
101
|
* </ConsentBanner.Root>
|
|
81
102
|
* ```
|
|
82
|
-
* Note: Next.js Server Components do not support compound components. Ensure you add 'use client' to the file.
|
|
83
|
-
* Using compound components for custom layout:
|
|
103
|
+
* Note: Next.js Server Components do not support compound components. Ensure you add `'use client'` to the file.
|
|
84
104
|
*
|
|
85
105
|
* @public
|
|
86
106
|
*/
|
|
@@ -42,30 +42,51 @@ export interface ConsentDialogCompoundComponent extends FC<ConsentDialogProps> {
|
|
|
42
42
|
* - Provides an accessible modal interface for consent customization
|
|
43
43
|
* - Implements smooth enter/exit animations
|
|
44
44
|
* - Manages proper focus handling
|
|
45
|
-
* - Supports theme customization
|
|
45
|
+
* - Supports theme customization through provider tokens and slots
|
|
46
46
|
* - Handles client-side portal rendering
|
|
47
|
+
* - Exposes compound primitives for advanced markup changes
|
|
47
48
|
*
|
|
48
49
|
* @example
|
|
50
|
+
* Basic usage:
|
|
49
51
|
* ```tsx
|
|
50
|
-
* <ConsentDialog
|
|
51
|
-
* theme={customTheme}
|
|
52
|
-
* disableAnimation={false}
|
|
53
|
-
* noStyle={false}
|
|
54
|
-
* />
|
|
52
|
+
* <ConsentDialog />
|
|
55
53
|
* ```
|
|
56
54
|
*
|
|
57
55
|
* @example
|
|
56
|
+
* Preferred customization with stock structure:
|
|
57
|
+
* ```tsx
|
|
58
|
+
* <ConsentManagerProvider
|
|
59
|
+
* options={{
|
|
60
|
+
* theme: {
|
|
61
|
+
* slots: {
|
|
62
|
+
* consentDialogCard: 'rounded-3xl shadow-xl',
|
|
63
|
+
* consentDialogFooter: 'border-t border-black/10',
|
|
64
|
+
* },
|
|
65
|
+
* },
|
|
66
|
+
* }}
|
|
67
|
+
* >
|
|
68
|
+
* <ConsentDialog hideBranding showTrigger />
|
|
69
|
+
* </ConsentManagerProvider>
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* Advanced custom markup with compound components:
|
|
58
74
|
* ```tsx
|
|
59
75
|
* <ConsentDialog.Root>
|
|
60
76
|
* <ConsentDialog.Card>
|
|
61
77
|
* <ConsentDialog.Header>
|
|
62
|
-
* <ConsentDialog.HeaderTitle
|
|
78
|
+
* <ConsentDialog.HeaderTitle />
|
|
79
|
+
* <ConsentDialog.HeaderDescription />
|
|
63
80
|
* </ConsentDialog.Header>
|
|
81
|
+
* <ConsentDialog.Content>
|
|
82
|
+
* <ConsentWidget />
|
|
83
|
+
* </ConsentDialog.Content>
|
|
84
|
+
* <ConsentDialog.Footer />
|
|
64
85
|
* </ConsentDialog.Card>
|
|
65
86
|
* </ConsentDialog.Root>
|
|
66
87
|
* ```
|
|
67
88
|
*
|
|
68
|
-
* Note: Next.js Server Components do not support compound components. Ensure you add 'use client' to the file.
|
|
89
|
+
* Note: Next.js Server Components do not support compound components. Ensure you add `'use client'` to the file.
|
|
69
90
|
*
|
|
70
91
|
* @public
|
|
71
92
|
*/
|
|
@@ -13,4 +13,3 @@ export interface ConsentDialogLinkProps extends Omit<ConsentButtonProps, 'childr
|
|
|
13
13
|
children: ReactNode;
|
|
14
14
|
}
|
|
15
15
|
export declare const ConsentDialogLink: import("react").ForwardRefExoticComponent<ConsentDialogLinkProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
16
|
-
lement>>;
|
|
@@ -7,20 +7,21 @@ declare const ConsentWidgetAccordionTriggerInner: import("react").ForwardRefExot
|
|
|
7
7
|
declare const ConsentWidgetAccordionContent: import("react").ForwardRefExoticComponent<PreferenceItem.PreferenceItemContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
8
8
|
declare const ConsentWidgetAccordionArrow: import("react").ForwardRefExoticComponent<PreferenceItem.PreferenceItemSlotProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
9
9
|
declare const ConsentWidgetSwitch: import("react").ForwardRefExoticComponent<RadixSwitch.SwitchProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
10
|
-
type ConsentWidgetAccordionProps = {
|
|
10
|
+
type ConsentWidgetAccordionProps = Omit<BoxProps, 'themeKey'> & {
|
|
11
|
+
'data-testid'?: string;
|
|
11
12
|
children: ReactNode;
|
|
12
13
|
onValueChange?: (value: string | string[]) => void;
|
|
13
14
|
type?: 'multiple' | 'single';
|
|
14
15
|
value?: string | string[];
|
|
15
16
|
};
|
|
16
|
-
declare const ConsentWidgetAccordion: ({ children, onValueChange, type, value, }: ConsentWidgetAccordionProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
declare const ConsentWidgetAccordion: ({ "data-testid": dataTestId, children, className, noStyle, onValueChange, style, type, value, ...props }: ConsentWidgetAccordionProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
18
|
declare const ConsentWidgetAccordionItems: () => import("react/jsx-runtime").JSX.Element[];
|
|
18
19
|
declare const ConsentWidgetAccordionItem: import("react").ForwardRefExoticComponent<Omit<PreferenceItem.PreferenceItemRootProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
19
20
|
declare const AccordionTriggerInner: import("react").ForwardRefExoticComponent<PreferenceItem.PreferenceItemTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
20
21
|
declare const AccordionTrigger: import("react").ForwardRefExoticComponent<BoxProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
21
22
|
declare const AccordionContent: import("react").ForwardRefExoticComponent<PreferenceItem.PreferenceItemContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
22
23
|
declare const AccordionArrow: import("react").ForwardRefExoticComponent<PreferenceItem.PreferenceItemSlotProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
23
|
-
declare const Accordion: ({ children, onValueChange, type, value, }: ConsentWidgetAccordionProps) => import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
declare const Accordion: ({ "data-testid": dataTestId, children, className, noStyle, onValueChange, style, type, value, ...props }: ConsentWidgetAccordionProps) => import("react/jsx-runtime").JSX.Element;
|
|
24
25
|
declare const Switch: import("react").ForwardRefExoticComponent<RadixSwitch.SwitchProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
25
26
|
declare const AccordionItems: () => import("react/jsx-runtime").JSX.Element[];
|
|
26
27
|
declare const AccordionItem: import("react").ForwardRefExoticComponent<Omit<PreferenceItem.PreferenceItemRootProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -44,11 +44,11 @@ export interface ConsentWidgetCompoundComponent extends FC<ConsentWidgetProps> {
|
|
|
44
44
|
*
|
|
45
45
|
* @remarks
|
|
46
46
|
* Key features:
|
|
47
|
-
* - Implements compound component pattern for flexible composition
|
|
48
47
|
* - Manages consent state and user interactions
|
|
49
48
|
* - Provides accessible controls for consent management
|
|
50
|
-
* - Supports comprehensive theming
|
|
49
|
+
* - Supports comprehensive theming with tokens and slots
|
|
51
50
|
* - Handles accordion state management
|
|
51
|
+
* - Exposes compound primitives for advanced layout changes
|
|
52
52
|
*
|
|
53
53
|
* @example
|
|
54
54
|
* Basic usage:
|
|
@@ -59,15 +59,32 @@ export interface ConsentWidgetCompoundComponent extends FC<ConsentWidgetProps> {
|
|
|
59
59
|
* ```
|
|
60
60
|
*
|
|
61
61
|
* @example
|
|
62
|
-
*
|
|
62
|
+
* Preferred stock customization with theme slots:
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <ConsentManagerProvider
|
|
65
|
+
* options={{
|
|
66
|
+
* theme: {
|
|
67
|
+
* slots: {
|
|
68
|
+
* consentWidgetAccordion: 'rounded-3xl border border-black/10',
|
|
69
|
+
* consentWidgetFooter: 'border-t border-black/10',
|
|
70
|
+
* },
|
|
71
|
+
* },
|
|
72
|
+
* }}
|
|
73
|
+
* >
|
|
74
|
+
* <ConsentWidget hideBranding />
|
|
75
|
+
* </ConsentManagerProvider>
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* Advanced compound components:
|
|
63
80
|
* ```tsx
|
|
64
81
|
* <ConsentWidget.Root>
|
|
65
82
|
* <ConsentWidget.Accordion>
|
|
66
83
|
* <ConsentWidget.AccordionItems />
|
|
67
|
-
*
|
|
68
|
-
*
|
|
84
|
+
* </ConsentWidget.Accordion>
|
|
85
|
+
* </ConsentWidget.Root>
|
|
69
86
|
* ```
|
|
70
|
-
* Note: Next.js Server Components do not support compound components. Ensure you add 'use client' to the file.
|
|
87
|
+
* Note: Next.js Server Components do not support compound components. Ensure you add `'use client'` to the file.
|
|
71
88
|
*
|
|
72
89
|
*/
|
|
73
90
|
declare const ConsentWidget: ConsentWidgetCompoundComponent;
|
package/dist-types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.0.0-rc.
|
|
1
|
+
export declare const version = "2.0.0-rc.7";
|
|
@@ -4,6 +4,9 @@ description: Build policy-aware custom consent components in React using the hea
|
|
|
4
4
|
---
|
|
5
5
|
Building headless components is easier now because c15t exposes policy-aware primitives instead of forcing you to reconstruct banner rules by hand.
|
|
6
6
|
|
|
7
|
+
> ⚠️ **Warning:**
|
|
8
|
+
> Headless is the last step in the customization ladder. Use this guide only when pre-built components, tokens, slots, compound components, and noStyle are no longer sufficient.
|
|
9
|
+
|
|
7
10
|
The headless stack is:
|
|
8
11
|
|
|
9
12
|
* `useHeadlessConsentUI()` for policy-aware banner/dialog actions, ordering, layout, and primary actions hints
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: ConsentBanner
|
|
3
|
-
description: A pre-built consent banner that appears when user consent is needed. Supports
|
|
3
|
+
description: A pre-built consent banner that appears when user consent is needed. Supports policy-aware layout, theming, and advanced composition when markup must change.
|
|
4
4
|
---
|
|
5
5
|
`ConsentBanner` is a ready-to-use consent banner that appears automatically in **opt-in jurisdictions** (like GDPR) where explicit consent is required before tracking. In opt-out jurisdictions (like CCPA), the banner won't appear — users get an opt-out mechanism instead. It includes reject, accept, and customize buttons with configurable layout.
|
|
6
6
|
|
|
@@ -18,20 +18,6 @@ export function ConsentManager() {
|
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
## Customizing Content
|
|
22
|
-
|
|
23
|
-
Override the default title, description, and button labels:
|
|
24
|
-
|
|
25
|
-
```tsx
|
|
26
|
-
<ConsentBanner
|
|
27
|
-
title="We value your privacy"
|
|
28
|
-
description="We use cookies to enhance your browsing experience and analyze site traffic."
|
|
29
|
-
acceptButtonText="Accept all"
|
|
30
|
-
rejectButtonText="Reject all"
|
|
31
|
-
customizeButtonText="Manage preferences"
|
|
32
|
-
/>
|
|
33
|
-
```
|
|
34
|
-
|
|
35
21
|
## Button Layout
|
|
36
22
|
|
|
37
23
|
The `layout` prop controls button arrangement. Each item is either a button ID or an array of button IDs (which groups them together):
|
|
@@ -86,6 +72,37 @@ Use the provider `theme` prop to control how stock consent actions look:
|
|
|
86
72
|
|
|
87
73
|
Policy packs control grouping, ordering, and direction. The theme controls button appearance.
|
|
88
74
|
|
|
75
|
+
## Styling First
|
|
76
|
+
|
|
77
|
+
> ℹ️ **Info:**
|
|
78
|
+
> For pure theming, stay inside the pre-built banner. Start with layout props, theme.consentActions, design tokens, and theme.slots before reaching for compound components. See Styling Overview.
|
|
79
|
+
|
|
80
|
+
The stock banner maps common visual changes to the theme system:
|
|
81
|
+
|
|
82
|
+
* Card background -> `theme.colors.surface`
|
|
83
|
+
* Footer background -> `theme.colors.surfaceHover`
|
|
84
|
+
* Card, footer, and title tweaks -> `theme.slots.consentBannerCard`, `consentBannerFooter`, and `consentBannerTitle`
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
<ConsentManagerProvider
|
|
88
|
+
options={{
|
|
89
|
+
theme: {
|
|
90
|
+
colors: {
|
|
91
|
+
surface: '#fffdf8',
|
|
92
|
+
surfaceHover: '#f6f3ee',
|
|
93
|
+
},
|
|
94
|
+
slots: {
|
|
95
|
+
consentBannerCard: 'rounded-[28px] shadow-xl',
|
|
96
|
+
consentBannerFooter: 'border-t border-black/10 px-6',
|
|
97
|
+
consentBannerTitle: 'tracking-tight',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
<ConsentBanner />
|
|
103
|
+
</ConsentManagerProvider>
|
|
104
|
+
```
|
|
105
|
+
|
|
89
106
|
### Primary Button
|
|
90
107
|
|
|
91
108
|
Highlight specific button(s) as the primary action:
|
|
@@ -116,9 +133,40 @@ Control which legal links appear in the banner description:
|
|
|
116
133
|
> ℹ️ **Info:**
|
|
117
134
|
> Legal link URLs are configured in the ConsentManagerProvider options via the legalLinks prop, not on the banner itself.
|
|
118
135
|
|
|
119
|
-
##
|
|
136
|
+
## Customizing Copy
|
|
137
|
+
|
|
138
|
+
Prefer provider `i18n` when you want to rename the stock banner content:
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<ConsentManagerProvider
|
|
142
|
+
options={{
|
|
143
|
+
i18n: {
|
|
144
|
+
locale: 'en',
|
|
145
|
+
messages: {
|
|
146
|
+
en: {
|
|
147
|
+
cookieBanner: {
|
|
148
|
+
title: 'We value your privacy',
|
|
149
|
+
description: 'We use cookies to improve the site and measure performance.',
|
|
150
|
+
},
|
|
151
|
+
common: {
|
|
152
|
+
acceptAll: 'Accept all',
|
|
153
|
+
rejectAll: 'Reject all',
|
|
154
|
+
customize: 'Manage preferences',
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<ConsentBanner />
|
|
162
|
+
</ConsentManagerProvider>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Direct text props such as `title`, `description`, and `acceptButtonText` are still supported for one-off overrides, but `i18n` is the preferred path for copy changes.
|
|
120
166
|
|
|
121
|
-
|
|
167
|
+
## Advanced: Compound Components
|
|
168
|
+
|
|
169
|
+
Use compound components only when the stock banner structure is no longer enough and you need to rearrange existing c15t primitives:
|
|
122
170
|
|
|
123
171
|
```tsx
|
|
124
172
|
<ConsentBanner.Root>
|
|
@@ -142,7 +190,7 @@ Build fully custom banner layouts using sub-components:
|
|
|
142
190
|
* `ConsentBanner.Root` — Outermost container, provides theme context
|
|
143
191
|
* `ConsentBanner.Card` — Main content card with optional focus trapping
|
|
144
192
|
* `ConsentBanner.Header` — Contains title and description
|
|
145
|
-
* `ConsentBanner.Title` — Heading, defaults to translation `
|
|
193
|
+
* `ConsentBanner.Title` — Heading, defaults to translation `cookieBanner.title`
|
|
146
194
|
* `ConsentBanner.Description` — Description text, supports `legalLinks` prop
|
|
147
195
|
* `ConsentBanner.Footer` — Action buttons container
|
|
148
196
|
* `ConsentBanner.FooterSubGroup` — Groups related buttons together
|
|
@@ -151,6 +199,8 @@ Build fully custom banner layouts using sub-components:
|
|
|
151
199
|
* `ConsentBanner.AcceptButton` — Accepts all consent
|
|
152
200
|
* `ConsentBanner.Overlay` — Optional backdrop overlay
|
|
153
201
|
|
|
202
|
+
If you only need styling changes, stay with tokens and slots instead of rebuilding the banner layout.
|
|
203
|
+
|
|
154
204
|
## Props
|
|
155
205
|
|
|
156
206
|
### ConsentBannerProps
|
|
@@ -81,9 +81,36 @@ Hide the c15t branding in the dialog footer:
|
|
|
81
81
|
<ConsentDialog hideBranding />
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
##
|
|
84
|
+
## Styling First
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
> ℹ️ **Info:**
|
|
87
|
+
> If you are only changing visuals, stay with the stock dialog and use the theme system first. Start with tokens and slots such as consentDialogCard, consentDialogHeader, and consentDialogFooter. See Styling Overview.
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
<ConsentManagerProvider
|
|
91
|
+
options={{
|
|
92
|
+
theme: {
|
|
93
|
+
colors: {
|
|
94
|
+
surface: '#fffdf8',
|
|
95
|
+
surfaceHover: '#f6f3ee',
|
|
96
|
+
},
|
|
97
|
+
slots: {
|
|
98
|
+
consentDialogCard: 'rounded-[32px] shadow-xl',
|
|
99
|
+
consentDialogHeader: 'gap-3',
|
|
100
|
+
consentDialogFooter: 'border-t border-black/10 px-6',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
<ConsentDialog />
|
|
106
|
+
</ConsentManagerProvider>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Dialog copy should be changed through `ConsentManagerProvider.options.i18n`, not by rebuilding the dialog structure.
|
|
110
|
+
|
|
111
|
+
## Advanced: Compound Components
|
|
112
|
+
|
|
113
|
+
Use compound components only when you need custom dialog markup while still keeping c15t primitives:
|
|
87
114
|
|
|
88
115
|
```tsx
|
|
89
116
|
<ConsentDialog.Root>
|
|
@@ -118,6 +145,8 @@ For a quick pre-composed layout, use the shorthand card:
|
|
|
118
145
|
</ConsentDialog.Root>
|
|
119
146
|
```
|
|
120
147
|
|
|
148
|
+
If the stock dialog structure still works, prefer tokens, slots, and provider configuration instead.
|
|
149
|
+
|
|
121
150
|
## Props
|
|
122
151
|
|
|
123
152
|
### ConsentDialogProps
|
|
@@ -35,9 +35,36 @@ export function PrivacySettingsPage() {
|
|
|
35
35
|
|
|
36
36
|
Each consent category is rendered as an expandable accordion item. Clicking the category header expands it to show a description and any associated services. Users can toggle individual categories on or off using the switch control. The `necessary` category is always enabled and cannot be toggled.
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Styling First
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
> ℹ️ **Info:**
|
|
41
|
+
> Most widget customization should stay in the stock component. Use theme tokens and slots such as consentWidgetAccordion, consentWidgetFooter, and toggle before reaching for compound components. See Styling Overview.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<ConsentManagerProvider
|
|
45
|
+
options={{
|
|
46
|
+
theme: {
|
|
47
|
+
colors: {
|
|
48
|
+
surface: '#fffdf8',
|
|
49
|
+
surfaceHover: '#f6f3ee',
|
|
50
|
+
},
|
|
51
|
+
slots: {
|
|
52
|
+
consentWidgetAccordion: 'rounded-3xl border border-black/10',
|
|
53
|
+
consentWidgetFooter: 'border-t border-black/10 px-6',
|
|
54
|
+
toggle: 'shadow-sm',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
<ConsentWidget />
|
|
60
|
+
</ConsentManagerProvider>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Widget copy should be changed through `ConsentManagerProvider.options.i18n` so the inline UI stays aligned with the rest of the consent experience.
|
|
64
|
+
|
|
65
|
+
## Advanced: Compound Components
|
|
66
|
+
|
|
67
|
+
Use compound components only when you need to rearrange the widget's existing primitives:
|
|
41
68
|
|
|
42
69
|
```tsx
|
|
43
70
|
<ConsentWidget.Root>
|
|
@@ -68,6 +95,8 @@ Build fully custom widget layouts using sub-components:
|
|
|
68
95
|
* `ConsentWidget.RejectButton` — Rejects all consent
|
|
69
96
|
* `ConsentWidget.SaveButton` — Saves custom selections
|
|
70
97
|
|
|
98
|
+
If the stock widget structure is already correct, stay with tokens and slots instead of rebuilding the layout.
|
|
99
|
+
|
|
71
100
|
## Props
|
|
72
101
|
|
|
73
102
|
### ConsentWidgetProps
|
package/docs/headless.md
CHANGED
|
@@ -4,11 +4,12 @@ description: Build fully custom consent UI using only hooks - no pre-built compo
|
|
|
4
4
|
---
|
|
5
5
|
c15t's headless mode means using the hooks (`useConsentManager`, `useTranslations`, etc.) without any pre-built UI components. This gives you complete control over the consent experience.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Before you go headless, walk the customization ladder in order:
|
|
8
8
|
|
|
9
|
-
1. **
|
|
10
|
-
2. **
|
|
11
|
-
3.
|
|
9
|
+
1. **Pre-built components** - Use provider options, component props, tokens, slots, and `theme.consentActions`
|
|
10
|
+
2. **Compound components** - Rearrange c15t primitives when the markup order must change
|
|
11
|
+
3. **`noStyle`** - Keep c15t structure but replace its styling
|
|
12
|
+
4. **Headless** - Use only hooks and build the entire UI yourself
|
|
12
13
|
|
|
13
14
|
## When to Go Headless
|
|
14
15
|
|
|
@@ -18,10 +19,15 @@ Go headless when:
|
|
|
18
19
|
* You need a consent flow that doesn't fit the banner/dialog pattern
|
|
19
20
|
* You want to embed consent choices inline rather than as overlays
|
|
20
21
|
|
|
21
|
-
Use
|
|
22
|
+
Use a lower-power tool instead when:
|
|
22
23
|
|
|
23
|
-
* The component structure works but the styling doesn't
|
|
24
|
-
* You
|
|
24
|
+
* The component structure works but the styling doesn't -> use tokens, slots, or `noStyle`
|
|
25
|
+
* You only need to rearrange existing c15t parts -> use compound components
|
|
26
|
+
* You want to change copy -> use `ConsentManagerProvider.options.i18n`
|
|
27
|
+
* You only need to restyle stock actions -> use `theme.consentActions`
|
|
28
|
+
|
|
29
|
+
> ⚠️ **Warning:**
|
|
30
|
+
> Headless mode is not the first answer for pure theming. If you are still trying to debug why a banner footer color did not change, stay in the styling system and verify the token-to-component mapping before you rebuild the UI.
|
|
25
31
|
|
|
26
32
|
> ℹ️ **Info:**
|
|
27
33
|
> Need a policy-aware implementation guide? See Building Headless Components.
|
|
@@ -2,15 +2,11 @@
|
|
|
2
2
|
title: Class Names
|
|
3
3
|
description: Style consent components using className props and per-slot className targeting via the theme.
|
|
4
4
|
---
|
|
5
|
-
##
|
|
5
|
+
## Prefer Slots for Stock Components
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
There is no single top-level `className` contract across every pre-built consent component.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
<ConsentBanner className="my-banner" />
|
|
11
|
-
<ConsentDialog className="my-dialog" />
|
|
12
|
-
<ConsentWidget className="my-widget" />
|
|
13
|
-
```
|
|
9
|
+
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.
|
|
14
10
|
|
|
15
11
|
## Per-Slot className
|
|
16
12
|
|
|
@@ -59,9 +55,19 @@ const theme = {
|
|
|
59
55
|
}
|
|
60
56
|
```
|
|
61
57
|
|
|
62
|
-
##
|
|
58
|
+
## When to Use Raw className
|
|
59
|
+
|
|
60
|
+
Use raw className-level styling when:
|
|
61
|
+
|
|
62
|
+
* your styling system is already class-driven
|
|
63
|
+
* tokens are too broad for the change
|
|
64
|
+
* slots already identify the correct element
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
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`.
|
|
67
|
+
|
|
68
|
+
## Advanced: `noStyle`
|
|
69
|
+
|
|
70
|
+
Use `noStyle` only when you want to remove defaults and style from scratch while still keeping c15t's component structure:
|
|
65
71
|
|
|
66
72
|
```tsx
|
|
67
73
|
{/* Remove all styles from a specific component */}
|
|
@@ -81,4 +87,6 @@ const theme = {
|
|
|
81
87
|
} satisfies Theme;
|
|
82
88
|
```
|
|
83
89
|
|
|
90
|
+
Treat `noStyle` as an advanced escape hatch. Do not jump to it just because a token or slot needs debugging.
|
|
91
|
+
|
|
84
92
|
For full custom markup and behavior, continue to [Headless Mode](../headless).
|