@xenterprises/nuxt-x-marketing 1.0.2 → 1.1.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.
Files changed (64) hide show
  1. package/README.md +130 -11
  2. package/app/components/X/Mark/CodeBlock/index.vue +19 -7
  3. package/app/components/X/Mark/Divider/Glow.vue +25 -19
  4. package/app/components/X/Mark/Section/Stitch.vue +45 -31
  5. package/app/composables/{useParallax.ts → useParallax.js} +6 -7
  6. package/app/composables/{useScrollReveal.ts → useScrollReveal.js} +4 -4
  7. package/nuxt.config.ts +1 -11
  8. package/package.json +1 -1
  9. package/.claude/settings.local.json +0 -23
  10. package/.nuxtrc +0 -1
  11. package/.playground/app.config.ts +0 -74
  12. package/.playground/app.vue +0 -269
  13. package/.playground/components/AppFooter.vue +0 -103
  14. package/.playground/components/AppHeader.vue +0 -41
  15. package/.playground/components/CodeExample.vue +0 -70
  16. package/.playground/components/ComponentPlayground.vue +0 -117
  17. package/.playground/components/DocsHeader.vue +0 -19
  18. package/.playground/layouts/default.vue +0 -15
  19. package/.playground/layouts/docs-layout.vue +0 -161
  20. package/.playground/layouts/docs.vue +0 -11
  21. package/.playground/nuxt.config.ts +0 -5
  22. package/.playground/package-lock.json +0 -6
  23. package/.playground/pages/blog/author.vue +0 -145
  24. package/.playground/pages/blog/card.vue +0 -149
  25. package/.playground/pages/blog/cta.vue +0 -131
  26. package/.playground/pages/blog/detail.vue +0 -471
  27. package/.playground/pages/blog/list.vue +0 -261
  28. package/.playground/pages/blog/navigation.vue +0 -228
  29. package/.playground/pages/blog/sidebar.vue +0 -279
  30. package/.playground/pages/config.vue +0 -289
  31. package/.playground/pages/content/comparison.vue +0 -253
  32. package/.playground/pages/content/cta.vue +0 -245
  33. package/.playground/pages/content/features.vue +0 -217
  34. package/.playground/pages/content/newsletter-section.vue +0 -260
  35. package/.playground/pages/content/newsletter.vue +0 -200
  36. package/.playground/pages/content/pricing.vue +0 -335
  37. package/.playground/pages/content/testimonials.vue +0 -188
  38. package/.playground/pages/hero.vue +0 -257
  39. package/.playground/pages/index.vue +0 -381
  40. package/.playground/pages/layout/footer.vue +0 -210
  41. package/.playground/pages/layout/legal-footer.vue +0 -121
  42. package/.playground/pages/layout/navbar.vue +0 -285
  43. package/.playground/pages/layout/section.vue +0 -266
  44. package/.playground/pages/layout/x-legal.vue +0 -199
  45. package/.playground/pages/modals/feature-modal.vue +0 -320
  46. package/.playground/pages/modals/image-lightbox.vue +0 -277
  47. package/.playground/pages/modals/video-modal.vue +0 -222
  48. package/.playground/pages/notifications/announcement-bar.vue +0 -164
  49. package/.playground/pages/notifications/cookie-banner.vue +0 -210
  50. package/.playground/pages/notifications/cookie-toast.vue +0 -143
  51. package/.playground/pages/notifications/gdpr.vue +0 -276
  52. package/.playground/pages/notifications/social-proof-toast.vue +0 -515
  53. package/.playground/pages/ui/badge.vue +0 -161
  54. package/.playground/pages/ui/bg-pattern.vue +0 -177
  55. package/.playground/pages/ui/glass-card.vue +0 -179
  56. package/.playground/pages/ui/glow-divider.vue +0 -179
  57. package/.playground/pages/ui/promo-card.vue +0 -259
  58. package/.playground/pages/ui/section-stitch.vue +0 -411
  59. package/.playground/pages/utilities/back-to-top.vue +0 -153
  60. package/.playground/pages/utilities/popup-chat.vue +0 -224
  61. package/componentList.json +0 -2129
  62. package/screenshots/playground-home.png +0 -0
  63. package/tsconfig.json +0 -3
  64. /package/app/composables/{useXBlog.ts → useXBlog.js} +0 -0
@@ -1,222 +0,0 @@
1
- <template>
2
- <div class="min-h-screen">
3
- <div class="bg-white dark:bg-neutral-900 border-b border-neutral-200 dark:border-neutral-800 px-8 py-6">
4
- <h1 class="text-2xl font-bold text-neutral-900 dark:text-white">Video Modal</h1>
5
- <p class="mt-2 text-neutral-600 dark:text-neutral-400">Cinematic video modal with built-in triggers, multiple sizes, and dark overlay.</p>
6
- </div>
7
-
8
- <div class="p-8 space-y-12">
9
- <!-- Thumbnail Trigger -->
10
- <section>
11
- <h2 class="text-lg font-semibold mb-4">Thumbnail Trigger</h2>
12
- <p class="text-sm text-neutral-500 mb-4">Click the thumbnail to open the video modal. Play button overlay is automatic.</p>
13
- <div class="max-w-lg">
14
- <XMarkModalVideo
15
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
16
- thumbnail="https://images.unsplash.com/photo-1611162617474-5b21e879e113?w=600&h=340&fit=crop"
17
- title="Sample YouTube Video"
18
- description="YouTube videos are automatically embedded with autoplay support."
19
- />
20
- </div>
21
- </section>
22
-
23
- <!-- Modal Sizes -->
24
- <section>
25
- <h2 class="text-lg font-semibold mb-4">Modal Sizes</h2>
26
- <p class="text-sm text-neutral-500 mb-4">Control the modal width with the size prop.</p>
27
- <div class="flex flex-wrap gap-4">
28
- <XMarkModalVideo
29
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
30
- size="2xl"
31
- :button="{ label: 'Size 2xl' }"
32
- />
33
- <XMarkModalVideo
34
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
35
- size="4xl"
36
- :button="{ label: 'Size 4xl (default)' }"
37
- />
38
- <XMarkModalVideo
39
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
40
- size="6xl"
41
- :button="{ label: 'Size 6xl' }"
42
- />
43
- <XMarkModalVideo
44
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
45
- size="full"
46
- :button="{ label: 'Size full (95vw)' }"
47
- />
48
- </div>
49
- </section>
50
-
51
- <!-- Button Object -->
52
- <section>
53
- <h2 class="text-lg font-semibold mb-4">Button Object</h2>
54
- <p class="text-sm text-neutral-500 mb-4">Configure the trigger button with a single object prop.</p>
55
- <div class="flex flex-wrap gap-4">
56
- <XMarkModalVideo
57
- src="https://vimeo.com/76979871"
58
- title="Vimeo Video"
59
- :button="{ label: 'Watch Vimeo', color: 'primary' }"
60
- />
61
- <XMarkModalVideo
62
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
63
- :button="{ label: 'Play Video', color: 'secondary', variant: 'outline' }"
64
- />
65
- <XMarkModalVideo
66
- src="https://www.w3schools.com/html/mov_bbb.mp4"
67
- title="Direct Video"
68
- :button="{ label: 'View Demo', color: 'neutral', size: 'lg', icon: 'i-lucide-video' }"
69
- :autoplay="false"
70
- />
71
- </div>
72
- </section>
73
-
74
- <!-- Custom Trigger -->
75
- <section>
76
- <h2 class="text-lg font-semibold mb-4">Custom Trigger (Slot)</h2>
77
- <p class="text-sm text-neutral-500 mb-4">Use the default slot for a completely custom trigger.</p>
78
- <XMarkModalVideo
79
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
80
- title="Custom Trigger Demo"
81
- size="5xl"
82
- >
83
- <UButton size="lg" label="Watch the Demo" leading-icon="i-lucide-play" />
84
- </XMarkModalVideo>
85
- </section>
86
-
87
- <!-- Minimal (No Title) -->
88
- <section>
89
- <h2 class="text-lg font-semibold mb-4">Minimal Modal (No Footer)</h2>
90
- <p class="text-sm text-neutral-500 mb-4">Omit title/description for a clean, video-only modal.</p>
91
- <XMarkModalVideo
92
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
93
- :button="{ label: 'Clean Modal', variant: 'subtle' }"
94
- />
95
- </section>
96
-
97
- <!-- Props -->
98
- <section>
99
- <h2 class="text-lg font-semibold mb-4">Props</h2>
100
- <table class="w-full text-sm">
101
- <thead>
102
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
103
- <th class="text-left py-3 px-4">Prop</th>
104
- <th class="text-left py-3 px-4">Type</th>
105
- <th class="text-left py-3 px-4">Default</th>
106
- <th class="text-left py-3 px-4">Description</th>
107
- </tr>
108
- </thead>
109
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
110
- <tr><td class="py-3 px-4 font-mono text-xs">src</td><td class="py-3 px-4">String</td><td class="py-3 px-4">required</td><td class="py-3 px-4">Video URL (YouTube, Vimeo, or direct)</td></tr>
111
- <tr><td class="py-3 px-4 font-mono text-xs">thumbnail</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">Thumbnail image (shows image with play button)</td></tr>
112
- <tr><td class="py-3 px-4 font-mono text-xs">title</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">Video title (shown in footer)</td></tr>
113
- <tr><td class="py-3 px-4 font-mono text-xs">description</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">Video description (shown in footer)</td></tr>
114
- <tr><td class="py-3 px-4 font-mono text-xs">size</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'4xl'</td><td class="py-3 px-4">lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl, 7xl, full</td></tr>
115
- <tr><td class="py-3 px-4 font-mono text-xs">autoplay</td><td class="py-3 px-4">Boolean</td><td class="py-3 px-4">true</td><td class="py-3 px-4">Autoplay when modal opens</td></tr>
116
- <tr><td class="py-3 px-4 font-mono text-xs">button</td><td class="py-3 px-4">Object</td><td class="py-3 px-4">{}</td><td class="py-3 px-4">{ label, color, variant, size, icon }</td></tr>
117
- <tr><td class="py-3 px-4 font-mono text-xs">poster</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">Poster image for direct videos</td></tr>
118
- <tr><td class="py-3 px-4 font-mono text-xs">captions</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">Captions file URL</td></tr>
119
- </tbody>
120
- </table>
121
- </section>
122
-
123
- <!-- Button Object -->
124
- <section>
125
- <h2 class="text-lg font-semibold mb-4">Button Object Properties</h2>
126
- <table class="w-full text-sm">
127
- <thead>
128
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
129
- <th class="text-left py-3 px-4">Property</th>
130
- <th class="text-left py-3 px-4">Type</th>
131
- <th class="text-left py-3 px-4">Default</th>
132
- </tr>
133
- </thead>
134
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
135
- <tr><td class="py-3 px-4 font-mono text-xs">label</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'Watch Video'</td></tr>
136
- <tr><td class="py-3 px-4 font-mono text-xs">color</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'primary'</td></tr>
137
- <tr><td class="py-3 px-4 font-mono text-xs">variant</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'solid'</td></tr>
138
- <tr><td class="py-3 px-4 font-mono text-xs">size</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'md'</td></tr>
139
- <tr><td class="py-3 px-4 font-mono text-xs">icon</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'i-lucide-play'</td></tr>
140
- </tbody>
141
- </table>
142
- </section>
143
-
144
- <!-- Supported Formats -->
145
- <section>
146
- <h2 class="text-lg font-semibold mb-4">Supported Video Sources</h2>
147
- <div class="grid md:grid-cols-3 gap-4">
148
- <div class="p-4 rounded-lg bg-neutral-100 dark:bg-neutral-800">
149
- <h3 class="font-medium mb-2">YouTube</h3>
150
- <ul class="text-sm text-neutral-600 dark:text-neutral-400 space-y-1">
151
- <li>youtube.com/watch?v=...</li>
152
- <li>youtu.be/...</li>
153
- <li>youtube.com/embed/...</li>
154
- </ul>
155
- </div>
156
- <div class="p-4 rounded-lg bg-neutral-100 dark:bg-neutral-800">
157
- <h3 class="font-medium mb-2">Vimeo</h3>
158
- <ul class="text-sm text-neutral-600 dark:text-neutral-400 space-y-1">
159
- <li>vimeo.com/12345</li>
160
- </ul>
161
- </div>
162
- <div class="p-4 rounded-lg bg-neutral-100 dark:bg-neutral-800">
163
- <h3 class="font-medium mb-2">Direct</h3>
164
- <ul class="text-sm text-neutral-600 dark:text-neutral-400 space-y-1">
165
- <li>.mp4, .webm, .ogg</li>
166
- <li>Any direct video URL</li>
167
- </ul>
168
- </div>
169
- </div>
170
- </section>
171
-
172
- <!-- Code Example -->
173
- <section>
174
- <h2 class="text-lg font-semibold mb-4">Code Example</h2>
175
- <CodeExample title="Video Modal Usage" :code="codeExample" />
176
- </section>
177
- </div>
178
- </div>
179
- </template>
180
-
181
- <script setup>
182
- const codeExample = `<!-- With thumbnail trigger -->
183
- <XMarkModalVideo
184
- src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
185
- thumbnail="/images/video-thumb.jpg"
186
- title="Product Demo"
187
- description="Watch our 3-minute overview."
188
- size="5xl"
189
- />
190
-
191
- <!-- With button trigger (object) -->
192
- <XMarkModalVideo
193
- src="https://vimeo.com/76979871"
194
- title="Customer Story"
195
- :button="{
196
- label: 'Watch Video',
197
- color: 'primary',
198
- variant: 'solid',
199
- size: 'lg',
200
- icon: 'i-lucide-play'
201
- }"
202
- />
203
-
204
- <!-- Large modal size -->
205
- <XMarkModalVideo
206
- src="https://www.youtube.com/watch?v=..."
207
- size="full"
208
- :button="{ label: 'Full Screen' }"
209
- />
210
-
211
- <!-- Custom trigger (slot) -->
212
- <XMarkModalVideo src="https://www.youtube.com/watch?v=...">
213
- <UButton size="lg" label="Watch Video" leading-icon="i-lucide-play" />
214
- </XMarkModalVideo>
215
-
216
- <!-- Minimal (no footer) -->
217
- <XMarkModalVideo
218
- src="/videos/demo.mp4"
219
- :button="{ label: 'Play' }"
220
- :autoplay="false"
221
- />`
222
- </script>
@@ -1,164 +0,0 @@
1
- <template>
2
- <div class="min-h-screen">
3
- <div class="bg-white dark:bg-neutral-900 border-b border-neutral-200 dark:border-neutral-800 px-8 py-6">
4
- <h1 class="text-2xl font-bold text-neutral-900 dark:text-white">Announcement Bar</h1>
5
- <p class="mt-2 text-neutral-600 dark:text-neutral-400">Top-of-page banner for announcements and promotions.</p>
6
- </div>
7
-
8
- <div class="p-8 space-y-12">
9
- <!-- Demo Bars -->
10
- <section>
11
- <h2 class="text-lg font-semibold mb-4">Variants</h2>
12
- <p class="text-sm text-neutral-500 mb-4">Click the buttons to show different announcement bar styles</p>
13
- <div class="flex flex-wrap gap-3 mb-6">
14
- <UButton @click="showBar('primary')">Primary</UButton>
15
- <UButton color="neutral" @click="showBar('neutral')">Neutral</UButton>
16
- <UButton color="success" @click="showBar('success')">Success</UButton>
17
- <UButton color="warning" @click="showBar('warning')">Warning</UButton>
18
- <UButton color="error" @click="showBar('error')">Error</UButton>
19
- </div>
20
-
21
- <!-- Demo Container -->
22
- <div class="relative bg-neutral-100 dark:bg-neutral-800 rounded-lg overflow-hidden min-h-[200px]">
23
- <XMarkLayoutAnnouncementBar
24
- v-if="activeBar"
25
- :message="barConfig.message"
26
- :badge="barConfig.badge"
27
- :icon="barConfig.icon"
28
- :link="barConfig.link"
29
- :link-text="barConfig.linkText"
30
- :variant="activeBar"
31
- :dismissible="true"
32
- storage-key=""
33
- @dismiss="activeBar = null"
34
- />
35
- <div class="p-8 pt-16">
36
- <p class="text-neutral-600 dark:text-neutral-400">Page content below announcement bar</p>
37
- </div>
38
- </div>
39
- </section>
40
-
41
- <!-- With Icon and Badge -->
42
- <section>
43
- <h2 class="text-lg font-semibold mb-4">With Icon and Badge</h2>
44
- <div class="relative bg-neutral-100 dark:bg-neutral-800 rounded-lg overflow-hidden">
45
- <XMarkLayoutAnnouncementBar
46
- message="Join us for our annual conference next month"
47
- badge="NEW"
48
- icon="i-lucide-calendar"
49
- link="#"
50
- link-text="Register now"
51
- variant="primary"
52
- :dismissible="false"
53
- storage-key=""
54
- />
55
- </div>
56
- </section>
57
-
58
- <!-- Simple Version -->
59
- <section>
60
- <h2 class="text-lg font-semibold mb-4">Simple Message</h2>
61
- <div class="relative bg-neutral-100 dark:bg-neutral-800 rounded-lg overflow-hidden">
62
- <XMarkLayoutAnnouncementBar
63
- message="Free shipping on orders over $50"
64
- variant="neutral"
65
- :dismissible="false"
66
- storage-key=""
67
- />
68
- </div>
69
- </section>
70
-
71
- <!-- Props -->
72
- <section>
73
- <h2 class="text-lg font-semibold mb-4">Props</h2>
74
- <table class="w-full text-sm">
75
- <thead>
76
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
77
- <th class="text-left py-3 px-4">Prop</th>
78
- <th class="text-left py-3 px-4">Type</th>
79
- <th class="text-left py-3 px-4">Default</th>
80
- <th class="text-left py-3 px-4">Description</th>
81
- </tr>
82
- </thead>
83
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
84
- <tr><td class="py-3 px-4 font-mono text-xs">message</td><td class="py-3 px-4">String</td><td class="py-3 px-4">required</td><td class="py-3 px-4">Main message text</td></tr>
85
- <tr><td class="py-3 px-4 font-mono text-xs">badge</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">Optional badge before message</td></tr>
86
- <tr><td class="py-3 px-4 font-mono text-xs">icon</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">Icon name (Lucide)</td></tr>
87
- <tr><td class="py-3 px-4 font-mono text-xs">link</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td><td class="py-3 px-4">CTA link URL</td></tr>
88
- <tr><td class="py-3 px-4 font-mono text-xs">linkText</td><td class="py-3 px-4">String</td><td class="py-3 px-4">Learn more</td><td class="py-3 px-4">CTA link text</td></tr>
89
- <tr><td class="py-3 px-4 font-mono text-xs">variant</td><td class="py-3 px-4">String</td><td class="py-3 px-4">primary</td><td class="py-3 px-4">primary, neutral, success, warning, error</td></tr>
90
- <tr><td class="py-3 px-4 font-mono text-xs">dismissible</td><td class="py-3 px-4">Boolean</td><td class="py-3 px-4">true</td><td class="py-3 px-4">Show close button</td></tr>
91
- <tr><td class="py-3 px-4 font-mono text-xs">storageKey</td><td class="py-3 px-4">String</td><td class="py-3 px-4">announcement-dismissed</td><td class="py-3 px-4">LocalStorage key for dismissed state</td></tr>
92
- </tbody>
93
- </table>
94
- </section>
95
-
96
- <!-- Events -->
97
- <section>
98
- <h2 class="text-lg font-semibold mb-4">Events</h2>
99
- <table class="w-full text-sm">
100
- <thead>
101
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
102
- <th class="text-left py-3 px-4">Event</th>
103
- <th class="text-left py-3 px-4">Description</th>
104
- </tr>
105
- </thead>
106
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
107
- <tr><td class="py-3 px-4 font-mono text-xs">@dismiss</td><td class="py-3 px-4">Emitted when user dismisses the bar</td></tr>
108
- </tbody>
109
- </table>
110
- </section>
111
-
112
- <!-- Code Example -->
113
- <section>
114
- <h2 class="text-lg font-semibold mb-4">Code Example</h2>
115
- <CodeExample title="Announcement Bar Usage" :code="codeExample" />
116
- </section>
117
- </div>
118
- </div>
119
- </template>
120
-
121
- <script setup>
122
- const codeExample = `<!-- Basic announcement -->
123
- <XMarkLayoutAnnouncementBar
124
- message="Free shipping on orders over $50"
125
- variant="neutral"
126
- />
127
-
128
- <!-- Full featured with icon and link -->
129
- <XMarkLayoutAnnouncementBar
130
- message="Our Black Friday sale is now live!"
131
- badge="SALE"
132
- icon="i-lucide-percent"
133
- link="/sale"
134
- link-text="Shop now"
135
- variant="primary"
136
- :dismissible="true"
137
- storage-key="black-friday-2024"
138
- @dismiss="handleDismiss"
139
- />
140
-
141
- <!-- Variants: primary, neutral, success, warning, error -->
142
- <XMarkLayoutAnnouncementBar
143
- message="Your order has been shipped!"
144
- variant="success"
145
- icon="i-lucide-package"
146
- />`
147
-
148
- const activeBar = ref('primary')
149
-
150
- const barConfig = {
151
- message: 'Our Black Friday sale is now live!',
152
- badge: 'SALE',
153
- icon: 'i-lucide-percent',
154
- link: '#',
155
- linkText: 'Shop now'
156
- }
157
-
158
- const showBar = (variant) => {
159
- activeBar.value = null
160
- setTimeout(() => {
161
- activeBar.value = variant
162
- }, 100)
163
- }
164
- </script>
@@ -1,210 +0,0 @@
1
- <template>
2
- <div class="min-h-screen">
3
- <div class="bg-white dark:bg-neutral-900 border-b border-neutral-200 dark:border-neutral-800 px-8 py-6">
4
- <h1 class="text-2xl font-bold text-neutral-900 dark:text-white">Cookie Banner</h1>
5
- <p class="mt-2 text-neutral-600 dark:text-neutral-400">Bottom cookie consent banner with accept/reject options.</p>
6
- </div>
7
-
8
- <div class="p-8 space-y-12">
9
- <!-- Demo -->
10
- <section>
11
- <h2 class="text-lg font-semibold mb-4">Cookie Banner Demo</h2>
12
- <p class="text-sm text-neutral-500 mb-4">Click the button to show the cookie banner (appears at bottom of page)</p>
13
- <div class="flex gap-3">
14
- <UButton @click="showBanner">Show Cookie Banner</UButton>
15
- <UButton color="neutral" variant="outline" @click="resetConsent">Reset Consent</UButton>
16
- </div>
17
- </section>
18
-
19
- <!-- Preview -->
20
- <section>
21
- <h2 class="text-lg font-semibold mb-4">Preview</h2>
22
- <div class="relative bg-neutral-100 dark:bg-neutral-800 rounded-lg p-6 min-h-[300px]">
23
- <p class="text-neutral-600 dark:text-neutral-400 mb-4">The banner appears at the bottom of the viewport:</p>
24
- <!-- Static preview -->
25
- <div class="absolute bottom-4 left-4 right-4">
26
- <div class="bg-white dark:bg-neutral-900 rounded-xl shadow-2xl border border-neutral-200 dark:border-neutral-700 p-6">
27
- <div class="flex flex-col lg:flex-row lg:items-center gap-4">
28
- <div class="flex-1">
29
- <h4 class="font-semibold">We use cookies</h4>
30
- <p class="text-sm text-neutral-500 mt-1">
31
- We use cookies to improve your experience on our site.
32
- <NuxtLink to="#" class="text-primary-500 hover:underline">Learn more</NuxtLink>
33
- </p>
34
- </div>
35
- <div class="flex flex-wrap gap-3">
36
- <UButton variant="outline">Reject All</UButton>
37
- <UButton>Accept All</UButton>
38
- </div>
39
- </div>
40
- </div>
41
- </div>
42
- </div>
43
- </section>
44
-
45
- <!-- With Customize -->
46
- <section>
47
- <h2 class="text-lg font-semibold mb-4">With Customize Button</h2>
48
- <UButton @click="showCustomizableBanner">Show with Customize Option</UButton>
49
- <p class="text-sm text-neutral-500 mt-2">Includes a "Customize" button that can open GDPR preferences modal</p>
50
- </section>
51
-
52
- <!-- Props -->
53
- <section>
54
- <h2 class="text-lg font-semibold mb-4">Props</h2>
55
- <table class="w-full text-sm">
56
- <thead>
57
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
58
- <th class="text-left py-3 px-4">Prop</th>
59
- <th class="text-left py-3 px-4">Type</th>
60
- <th class="text-left py-3 px-4">Default</th>
61
- <th class="text-left py-3 px-4">Description</th>
62
- </tr>
63
- </thead>
64
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
65
- <tr><td class="py-3 px-4 font-mono text-xs">title</td><td class="py-3 px-4">String</td><td class="py-3 px-4">We use cookies</td><td class="py-3 px-4">Banner title</td></tr>
66
- <tr><td class="py-3 px-4 font-mono text-xs">message</td><td class="py-3 px-4">String</td><td class="py-3 px-4">We use cookies to...</td><td class="py-3 px-4">Banner message</td></tr>
67
- <tr><td class="py-3 px-4 font-mono text-xs">policyLink</td><td class="py-3 px-4">String</td><td class="py-3 px-4">/privacy</td><td class="py-3 px-4">Privacy policy URL</td></tr>
68
- <tr><td class="py-3 px-4 font-mono text-xs">policyLabel</td><td class="py-3 px-4">String</td><td class="py-3 px-4">Learn more</td><td class="py-3 px-4">Privacy link text</td></tr>
69
- <tr><td class="py-3 px-4 font-mono text-xs">hasCustomize</td><td class="py-3 px-4">Boolean</td><td class="py-3 px-4">false</td><td class="py-3 px-4">Show customize button</td></tr>
70
- <tr><td class="py-3 px-4 font-mono text-xs">hasReject</td><td class="py-3 px-4">Boolean</td><td class="py-3 px-4">true</td><td class="py-3 px-4">Show reject button</td></tr>
71
- <tr><td class="py-3 px-4 font-mono text-xs">storageKey</td><td class="py-3 px-4">String</td><td class="py-3 px-4">cookie-consent</td><td class="py-3 px-4">LocalStorage key</td></tr>
72
- </tbody>
73
- </table>
74
- </section>
75
-
76
- <!-- Events -->
77
- <section>
78
- <h2 class="text-lg font-semibold mb-4">Events</h2>
79
- <table class="w-full text-sm">
80
- <thead>
81
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
82
- <th class="text-left py-3 px-4">Event</th>
83
- <th class="text-left py-3 px-4">Description</th>
84
- </tr>
85
- </thead>
86
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
87
- <tr><td class="py-3 px-4 font-mono text-xs">@accept</td><td class="py-3 px-4">Emitted when user accepts all cookies</td></tr>
88
- <tr><td class="py-3 px-4 font-mono text-xs">@reject</td><td class="py-3 px-4">Emitted when user rejects cookies</td></tr>
89
- <tr><td class="py-3 px-4 font-mono text-xs">@customize</td><td class="py-3 px-4">Emitted when user clicks customize</td></tr>
90
- </tbody>
91
- </table>
92
- </section>
93
-
94
- <!-- Code Example -->
95
- <section>
96
- <h2 class="text-lg font-semibold mb-4">Code Example</h2>
97
- <CodeExample title="Cookie Banner Usage" :code="codeExample" />
98
- </section>
99
- </div>
100
-
101
- <!-- Actual Banner Components -->
102
- <XMarkPrivacyCookieBanner
103
- v-if="bannerVisible"
104
- title="We use cookies"
105
- message="We use cookies to improve your experience on our site."
106
- policy-link="/privacy"
107
- :has-customize="false"
108
- :has-reject="true"
109
- storage-key="demo-cookie-consent"
110
- @accept="handleAccept"
111
- @reject="handleReject"
112
- />
113
-
114
- <XMarkPrivacyCookieBanner
115
- v-if="customizableBannerVisible"
116
- title="Cookie Preferences"
117
- message="We use cookies to personalize content and analyze traffic."
118
- :has-customize="true"
119
- :has-reject="true"
120
- storage-key="demo-customizable-consent"
121
- @accept="handleAccept"
122
- @reject="handleReject"
123
- @customize="handleCustomize"
124
- />
125
- </div>
126
- </template>
127
-
128
- <script setup>
129
- const codeExample = `<!-- Basic cookie banner -->
130
- <XMarkPrivacyCookieBanner
131
- title="We use cookies"
132
- message="We use cookies to improve your experience."
133
- policy-link="/privacy"
134
- @accept="handleAccept"
135
- @reject="handleReject"
136
- />
137
-
138
- <!-- With customize option -->
139
- <XMarkPrivacyCookieBanner
140
- title="Cookie Preferences"
141
- message="We use cookies to personalize content."
142
- :has-customize="true"
143
- :has-reject="true"
144
- storage-key="cookie-consent"
145
- @accept="handleAccept"
146
- @reject="handleReject"
147
- @customize="openGDPRModal"
148
- />
149
-
150
- <!-- In your layout -->
151
- <template>
152
- <div>
153
- <NuxtPage />
154
- <XMarkPrivacyCookieBanner
155
- @accept="enableAnalytics"
156
- @customize="gdprModalOpen = true"
157
- />
158
- <XMarkPrivacyGDPR v-model="gdprModalOpen" />
159
- </div>
160
- </template>`
161
-
162
- const bannerVisible = ref(false)
163
- const customizableBannerVisible = ref(false)
164
-
165
- const showBanner = () => {
166
- localStorage.removeItem('demo-cookie-consent')
167
- bannerVisible.value = true
168
- // Force re-render by toggling
169
- nextTick(() => {
170
- bannerVisible.value = false
171
- nextTick(() => {
172
- bannerVisible.value = true
173
- })
174
- })
175
- }
176
-
177
- const showCustomizableBanner = () => {
178
- localStorage.removeItem('demo-customizable-consent')
179
- customizableBannerVisible.value = true
180
- nextTick(() => {
181
- customizableBannerVisible.value = false
182
- nextTick(() => {
183
- customizableBannerVisible.value = true
184
- })
185
- })
186
- }
187
-
188
- const resetConsent = () => {
189
- localStorage.removeItem('demo-cookie-consent')
190
- localStorage.removeItem('demo-customizable-consent')
191
- bannerVisible.value = false
192
- customizableBannerVisible.value = false
193
- }
194
-
195
- const handleAccept = () => {
196
- console.log('Cookies accepted')
197
- bannerVisible.value = false
198
- customizableBannerVisible.value = false
199
- }
200
-
201
- const handleReject = () => {
202
- console.log('Cookies rejected')
203
- bannerVisible.value = false
204
- customizableBannerVisible.value = false
205
- }
206
-
207
- const handleCustomize = () => {
208
- console.log('Open GDPR preferences modal')
209
- }
210
- </script>