@shamaz332/react-gdpr
v1.2.0
Published
A lightweight, customizable GDPR cookie consent component for React, Vue, Angular and Vanilla JS.
Maintainers
Readme
@shamaz332/react-gdpr
A lightweight, fully customizable GDPR cookie-consent banner for React, Vue 3, Angular, and plain HTML / Vanilla JS via a framework-agnostic Web Component.
Table of Contents
- Features
- Installation
- Usage
- Theming
- Cookie Categories
- Props / Attributes Reference
- Web Component Events
- TypeScript
Features
- React component with full prop API
- Web Component (
<cookie-notice>) — works in Vue, Angular, Svelte, or plain HTML with React bundled in - 8 built-in theme presets —
dark,light,ocean,forest,corporate,warm,minimal,neon - Full custom theming via
themeConfig(colours, radius, font, shadow) - 3 animation modes —
none,slide,fade - 4 position modes —
bottom,top,center,modal - 5 cookie category presets —
necessary,analytics,marketing,functional,social - Auto dark/light mode via
theme="auto"(prefers-color-scheme) - Legacy cookie support for cross-domain scenarios
- Full TypeScript definitions
Installation
React
npm install @shamaz332/react-gdpr
# or
yarn add @shamaz332/react-gdprReact ≥ 17 is a peer dependency — it must already be in your project.
Vue 3
npm install @shamaz332/react-gdprThe Web Component build ships React bundled inside — your Vue project does not need React as a dependency.
Configure Vite to treat <cookie-notice> as a custom element:
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag === 'cookie-notice'
}
}
})
]
});If you use Vue CLI instead of Vite, add to vue.config.js:
module.exports = {
chainWebpack(config) {
config.module
.rule('vue')
.use('vue-loader')
.tap((options) => ({
...options,
compilerOptions: {
isCustomElement: (tag) => tag === 'cookie-notice'
}
}));
}
};Angular
npm install @shamaz332/react-gdprRegister CUSTOM_ELEMENTS_SCHEMA in your module and import the web component bundle:
// app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import '@shamaz332/react-gdpr/dist/cookie-notice.wc.js';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent]
})
export class AppModule {}If you use standalone components (Angular 17+):
// app.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@shamaz332/react-gdpr/dist/cookie-notice.wc.js';
@Component({
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<cookie-notice
theme="corporate"
animation="slide"
notice-title="Cookie Consent"
notice-text="We use cookies to improve your experience."
></cookie-notice>
`
})
export class AppComponent {}Vanilla JS / HTML
Download or link the self-contained bundle — no npm, no build step needed:
<!-- From node_modules after npm install -->
<script src="node_modules/@shamaz332/react-gdpr/dist/cookie-notice.wc.js"></script>
<cookie-notice
theme="ocean"
animation="fade"
notice-title="We use cookies"
notice-text="We use cookies to improve your experience."
></cookie-notice>Usage
React Usage
import React from 'react';
import CookieNotice, { COOKIE_PRESETS, THEME_PRESETS } from '@shamaz332/react-gdpr';
export default function App() {
return (
<CookieNotice
theme="dark"
animation="slide"
position="bottom"
cookies={[
COOKIE_PRESETS.necessary,
COOKIE_PRESETS.analytics,
COOKIE_PRESETS.marketing,
]}
themeConfig={THEME_PRESETS.ocean}
onInit={(cookies) => console.log('init', cookies)}
onSave={(cookies) => console.log('saved', cookies)}
>
<h3>We use cookies</h3>
<p>
We use cookies to improve your browsing experience and to analyse
our traffic. Please choose your preferences below.
</p>
</CookieNotice>
);
}Fully custom theme:
<CookieNotice
themeConfig={{
background: '#1a1a2e',
color: '#eaeaea',
primaryButton: '#e94560',
primaryButtonColor: '#ffffff',
secondaryButtonColor: '#e94560',
cookieListBackground: '#16213e',
cookieListColor: '#eaeaea',
borderRadius: '12px',
buttonRadius: '8px',
fontFamily: "'Inter', sans-serif",
shadow: '0 -8px 32px rgba(233,69,96,0.2)'
}}
animation="fade"
position="modal"
>
<h3>Cookie Settings</h3>
<p>Manage your cookie preferences below.</p>
</CookieNotice>Vue 3 Usage
<!-- src/App.vue -->
<template>
<div>
<h1>My App</h1>
<cookie-notice
theme="ocean"
animation="slide"
position="bottom"
notice-title="We use cookies"
notice-text="We use cookies to enhance your experience."
accept-all-text="Accept All"
preferences-text="Manage Cookies"
@cookie-init="onCookieInit"
@cookie-save="onCookieSave"
/>
</div>
</template>
<script setup>
import '@shamaz332/react-gdpr/dist/cookie-notice.wc.js';
function onCookieInit(event) {
console.log('Cookie init:', event.detail);
}
function onCookieSave(event) {
console.log('Cookie save:', event.detail);
}
</script>Setting complex props via template ref:
<template>
<cookie-notice ref="cookieEl" theme="corporate" animation="fade" />
</template>
<script setup>
import { ref, onMounted } from 'vue';
import '@shamaz332/react-gdpr/dist/cookie-notice.wc.js';
const cookieEl = ref(null);
onMounted(() => {
cookieEl.value.cookies = [
{ name: 'necessary', checked: true, editable: false, default: true, title: 'Essential', text: 'Required for the website to function.' },
{ name: 'analytics', checked: false, editable: true, title: 'Analytics', text: 'Helps us understand visitor behaviour.' },
];
cookieEl.value.onSave = (cookies) => console.log('saved', cookies);
});
</script>Angular Usage
// app.component.ts
import { Component, ElementRef, ViewChild, AfterViewInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@shamaz332/react-gdpr/dist/cookie-notice.wc.js';
@Component({
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<cookie-notice
#cookieEl
theme="light"
animation="slide"
notice-title="Cookie Consent"
notice-text="We use cookies to provide a better browsing experience."
accept-all-text="Accept All"
preferences-text="Manage Preferences"
(cookie-save)="onCookieSave($event)"
(cookie-init)="onCookieInit($event)"
></cookie-notice>
`
})
export class AppComponent implements AfterViewInit {
@ViewChild('cookieEl') cookieEl!: ElementRef;
ngAfterViewInit() {
this.cookieEl.nativeElement.cookies = [
{ name: 'necessary', checked: true, editable: false, default: true, title: 'Essential', text: 'Required for the website.' },
{ name: 'analytics', checked: false, editable: true, title: 'Analytics', text: 'Help us improve our website.' },
{ name: 'marketing', checked: false, editable: true, title: 'Marketing', text: 'Used for targeted ads.' },
];
}
onCookieSave(event: CustomEvent) {
console.log('Saved:', event.detail);
}
onCookieInit(event: CustomEvent) {
console.log('Init:', event.detail);
}
}Vanilla JS Usage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="node_modules/@shamaz332/react-gdpr/dist/cookie-notice.wc.js"></script>
</head>
<body>
<cookie-notice
id="cookieConsent"
theme="warm"
animation="slide"
position="bottom"
notice-title="We use cookies"
notice-text="Choose which cookies you allow below."
accept-all-text="Accept All"
preferences-text="Manage"
link-privacy="privacy-policy"
link-privacy-text="Privacy Policy"
link-terms="terms"
link-terms-text="Terms"
></cookie-notice>
<script>
const el = document.getElementById('cookieConsent');
el.cookies = [
{ name: 'necessary', checked: true, editable: false, default: true, title: 'Essential', text: 'Required for the website to work.' },
{ name: 'analytics', checked: false, editable: true, title: 'Analytics', text: 'Helps us understand visitor behaviour.' },
{ name: 'marketing', checked: false, editable: true, title: 'Marketing', text: 'Used for targeted advertising.' },
];
el.addEventListener('cookie-init', (e) => {
console.log('Init:', e.detail);
});
el.addEventListener('cookie-save', (e) => {
const accepted = e.detail.filter(c => c.checked).map(c => c.name);
console.log('Accepted:', accepted);
});
</script>
</body>
</html>Theming
Built-in themes
The theme prop applies a CSS-class-based theme:
| Value | Description |
|--------|------------------------------------|
| dark | Default — dark banner, cyan CTA |
| light| White banner, blue CTA |
| auto | Follows OS prefers-color-scheme |
<CookieNotice theme="light" />
<CookieNotice theme="auto" />THEME_PRESETS
Pre-built full colour configurations passed to themeConfig:
| Key | Look |
|-------------|-----------------------------------------------|
| dark | Classic dark grey, cyan CTA |
| light | Clean white, blue CTA |
| ocean | Deep navy, teal CTA, soft glow shadow |
| forest | Deep green, emerald CTA |
| corporate | Dark indigo, purple CTA, rounded corners |
| warm | Dark brown, orange CTA |
| minimal | Off-white, black CTA, no border radius |
| neon | Pure black, neon-green CTA, glow shadow |
import CookieNotice, { THEME_PRESETS } from '@shamaz332/react-gdpr';
// Use a preset directly
<CookieNotice themeConfig={THEME_PRESETS.ocean} animation="slide" />
// Extend a preset with overrides
<CookieNotice
themeConfig={{
...THEME_PRESETS.corporate,
primaryButton: '#ff6600',
borderRadius: '12px'
}}
/>Web Component — use the theme-preset attribute:
<cookie-notice theme-preset="ocean" animation="slide"></cookie-notice>
<cookie-notice theme-preset="neon" animation="fade"></cookie-notice>themeConfig reference
All fields are optional. Any omitted field falls back to the active theme value.
| Field | CSS variable | Description |
|------------------------|-----------------------------|--------------------------------------|
| background | --rcn-bg | Banner background colour |
| color | --rcn-color | Banner text colour |
| primaryButton | --rcn-btn-primary-bg | Accept button background |
| primaryButtonColor | --rcn-btn-primary-color | Accept button text colour |
| secondaryButtonColor | --rcn-btn-secondary-color | Preferences button colour |
| cookieListBackground | --rcn-cookie-list-bg | Preferences list background |
| cookieListColor | --rcn-cookie-list-color | Preferences list text colour |
| borderRadius | --rcn-border-radius | Banner corner radius (e.g. '8px') |
| buttonRadius | --rcn-btn-radius | Button corner radius |
| fontFamily | --rcn-font-family | Font family override |
| fontSize | --rcn-font-size | Base font size |
| shadow | --rcn-shadow | Banner box-shadow |
Cookie Categories
COOKIE_PRESETS
import CookieNotice, { COOKIE_PRESETS } from '@shamaz332/react-gdpr';
<CookieNotice
cookies={[
COOKIE_PRESETS.necessary,
COOKIE_PRESETS.analytics,
COOKIE_PRESETS.marketing,
COOKIE_PRESETS.functional,
COOKIE_PRESETS.social,
]}
/>| Key | Editable | Default | Title |
|--------------|----------|---------|----------------|
| necessary | No | Yes | Essential |
| analytics | Yes | No | Analytics |
| marketing | Yes | No | Marketing |
| functional | Yes | No | Functional |
| social | Yes | No | Social Media |
Props / Attributes Reference
React props
| Prop | Type | Default |
|-----------------------------|----------------------------------------------------|-----------------------------|
| theme | 'dark' \| 'light' \| 'auto' | 'dark' |
| themeConfig | ThemeConfig | null |
| animation | 'none' \| 'slide' \| 'fade' | 'none' |
| position | 'bottom' \| 'top' \| 'center' \| 'modal' | 'bottom' |
| cookies | CookiePreset[] | [necessary, marketing] |
| cookiePrefix | string | 'react_cookie_notice_' |
| acceptAllButtonText | string | 'Accept all cookies' |
| preferencesButtonText | string | 'Cookie preferences' |
| savePreferencesButtonText | string | 'Save cookie preferences' |
| showCookiePreferences | boolean | true |
| linkOne / linkOneText | string | '' |
| linkTwo / linkTwoText | string | '' |
| onInit | (cookies: CookiePreset[]) => void | () => {} |
| onSave | (cookies: CookiePreset[]) => void | () => {} |
| cookieOptions | object | { expires: 365 } |
| legacyCookie | boolean | false |
| legacyCookieOptions | object | { expires: 365 } |
| toggleVisibility | boolean | true |
| containerStyle | CSSProperties | {} |
| buttonPrimaryStyle | CSSProperties | {} |
| buttonSecondaryStyle | CSSProperties | {} |
Web Component attributes
| Attribute | Equivalent JS property | Description |
|--------------------------|------------------------|--------------------------------------------------|
| theme | — | 'dark', 'light', 'auto' |
| theme-preset | themeConfig | Name from THEME_PRESETS (e.g. 'ocean') |
| animation | — | 'none', 'slide', 'fade' |
| position | — | 'bottom', 'top', 'center', 'modal' |
| notice-title | — | Banner heading text |
| notice-text | — | Banner body text |
| cookie-prefix | — | Cookie storage prefix |
| accept-all-text | — | Accept button label |
| preferences-text | — | Preferences button label |
| save-preferences-text | — | Save button label |
| show-preferences | — | 'false' to hide preferences button |
| link-privacy | — | Privacy policy URL path |
| link-privacy-text | — | Privacy policy link label |
| link-terms | — | Terms URL path |
| link-terms-text | — | Terms link label |
| legacy-cookie | — | 'true' to enable legacy cookies |
| — | cookies | CookiePreset[] array |
| — | themeConfig | ThemeConfig object |
| — | cookieOptions | js-cookie options |
| — | onSave | Save callback (cookies) => void |
| — | onInit | Init callback (cookies) => void |
Web Component Events
| Event | Fired when | event.detail |
|---------------|----------------------------------------|------------------|
| cookie-init | Component mounts, reads stored cookies | CookiePreset[] |
| cookie-save | User accepts or saves preferences | CookiePreset[] |
document.querySelector('cookie-notice').addEventListener('cookie-save', (e) => {
const accepted = e.detail.filter(c => c.checked).map(c => c.name);
// e.g. ['necessary', 'analytics']
if (accepted.includes('analytics')) initAnalytics();
});TypeScript
import CookieNotice, {
COOKIE_PRESETS,
THEME_PRESETS,
type CookiePreset,
type ThemeConfig,
type CookieNoticeProps
} from '@shamaz332/react-gdpr';Web Component types:
import type CookieNoticeElement from '@shamaz332/react-gdpr/web-component';
const el = document.querySelector('cookie-notice') as CookieNoticeElement;
el.cookies = [COOKIE_PRESETS.necessary, COOKIE_PRESETS.analytics];
el.themeConfig = THEME_PRESETS.ocean;License
MIT © Shamaz Saeed
