Skip to content

Commit 71dc41a

Browse files
committed
feat: integrate astro-consent for cookie management and add consent banner styles
1 parent c3b2e78 commit 71dc41a

File tree

5 files changed

+309
-12
lines changed

5 files changed

+309
-12
lines changed

astro.config.mjs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
// @ts-check
22
import { defineConfig } from 'astro/config';
3-
3+
import astroConsent from 'astro-consent';
44
import tailwindcss from '@tailwindcss/vite';
55

66
// https://astro.build/config
77
export default defineConfig({
88
site: 'https://devproxy.net',
99
base: '/',
10+
integrations: [
11+
astroConsent({
12+
siteName: 'Dev Proxy',
13+
policyUrl: 'https://go.microsoft.com/fwlink/?LinkId=521839',
14+
consent: {
15+
days: 90,
16+
storageKey: 'devproxy-cookie-consent'
17+
},
18+
categories: {
19+
analytics: false
20+
}
21+
})
22+
],
1023
vite: {
1124
plugins: [tailwindcss()]
1225
}

package-lock.json

Lines changed: 21 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@astrojs/rss": "4.0.15",
1414
"@tailwindcss/vite": "4.2.1",
1515
"astro": "5.18.0",
16+
"astro-consent": "1.0.17",
1617
"tailwindcss": "4.2.1"
1718
},
1819
"devDependencies": {

src/cookiebanner.css

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
/* =========================================================
2+
astro-consent — FULL THEME + STRUCTURE
3+
This file is NEVER overwritten.
4+
========================================================= */
5+
6+
:root {
7+
--cb-font: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
8+
9+
--cb-bg: var(--bg-primary, #ffffff);
10+
--cb-border: var(--border-primary, #e5e7eb);
11+
--cb-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
12+
13+
--cb-text: var(--text-primary, #111827);
14+
--cb-muted: var(--text-muted, #6b7280);
15+
--cb-link: #a855f7;
16+
17+
--cb-radius: 16px;
18+
--cb-btn-radius: 999px;
19+
--cb-btn-padding: 10px 18px;
20+
21+
--cb-accept-bg: #9333ea;
22+
--cb-accept-text: #ffffff;
23+
24+
--cb-reject-bg: var(--cb-border);
25+
--cb-reject-text: var(--cb-text);
26+
27+
--cb-manage-bg: transparent;
28+
--cb-manage-text: var(--cb-text);
29+
--cb-manage-border: var(--cb-border);
30+
31+
--cb-modal-bg: var(--cb-bg);
32+
--cb-modal-backdrop: rgba(0, 0, 0, 0.45);
33+
--cb-modal-radius: 18px;
34+
--cb-modal-width: 480px;
35+
36+
--cb-toggle-off-bg: var(--cb-border);
37+
--cb-toggle-on-bg: #9333ea;
38+
--cb-toggle-knob: #ffffff;
39+
}
40+
41+
/* ===============================
42+
Dark mode overrides
43+
=============================== */
44+
45+
.dark #astro-consent-banner,
46+
.dark #astro-consent-modal {
47+
--cb-bg: var(--bg-primary, #030712);
48+
--cb-border: var(--border-primary, #1f2937);
49+
--cb-text: var(--text-primary, #f3f4f6);
50+
--cb-muted: var(--text-muted, #9ca3af);
51+
--cb-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
52+
--cb-modal-backdrop: rgba(0, 0, 0, 0.6);
53+
}
54+
55+
/* ===============================
56+
Banner
57+
=============================== */
58+
59+
#astro-consent-banner {
60+
position: fixed;
61+
left: 16px;
62+
right: 16px;
63+
bottom: 16px;
64+
z-index: 9999;
65+
font-family: var(--cb-font);
66+
}
67+
68+
.cb-container {
69+
max-width: 1200px;
70+
margin: 0 auto;
71+
padding: 20px 24px;
72+
display: flex;
73+
gap: 24px;
74+
justify-content: space-between;
75+
align-items: center;
76+
77+
background: var(--cb-bg);
78+
border-radius: var(--cb-radius);
79+
border: 1px solid var(--cb-border);
80+
box-shadow: var(--cb-shadow);
81+
color: var(--cb-text);
82+
}
83+
84+
.cb-title {
85+
font-size: 16px;
86+
font-weight: 600;
87+
}
88+
89+
.cb-desc {
90+
margin-top: 4px;
91+
font-size: 14px;
92+
color: var(--cb-muted);
93+
}
94+
95+
.cb-desc a {
96+
color: var(--cb-link);
97+
text-decoration: none;
98+
}
99+
100+
.cb-desc a:hover {
101+
text-decoration: underline;
102+
}
103+
104+
/* ===============================
105+
Buttons
106+
=============================== */
107+
108+
.cb-actions {
109+
display: flex;
110+
gap: 10px;
111+
}
112+
113+
.cb-actions button {
114+
padding: var(--cb-btn-padding);
115+
border-radius: var(--cb-btn-radius);
116+
border: 1px solid transparent;
117+
font-size: 14px;
118+
font-weight: 600;
119+
cursor: pointer;
120+
}
121+
122+
.cb-accept {
123+
background: var(--cb-accept-bg);
124+
color: var(--cb-accept-text);
125+
}
126+
127+
.cb-reject {
128+
background: var(--cb-reject-bg);
129+
color: var(--cb-reject-text);
130+
}
131+
132+
.cb-manage {
133+
background: var(--cb-manage-bg);
134+
color: var(--cb-manage-text);
135+
border: 1px solid var(--cb-manage-border);
136+
}
137+
138+
/* ===============================
139+
Modal
140+
=============================== */
141+
142+
#astro-consent-modal {
143+
position: fixed;
144+
inset: 0;
145+
background: var(--cb-modal-backdrop);
146+
display: flex;
147+
align-items: center;
148+
justify-content: center;
149+
z-index: 10000;
150+
}
151+
152+
.cb-modal {
153+
width: 100%;
154+
max-width: var(--cb-modal-width);
155+
background: var(--cb-modal-bg);
156+
border-radius: var(--cb-modal-radius);
157+
padding: 28px;
158+
color: var(--cb-text);
159+
border: 1px solid var(--cb-border);
160+
}
161+
162+
/* ===============================
163+
Modal rows (SPACING FIXED)
164+
=============================== */
165+
166+
.cb-row {
167+
display: flex;
168+
justify-content: space-between;
169+
align-items: center;
170+
gap: 16px;
171+
padding: 18px 0;
172+
border-bottom: 1px solid var(--cb-border);
173+
}
174+
175+
.cb-row:last-of-type {
176+
border-bottom: 0;
177+
padding-bottom: 32px;
178+
}
179+
180+
/* ===============================
181+
Modal actions
182+
=============================== */
183+
184+
.cb-modal .cb-actions {
185+
margin-top: 24px;
186+
padding-top: 20px;
187+
border-top: 1px solid var(--cb-border);
188+
display: flex;
189+
justify-content: flex-end;
190+
}
191+
192+
/* ===============================
193+
Toggles
194+
=============================== */
195+
196+
.cb-toggle {
197+
width: 44px;
198+
height: 24px;
199+
background: var(--cb-toggle-off-bg);
200+
border-radius: 999px;
201+
position: relative;
202+
cursor: pointer;
203+
flex-shrink: 0;
204+
}
205+
206+
.cb-toggle span {
207+
position: absolute;
208+
width: 18px;
209+
height: 18px;
210+
background: var(--cb-toggle-knob);
211+
border-radius: 50%;
212+
top: 3px;
213+
left: 3px;
214+
transition: transform 0.2s ease;
215+
}
216+
217+
.cb-toggle.active {
218+
background: var(--cb-toggle-on-bg);
219+
}
220+
221+
.cb-toggle.active span {
222+
transform: translateX(20px);
223+
}
224+
225+
/* ===============================
226+
Mobile
227+
=============================== */
228+
229+
@media (max-width: 640px) {
230+
.cb-container {
231+
flex-direction: column;
232+
align-items: stretch;
233+
gap: 16px;
234+
}
235+
236+
.cb-actions {
237+
justify-content: flex-end;
238+
flex-wrap: wrap;
239+
}
240+
}
241+
242+
/* ===============================
243+
Hide unused marketing toggle
244+
=============================== */
245+
246+
.cb-toggle[data-key="marketing"] {
247+
display: none;
248+
}
249+
250+
.cb-toggle[data-key="marketing"]:has(~ *),
251+
.cb-row:has(.cb-toggle[data-key="marketing"]) {
252+
display: none;
253+
}

src/layouts/Layout.astro

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
import '../styles/global.css';
3+
import '../cookiebanner.css';
34
45
interface Props {
56
title: string;
@@ -45,12 +46,24 @@ const ogImage = image ? new URL(image, Astro.site ?? 'https://devproxy.net').hre
4546
}
4647
})();
4748
</script>
48-
<script is:inline type="text/javascript">
49-
(function(c,l,a,r,i,t,y){
50-
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
51-
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
52-
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
53-
})(window, document, "clarity", "script", "vr3ajkmgm3");
49+
<script is:inline>
50+
(function() {
51+
function loadClarity() {
52+
(function(c,l,a,r,i,t,y){
53+
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
54+
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
55+
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
56+
})(window, document, "clarity", "script", "vr3ajkmgm3");
57+
}
58+
function checkConsent() {
59+
if (window.cookieConsent) {
60+
var consent = window.cookieConsent.get();
61+
if (consent && consent.analytics) loadClarity();
62+
}
63+
}
64+
checkConsent();
65+
document.addEventListener('cookie-consent-updated', checkConsent);
66+
})();
5467
</script>
5568
</head>
5669
<body class="min-h-screen flex flex-col">
@@ -136,6 +149,7 @@ const ogImage = image ? new URL(image, Astro.site ?? 'https://devproxy.net').hre
136149
<footer class="border-t py-8 mt-16" style="border-color: var(--border-primary);">
137150
<div class="max-w-6xl mx-auto px-4 text-center text-sm" style="color: var(--text-faint);">
138151
<p>&copy; {new Date().getFullYear()} Dev Proxy.</p>
152+
<p class="mt-2"><button onclick="window.cookieConsent && window.cookieConsent.reset()" class="underline hover:text-purple-400 transition-colors" style="color: var(--text-faint); background: none; border: none; cursor: pointer; font-size: inherit;">Cookie Settings</button></p>
139153
</div>
140154
</footer>
141155

0 commit comments

Comments
 (0)