@c15t/nextjs 2.2.0 → 3.0.0-alpha.0
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 +102 -142
- package/README.md +4 -4
- package/dist/api.js +1 -0
- package/dist/config.js +1 -0
- package/dist/devtools.js +2 -0
- package/dist/headers.js +1 -0
- package/dist/iab/styles.css +1 -1
- package/dist/iab/styles.tw3.css +133 -19
- package/dist/index.js +1 -1
- package/dist/middleware.js +1 -0
- package/dist/node-bridge.js +1 -0
- package/dist/pages.js +1 -0
- package/dist/proxy.js +1 -0
- package/dist/root.js +2 -0
- package/dist/server.js +1 -0
- package/dist/static.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/styles.tw3.css +173 -29
- package/dist/version.js +1 -1
- package/dist-types/api.d.ts +88 -0
- package/dist-types/config.d.ts +110 -0
- package/dist-types/devtools.d.ts +1 -0
- package/dist-types/headers.d.ts +4 -0
- package/dist-types/index.d.ts +28 -10
- package/dist-types/middleware.d.ts +15 -0
- package/dist-types/node-bridge.d.ts +57 -0
- package/dist-types/pages.d.ts +88 -0
- package/dist-types/proxy.d.ts +34 -0
- package/dist-types/root.d.ts +86 -0
- package/dist-types/server.d.ts +164 -0
- package/dist-types/static.d.ts +42 -0
- package/dist-types/types.d.ts +5 -36
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +102 -142
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/customization/overview.md +45 -0
- package/docs/customization/recipes.md +79 -0
- package/docs/customization/slots.md +55 -0
- package/docs/customization/tokens.md +76 -0
- package/docs/customization/translations.md +49 -0
- package/docs/frameworks/next/api-reference/data-fetching.md +416 -0
- package/docs/frameworks/next/app-router.md +403 -0
- package/docs/frameworks/next/client-side.md +118 -0
- package/docs/frameworks/next/components/consent-banner.md +251 -211
- package/docs/frameworks/next/components/consent-dialog-link.md +96 -35
- package/docs/frameworks/next/components/consent-dialog-trigger.md +74 -149
- package/docs/frameworks/next/components/consent-dialog.md +189 -134
- package/docs/frameworks/next/components/consent-manager-provider.md +60 -318
- package/docs/frameworks/next/components/consent-widget.md +172 -114
- package/docs/frameworks/next/components/dev-tools.md +199 -40
- package/docs/frameworks/next/components/frame.md +137 -42
- package/docs/frameworks/next/concepts/consent-categories.md +24 -89
- package/docs/frameworks/next/concepts/policy-presets.md +142 -0
- package/docs/frameworks/next/content-security-policy.md +189 -0
- package/docs/frameworks/next/data-fetching.md +74 -0
- package/docs/frameworks/next/geography-headers.md +251 -0
- package/docs/frameworks/next/headless.md +95 -185
- package/docs/frameworks/next/hooks/use-consent-manager/overview.md +42 -163
- package/docs/frameworks/next/iab/overview.md +37 -107
- package/docs/frameworks/next/optimization.md +158 -194
- package/docs/frameworks/next/pages-router.md +296 -0
- package/docs/frameworks/next/quickstart.md +31 -132
- package/docs/frameworks/next/script-loader.md +134 -467
- package/docs/frameworks/next/server-side.md +97 -130
- package/docs/frameworks/next/static-export.md +164 -0
- package/docs/frameworks/next/styling/overview.md +166 -250
- package/docs/frameworks/next/troubleshooting.md +134 -144
- package/docs/guides/consent-state.md +60 -0
- package/docs/guides/data-fetching.md +163 -0
- package/docs/guides/deployment-modes.md +63 -0
- package/docs/guides/troubleshooting.md +68 -0
- package/docs/guides/verify-consent.md +62 -0
- package/docs/integrations/adobe-analytics.md +239 -105
- package/docs/integrations/ahrefs-analytics.md +238 -104
- package/docs/integrations/amplitude.md +219 -157
- package/docs/integrations/building-integrations.md +32 -224
- package/docs/integrations/clearbit.md +247 -86
- package/docs/integrations/cloudflare-web-analytics.md +250 -84
- package/docs/integrations/crisp.md +251 -97
- package/docs/integrations/databuddy.md +259 -153
- package/docs/integrations/fathom-analytics.md +239 -96
- package/docs/integrations/google-maps.md +328 -207
- package/docs/integrations/google-tag-manager.md +248 -96
- package/docs/integrations/google-tag.md +261 -90
- package/docs/integrations/heap.md +222 -149
- package/docs/integrations/hightouch.md +225 -131
- package/docs/integrations/hotjar.md +239 -90
- package/docs/integrations/intercom.md +239 -98
- package/docs/integrations/linkedin-insights.md +243 -113
- package/docs/integrations/logrocket.md +241 -123
- package/docs/integrations/matomo-analytics.md +256 -111
- package/docs/integrations/meta-pixel.md +197 -324
- package/docs/integrations/microsoft-clarity.md +233 -114
- package/docs/integrations/microsoft-uet.md +245 -110
- package/docs/integrations/mixpanel-analytics.md +252 -87
- package/docs/integrations/openai-pixel.md +441 -0
- package/docs/integrations/overview.md +95 -133
- package/docs/integrations/pirsch.md +249 -96
- package/docs/integrations/plausible-analytics.md +241 -100
- package/docs/integrations/posthog.md +353 -214
- package/docs/integrations/promptwatch.md +251 -81
- package/docs/integrations/reddit-pixel.md +226 -173
- package/docs/integrations/rudderstack.md +244 -187
- package/docs/integrations/rybbit-analytics.md +244 -91
- package/docs/integrations/segment.md +238 -92
- package/docs/integrations/snapchat-pixel.md +240 -110
- package/docs/integrations/tiktok-pixel.md +249 -81
- package/docs/integrations/umami-analytics.md +242 -95
- package/docs/integrations/vercel-analytics.md +242 -90
- package/docs/integrations/x-pixel.md +238 -104
- package/docs/integrations/youtube.md +354 -142
- package/docs/upgrade-v3.md +334 -0
- package/iab/styles.css +1 -1
- package/iab/styles.tw3.css +1 -1
- package/package.json +106 -65
- package/readme.json +3 -3
- package/src/iab/styles.css +1 -1
- package/src/iab/styles.tw3.css +1 -1
- package/src/styles.css +1 -1
- package/src/styles.tw3.css +1 -1
- package/styles.css +1 -1
- package/styles.tw3.css +1 -1
- package/client/components/consent-dialog-link.js +0 -3
- package/client/components/integrations.js +0 -3
- package/dist/components/integrations/index.cjs +0 -1
- package/dist/components/integrations/index.js +0 -1
- package/dist/headless.cjs +0 -1
- package/dist/index.cjs +0 -1
- package/dist/libs/browser-initial-data.cjs +0 -1
- package/dist/libs/browser-initial-data.js +0 -1
- package/dist/libs/initial-data.cjs +0 -1
- package/dist/libs/initial-data.js +0 -1
- package/dist/types.cjs +0 -1
- package/dist/version.cjs +0 -1
- package/dist-types/components/integrations/index.d.ts +0 -1
- package/dist-types/libs/browser-initial-data.d.ts +0 -9
- package/dist-types/libs/initial-data.d.ts +0 -33
- package/docs/frameworks/next/building-headless-components.md +0 -379
- package/docs/frameworks/next/callbacks.md +0 -186
- package/docs/frameworks/next/concepts/client-modes.md +0 -177
- package/docs/frameworks/next/concepts/consent-models.md +0 -117
- package/docs/frameworks/next/concepts/cookie-management.md +0 -122
- package/docs/frameworks/next/concepts/glossary.md +0 -24
- package/docs/frameworks/next/concepts/initialization-flow.md +0 -149
- package/docs/frameworks/next/concepts/policy-packs.md +0 -230
- package/docs/frameworks/next/hooks/use-color-scheme.md +0 -41
- package/docs/frameworks/next/hooks/use-consent-manager/checking-consent.md +0 -96
- package/docs/frameworks/next/hooks/use-consent-manager/location-info.md +0 -97
- package/docs/frameworks/next/hooks/use-consent-manager/setting-consent.md +0 -94
- package/docs/frameworks/next/hooks/use-draggable.md +0 -59
- package/docs/frameworks/next/hooks/use-focus-trap.md +0 -42
- package/docs/frameworks/next/hooks/use-reduced-motion.md +0 -37
- package/docs/frameworks/next/hooks/use-ssr-status.md +0 -32
- package/docs/frameworks/next/hooks/use-text-direction.md +0 -50
- package/docs/frameworks/next/hooks/use-translations.md +0 -55
- package/docs/frameworks/next/iab/consent-banner.md +0 -91
- package/docs/frameworks/next/iab/consent-dialog.md +0 -129
- package/docs/frameworks/next/iab/use-gvl-data.md +0 -21
- package/docs/frameworks/next/iframe-blocking.md +0 -106
- package/docs/frameworks/next/internationalization.md +0 -207
- package/docs/frameworks/next/network-blocker.md +0 -140
- package/docs/frameworks/next/policy-packs.md +0 -248
- package/docs/frameworks/next/styling/classnames.md +0 -94
- package/docs/frameworks/next/styling/color-scheme.md +0 -84
- package/docs/frameworks/next/styling/css-variables.md +0 -53
- package/docs/frameworks/next/styling/slots.md +0 -94
- package/docs/frameworks/next/styling/tailwind.md +0 -137
- package/docs/frameworks/next/styling/tokens.md +0 -156
- package/docs/shared/concepts/client-modes.md +0 -103
- package/docs/shared/concepts/consent-categories.md +0 -41
- package/docs/shared/concepts/consent-models.md +0 -72
- package/docs/shared/concepts/cookie-management.md +0 -88
- package/docs/shared/concepts/glossary.md +0 -24
- package/docs/shared/concepts/initialization-flow.md +0 -105
- package/docs/shared/concepts/policy-packs.md +0 -225
- package/docs/shared/react/components/consent-banner.md +0 -242
- package/docs/shared/react/components/consent-dialog-link.md +0 -45
- package/docs/shared/react/components/consent-dialog-trigger.md +0 -185
- package/docs/shared/react/components/consent-dialog.md +0 -119
- package/docs/shared/react/components/consent-manager-provider.md +0 -225
- package/docs/shared/react/components/consent-widget.md +0 -121
- package/docs/shared/react/components/dev-tools.md +0 -81
- package/docs/shared/react/components/frame.md +0 -52
- package/docs/shared/react/guides/building-headless-components.md +0 -110
- package/docs/shared/react/guides/callbacks.md +0 -89
- package/docs/shared/react/guides/headless.md +0 -31
- package/docs/shared/react/guides/iframe-blocking.md +0 -65
- package/docs/shared/react/guides/internationalization.md +0 -123
- package/docs/shared/react/guides/network-blocker.md +0 -72
- package/docs/shared/react/guides/optimization.md +0 -44
- package/docs/shared/react/guides/policy-packs.md +0 -173
- package/docs/shared/react/guides/script-loader.md +0 -311
- package/docs/shared/react/hooks/use-color-scheme.md +0 -31
- package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +0 -95
- package/docs/shared/react/hooks/use-consent-manager/location-info.md +0 -96
- package/docs/shared/react/hooks/use-consent-manager/overview.md +0 -74
- package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +0 -93
- package/docs/shared/react/hooks/use-draggable.md +0 -30
- package/docs/shared/react/hooks/use-focus-trap.md +0 -20
- package/docs/shared/react/hooks/use-reduced-motion.md +0 -33
- package/docs/shared/react/hooks/use-ssr-status.md +0 -16
- package/docs/shared/react/hooks/use-text-direction.md +0 -38
- package/docs/shared/react/hooks/use-translations.md +0 -15
- package/docs/shared/react/iab/consent-banner.md +0 -60
- package/docs/shared/react/iab/consent-dialog.md +0 -76
- package/docs/shared/react/iab/overview.md +0 -80
- package/docs/shared/react/iab/use-gvl-data.md +0 -21
- package/docs/shared/react/styling/classnames.md +0 -93
- package/docs/shared/react/styling/color-scheme.md +0 -35
- package/docs/shared/react/styling/css-variables.md +0 -53
- package/docs/shared/react/styling/overview.md +0 -261
- package/docs/shared/react/styling/slots.md +0 -93
- package/docs/shared/react/styling/stylesheet-entrypoint.md +0 -8
- package/docs/shared/react/styling/tailwind.md +0 -88
- package/docs/shared/react/styling/tokens.md +0 -155
- package/docs/shared/troubleshooting.md +0 -82
|
@@ -1,62 +1,123 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: ConsentDialogLink
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: Open the preference center from a Next.js footer with
|
|
4
|
+
ConsentDialogLink, a Client Component that renders an unstyled button inside
|
|
5
|
+
ConsentRoot.
|
|
5
6
|
group: frameworks
|
|
6
7
|
---
|
|
7
|
-
`ConsentDialogLink` is an inline trigger for opening the consent dialog from places like site footers, legal pages, or account settings. It is unstyled by default, so it inherits your app's typography and link/button styles.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Reopen the preference center from your footer
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
`ConsentDialogLink` is an unstyled button that opens the consent dialog.
|
|
12
|
+
Put it where your site already keeps its legal links, so preferences stay
|
|
13
|
+
reachable after the banner closes. It is a Client Component and must render
|
|
14
|
+
inside the `ConsentRoot` from your
|
|
15
|
+
[App Router](../app-router.md) or
|
|
16
|
+
[Pages Router](../pages-router.md) setup, which also mounts
|
|
17
|
+
the `ConsentDialog` it opens.
|
|
18
|
+
|
|
19
|
+
```tsx title="components/site-footer.tsx"
|
|
20
|
+
'use client';
|
|
21
|
+
|
|
22
|
+
import Link from 'next/link';
|
|
23
|
+
import { ConsentDialogLink } from 'c15t/next';
|
|
13
24
|
|
|
14
25
|
export function SiteFooter() {
|
|
15
26
|
return (
|
|
16
27
|
<footer>
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
<nav aria-label="Legal">
|
|
29
|
+
<Link href="/privacy">Privacy policy</Link>
|
|
30
|
+
<Link href="/terms">Terms</Link>
|
|
31
|
+
<ConsentDialogLink className="footer-link">Privacy settings</ConsentDialogLink>
|
|
32
|
+
</nav>
|
|
20
33
|
</footer>
|
|
21
34
|
);
|
|
22
35
|
}
|
|
23
36
|
```
|
|
24
37
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Your privacy settings
|
|
31
|
-
</ConsentDialogLink>
|
|
32
|
-
</footer>
|
|
33
|
-
```
|
|
38
|
+
Render `SiteFooter` from the root layout as a child of the `Consent`
|
|
39
|
+
wrapper, in place of the inline footer the router guides show. The layout
|
|
40
|
+
stays a Server Component; only this file needs `'use client'`. The link
|
|
41
|
+
renders a `button`, so the CSS for `.footer-link` should reset button chrome
|
|
42
|
+
if your footer styles target anchors only.
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Use `asChild` to keep semantic anchor markup while still opening the dialog:
|
|
44
|
+
To reuse an existing link component, pass `asChild`:
|
|
38
45
|
|
|
39
46
|
```tsx
|
|
40
47
|
<ConsentDialogLink asChild>
|
|
41
|
-
<a href="#
|
|
48
|
+
<a href="#cookie-preferences">Manage cookies</a>
|
|
42
49
|
</ConsentDialogLink>
|
|
43
50
|
```
|
|
44
51
|
|
|
45
|
-
##
|
|
52
|
+
## Props
|
|
46
53
|
|
|
47
|
-
|
|
54
|
+
| Prop | Type | Default | Description |
|
|
55
|
+
| ---------- | ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `children` | `ReactNode` | required | The visible label, such as "Privacy settings" or "Manage preferences". It is also the accessible name. |
|
|
57
|
+
| `asChild` | `boolean` | `false` | Renders your own element, such as an anchor, instead of a `button`, and attaches the click handler to it. |
|
|
58
|
+
| `noStyle` | `boolean` | `true` | Omits c15t button classes. Native browser styles remain unless your CSS resets them. Pass `false` to render it as a consent button with `variant` and `mode`. |
|
|
59
|
+
| `onClick` | `(event) => void` | none | Runs before the dialog opens. Call `event.preventDefault()` to keep it closed. |
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Privacy Settings
|
|
52
|
-
</ConsentDialogLink>
|
|
53
|
-
```
|
|
61
|
+
Other `button` attributes such as `className`, `style`, `id` and `aria-*`
|
|
62
|
+
pass through to the rendered element.
|
|
54
63
|
|
|
55
|
-
##
|
|
64
|
+
## Behavior
|
|
65
|
+
|
|
66
|
+
`ConsentDialogLink` renders a `button` with `type="button"` and no c15t
|
|
67
|
+
styling by default. Clicking it makes `dialog` the active surface, which opens a
|
|
68
|
+
mounted `ConsentDialog`. It performs no save and does not change any
|
|
69
|
+
permission.
|
|
70
|
+
|
|
71
|
+
The element carries `data-c15t-rights` listing the rights of the active
|
|
72
|
+
policy rule, for example `disclosure opt-out preferences` under a US
|
|
73
|
+
opt-out rule and `disclosure preferences` under an opt-in rule, so a
|
|
74
|
+
stylesheet or a `::after` label can adapt the wording by region.
|
|
75
|
+
|
|
76
|
+
Without a resolved policy rule the link renders nothing and appears as soon
|
|
77
|
+
as a rule resolves, without a remount. A rule with `model: 'none'` and an
|
|
78
|
+
empty `rights` list owes no consent UI, so the link hides under it; a `none`
|
|
79
|
+
rule that lists any right, such as `['disclosure']`, shows the link and the
|
|
80
|
+
dialog opens as a settings route.
|
|
81
|
+
|
|
82
|
+
Mount exactly one `ConsentDialog` inside the same provider. If none is
|
|
83
|
+
mounted, the click still switches the active surface: nothing opens, and a
|
|
84
|
+
banner that was showing closes because the surface is no longer `banner`.
|
|
85
|
+
|
|
86
|
+
With `asChild`, the child's own `onClick` runs first; if it calls
|
|
87
|
+
`event.preventDefault()` the dialog stays closed. c15t does not prevent the
|
|
88
|
+
child's native behavior, so an anchor still follows its `href`. Use a
|
|
89
|
+
fragment or the current page as the destination, or render a `button`.
|
|
90
|
+
|
|
91
|
+
### ConsentDialogLink or ConsentDialogTrigger
|
|
92
|
+
|
|
93
|
+
Both open the same dialog and carry `data-c15t-rights`. Use
|
|
94
|
+
`ConsentDialogLink` where the control belongs in your own layout: a footer,
|
|
95
|
+
a privacy page, a settings menu. It has no position, icon or visibility
|
|
96
|
+
rule of its own. Use `ConsentDialogTrigger` when you want a floating,
|
|
97
|
+
draggable button that positions itself in a corner and can wait until the
|
|
98
|
+
prompt is answered.
|
|
99
|
+
|
|
100
|
+
`ConsentDialogTrigger` has its own page: [ConsentDialogTrigger](./consent-dialog-trigger.md).
|
|
101
|
+
|
|
102
|
+
## Accessibility
|
|
103
|
+
|
|
104
|
+
The rendered `button` is keyboard-focusable and activates with Enter and
|
|
105
|
+
Space; its accessible name is the text you pass as `children`, so give it
|
|
106
|
+
words that describe the destination rather than "click here". Because the
|
|
107
|
+
dialog it opens is labelled by its own title and, while blocking, returns
|
|
108
|
+
focus to the link on close, no additional `aria-haspopup` or
|
|
109
|
+
`aria-controls` is added; a non-blocking dialog manages no focus, so the
|
|
110
|
+
link does not regain it. With `asChild`,
|
|
111
|
+
focusability comes from your element: use a `button` or an anchor with an
|
|
112
|
+
`href`.
|
|
56
113
|
|
|
57
|
-
|
|
58
|
-
|:--|:--|
|
|
59
|
-
|Type Name|\`ConsentDialogLinkProps\`|
|
|
60
|
-
|Source Path|\`./packages/react/src/components/consent-preferences-link/consent-preferences-link.tsx\`|
|
|
114
|
+
## Verify
|
|
61
115
|
|
|
62
|
-
|
|
116
|
+
Scroll to the footer. With the footer button reset applied, the link uses
|
|
117
|
+
your footer's text styles and has no button chrome. Activate it with a click or with Enter: the preference
|
|
118
|
+
center opens as a centered dialog. Close it with Escape: with the default
|
|
119
|
+
blocking dialog, focus returns to the link. In your browser's element
|
|
120
|
+
inspector the link has
|
|
121
|
+
`data-c15t-rights`; change the visitor's region to a US opt-out rule and
|
|
122
|
+
the value includes `opt-out`. Under a rule with `model: 'none'` and no
|
|
123
|
+
rights, the link is absent.
|
|
@@ -1,44 +1,54 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: ConsentDialogTrigger
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: Add the floating ConsentDialogTrigger button or toolbar to a
|
|
4
|
+
Next.js ConsentRoot so visitors can reopen the preference center.
|
|
5
5
|
group: frameworks
|
|
6
6
|
---
|
|
7
|
-
`ConsentDialogTrigger` is a floating button that opens the consent dialog when clicked. Users can drag it to any corner of the screen, and the position persists across sessions. Use it to give users a persistent way to manage their privacy settings.
|
|
8
7
|
|
|
9
|
-
##
|
|
8
|
+
## Usage
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
`ConsentDialogTrigger` is a draggable floating button that opens the preference center. Place it once, next to the banner and dialog, so visitors can revisit their choices without a footer link.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
Keep the boundary, stylesheet and transport from your
|
|
13
|
+
[router setup](../quickstart.md). Add this component as a child
|
|
14
|
+
of the existing boundary, alongside its banner and dialog:
|
|
15
|
+
|
|
16
|
+
```tsx title="components/privacy-trigger.tsx"
|
|
17
|
+
'use client';
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
<ConsentDialogTrigger />
|
|
19
|
+
import { ConsentDialogTrigger } from 'c15t/next';
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
+
export function PrivacyTrigger() {
|
|
22
|
+
return <ConsentDialogTrigger showWhen="after-prompt" />;
|
|
23
|
+
}
|
|
21
24
|
```
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
`showWhen="after-prompt"` keeps the button out of the way while a choice or notice is still owed and shows it once the visitor has answered, so the banner and the trigger never compete for the same corner. The default, `always`, shows it whenever the preference center is closed.
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
The button carries `data-c15t-rights` with the rights the active policy guarantees, so a stylesheet can label it differently under an opt-out rule.
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
{/* Built-in icons */}
|
|
29
|
-
<ConsentDialogTrigger icon="branding" /> {/* c15t logo (default) */}
|
|
30
|
-
<ConsentDialogTrigger icon="fingerprint" /> {/* Privacy icon */}
|
|
31
|
-
<ConsentDialogTrigger icon="settings" /> {/* Gear icon */}
|
|
30
|
+
## Props
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
| Prop | Type | Default | Description |
|
|
33
|
+
| ----------------- | ----------------------------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------- |
|
|
34
|
+
| `icon` | `'branding' \|'fingerprint' \|'settings' \|ReactNode` | `'branding'` | Icon rendered inside the button. |
|
|
35
|
+
| `defaultPosition` | `'bottom-left' \|'bottom-right' \|'top-left' \|'top-right'` | `'bottom-right'` | Corner the button starts in. |
|
|
36
|
+
| `persistPosition` | `boolean` | `true` | Remember the corner the visitor dragged it to. |
|
|
37
|
+
| `showWhen` | `'always' \|'after-prompt' \|'never'` | `'always'` | When the button is visible. `after-prompt` waits until no choice or notice is owed. |
|
|
38
|
+
| `size` | `'sm' \|'md' \|'lg'` | `'md'` | Button size. |
|
|
39
|
+
| `ariaLabel` | `string` | `'Open privacy settings'` | Accessible name. |
|
|
40
|
+
| `noStyle` | `boolean` | `false` | Remove the default styling. |
|
|
41
|
+
|
|
42
|
+
## Configurable toolbar
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
Use `ConsentDialogTriggerToolbar` when you want app-owned controls beside the privacy trigger. It always renders exactly one built-in action that opens the preference center, so `actions` only holds controls your app owns.
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
This partial example belongs in a Client Component inside the existing boundary.
|
|
47
|
+
Define the theme state, icons and callbacks in that component.
|
|
40
48
|
|
|
41
49
|
```tsx
|
|
50
|
+
import { ConsentDialogTriggerToolbar } from 'c15t/next';
|
|
51
|
+
|
|
42
52
|
<ConsentDialogTriggerToolbar
|
|
43
53
|
ariaLabel="Site controls"
|
|
44
54
|
actions={[
|
|
@@ -63,140 +73,55 @@ Use the separate `ConsentDialogTriggerToolbar` when you want to place app-owned
|
|
|
63
73
|
/>
|
|
64
74
|
```
|
|
65
75
|
|
|
66
|
-
Each custom action
|
|
67
|
-
|
|
68
|
-
Toolbars are horizontal by default. Set `orientation="vertical"` to stack the actions and enable Up/Down arrow-key navigation:
|
|
69
|
-
|
|
70
|
-
```tsx
|
|
71
|
-
<ConsentDialogTriggerToolbar
|
|
72
|
-
orientation="vertical"
|
|
73
|
-
actions={toolbarActions}
|
|
74
|
-
/>
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Toolbar Styling
|
|
78
|
-
|
|
79
|
-
The toolbar follows the standard styling precedence: internal CSS module styles, provider theme slots, then direct component overrides. Use `className` and `style` on the toolbar, or on an individual action, and use `noStyle` for a fully custom implementation.
|
|
80
|
-
|
|
81
|
-
```tsx
|
|
82
|
-
<ConsentManagerProvider
|
|
83
|
-
options={{
|
|
84
|
-
theme: {
|
|
85
|
-
slots: {
|
|
86
|
-
consentDialogTriggerToolbar: 'my-toolbar',
|
|
87
|
-
consentDialogTriggerToolbarItem: 'my-toolbar-item',
|
|
88
|
-
consentDialogTriggerToolbarIcon: 'my-toolbar-icon',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
}}
|
|
92
|
-
>
|
|
93
|
-
<ConsentDialogTriggerToolbar
|
|
94
|
-
className="fixed-toolbar"
|
|
95
|
-
style={{ '--cdtt-offset': '24px' }}
|
|
96
|
-
actions={[
|
|
97
|
-
{
|
|
98
|
-
id: 'support',
|
|
99
|
-
label: 'Open support chat',
|
|
100
|
-
icon: <ChatIcon />,
|
|
101
|
-
onSelect: openSupportChat,
|
|
102
|
-
className: 'support-action',
|
|
103
|
-
},
|
|
104
|
-
]}
|
|
105
|
-
/>
|
|
106
|
-
</ConsentManagerProvider>
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Available toolbar theme slots are `consentDialogTriggerToolbar`, `consentDialogTriggerToolbarItem`, and `consentDialogTriggerToolbarIcon`.
|
|
110
|
-
|
|
111
|
-
With `noStyle`, use `data-corner`, `data-dragging`, and `data-snapping` on the toolbar to style its current position and interaction state.
|
|
112
|
-
|
|
113
|
-
## Visibility
|
|
114
|
-
|
|
115
|
-
Control when the trigger is visible:
|
|
76
|
+
Each custom action needs a stable `id`, an accessible `label`, an `icon`, and an `onSelect` callback. Use `pressed` for toggle actions and `disabled` for unavailable ones. Your app owns the state behind each action. The preferences action moves to the edge nearest the toolbar's snapped corner while custom actions keep their configured order.
|
|
116
77
|
|
|
117
|
-
|
|
118
|
-
{/* Always visible (default) */}
|
|
119
|
-
<ConsentDialogTrigger showWhen="always" />
|
|
120
|
-
|
|
121
|
-
{/* Only after user has made a consent choice */}
|
|
122
|
-
<ConsentDialogTrigger showWhen="after-consent" />
|
|
123
|
-
|
|
124
|
-
{/* Hidden (control visibility programmatically) */}
|
|
125
|
-
<ConsentDialogTrigger showWhen="never" />
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Position
|
|
78
|
+
The toolbar does not depend on the consent policy. Your actions always render, so a theme toggle stays available while a banner is up. On the toolbar, `showWhen` applies only to the built-in preferences action: `after-prompt` hides that one item while a choice or notice is owed and shows it once the visitor has answered, and `never` leaves it out. The toolbar renders nothing only when it has no visible item. On the single `ConsentDialogTrigger`, `showWhen` applies to the whole control.
|
|
129
79
|
|
|
130
|
-
|
|
80
|
+
No policy, no UI. When no rule has resolved, because resolution failed, no rule matched and you set no default, or init is still withheld, the built-in preferences action and the single `ConsentDialogTrigger` render nothing; app-owned toolbar actions still do. They appear as soon as a rule resolves, without a remount. A rule with `model: 'none'` owes no rights, so the built-in action and the single trigger hide under it too, unless the rule adds `rights: ['preferences']`. The policy chooses what the control says, you choose where and when it sits, and it disappears only when there is nothing to manage.
|
|
131
81
|
|
|
132
|
-
|
|
133
|
-
<ConsentDialogTrigger
|
|
134
|
-
defaultPosition="bottom-left"
|
|
135
|
-
persistPosition={true} // Remembers user's drag position
|
|
136
|
-
onPositionChange={(position) => console.log('Moved to:', position)}
|
|
137
|
-
/>
|
|
138
|
-
```
|
|
82
|
+
The built-in action names the strongest right the active rule guarantees. Under a rule that carries the `opt-out` right, such as a US opt-out notice, its accessible name is the translated "Do not sell or share my data" and the button carries `data-right="opt-out"`. Under any other rule it reads "Manage preferences" with `data-right="preferences"`. Either way it opens the preference center, and a `preferences.label` you pass replaces the default. The button also carries `data-c15t-rights` with every right on the rule.
|
|
139
83
|
|
|
140
|
-
|
|
84
|
+
Toolbars are horizontal by default. Set `orientation="vertical"` to stack the actions and switch arrow-key navigation to up and down:
|
|
141
85
|
|
|
142
86
|
```tsx
|
|
143
|
-
<
|
|
144
|
-
<ConsentDialogTrigger size="md" /> {/* Medium (default) */}
|
|
145
|
-
<ConsentDialogTrigger size="lg" /> {/* Large */}
|
|
87
|
+
<ConsentDialogTriggerToolbar orientation="vertical" actions={toolbarActions} />
|
|
146
88
|
```
|
|
147
89
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
90
|
+
### Toolbar props
|
|
91
|
+
|
|
92
|
+
| Prop | Type | Default | Description |
|
|
93
|
+
| ----------------- | ---------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
94
|
+
| `actions` | `ConsentDialogTriggerToolbarAction[]` | `[]` | App-owned actions rendered beside the preferences action. |
|
|
95
|
+
| `preferences` | `ConsentDialogTriggerToolbarPreferences` | `{}` | Overrides for the built-in action: `icon`, `label`, `onSelect`, `className`, `style`. The label defaults to the opt-out or preferences right on the active rule. |
|
|
96
|
+
| `orientation` | `'horizontal' \|'vertical'` | `'horizontal'` | Layout direction. |
|
|
97
|
+
| `defaultPosition` | `CornerPosition` | `'bottom-right'` | Corner the toolbar starts in. |
|
|
98
|
+
| `persistPosition` | `boolean` | `true` | Remember the dragged corner. |
|
|
99
|
+
| `showWhen` | `'always' \|'after-prompt' \|'never'` | `'always'` | When the built-in preferences action is visible. App-owned actions always render. `after-prompt` waits until no choice or notice is owed. |
|
|
100
|
+
| `size` | `'sm' \|'md' \|'lg'` | `'md'` | Size of each action. |
|
|
101
|
+
| `ariaLabel` | `string` | `'Privacy controls'` | Accessible name for the toolbar group. |
|
|
102
|
+
| `noStyle` | `boolean` | `false` | Remove the default styling. |
|
|
103
|
+
|
|
104
|
+
### Toolbar styling
|
|
105
|
+
|
|
106
|
+
The toolbar follows the standard precedence: bundled styles, then provider slots, then direct `className` and `style` on the toolbar or on one action. Use `noStyle` for a fully custom implementation.
|
|
107
|
+
|
|
108
|
+
Add these slot values to `options.components` on your existing
|
|
109
|
+
`ConsentRoot` or `ConsentProvider`. Merge them with any existing component
|
|
110
|
+
slots and retain the configured transport:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const triggerSlots = {
|
|
114
|
+
toolbar: { className: 'my-toolbar' },
|
|
115
|
+
toolbarItem: { className: 'my-toolbar-item' },
|
|
116
|
+
toolbarIcon: { className: 'my-toolbar-icon' },
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// In the existing options.components object:
|
|
120
|
+
// trigger: triggerSlots
|
|
159
121
|
```
|
|
160
122
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
* `ConsentDialogTrigger.Text` — Optional text label
|
|
165
|
-
|
|
166
|
-
## Props
|
|
167
|
-
|
|
168
|
-
### ConsentDialogTrigger
|
|
169
|
-
|
|
170
|
-
|Property|Value|
|
|
171
|
-
|:--|:--|
|
|
172
|
-
|Type Name|\`ConsentDialogTriggerProps\`|
|
|
173
|
-
|Source Path|\`./packages/react/src/components/consent-dialog-trigger/types.ts\`|
|
|
174
|
-
|
|
175
|
-
\*ExtractedTypeTable: Could not extract "ConsentDialogTriggerProps" from "./packages/react/src/components/consent-dialog-trigger/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
176
|
-
|
|
177
|
-
### ConsentDialogTriggerToolbar
|
|
178
|
-
|
|
179
|
-
|Property|Value|
|
|
180
|
-
|:--|:--|
|
|
181
|
-
|Type Name|\`ConsentDialogTriggerToolbarProps\`|
|
|
182
|
-
|Source Path|\`./packages/react/src/components/consent-dialog-trigger/types.ts\`|
|
|
183
|
-
|
|
184
|
-
\*ExtractedTypeTable: Could not extract "ConsentDialogTriggerToolbarProps" from "./packages/react/src/components/consent-dialog-trigger/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
185
|
-
|
|
186
|
-
### Toolbar Actions
|
|
187
|
-
|
|
188
|
-
|Property|Value|
|
|
189
|
-
|:--|:--|
|
|
190
|
-
|Type Name|\`ConsentDialogTriggerToolbarAction\`|
|
|
191
|
-
|Source Path|\`./packages/react/src/components/consent-dialog-trigger/types.ts\`|
|
|
192
|
-
|
|
193
|
-
\*ExtractedTypeTable: Could not extract "ConsentDialogTriggerToolbarAction" from "./packages/react/src/components/consent-dialog-trigger/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
194
|
-
|
|
195
|
-
### Preferences Action
|
|
196
|
-
|
|
197
|
-
|Property|Value|
|
|
198
|
-
|:--|:--|
|
|
199
|
-
|Type Name|\`ConsentDialogTriggerToolbarPreferences\`|
|
|
200
|
-
|Source Path|\`./packages/react/src/components/consent-dialog-trigger/types.ts\`|
|
|
123
|
+
For one toolbar, pass `className="fixed-toolbar"` directly. Each app-owned
|
|
124
|
+
item also accepts `className`, such as `className: 'support-action'` on your
|
|
125
|
+
support action. Keep its icon and callback in the Client Component.
|
|
201
126
|
|
|
202
|
-
|
|
127
|
+
The toolbar slot keys are `trigger.toolbar`, `trigger.toolbarItem`, and `trigger.toolbarIcon`. With `noStyle`, style the current position and interaction state through `data-corner`, `data-dragging`, and `data-snapping` on the toolbar element.
|