The NDPR Toolkit provides a flexible, customizable consent management system that can be used in three ways:
- Full UI Mode - Pre-built components with theming
- Headless Mode - State management only, bring your own UI
- Hybrid Mode - Mix of custom and pre-built components
npm install @tantainnovative/ndpr-toolkit
# or
yarn add @tantainnovative/ndpr-toolkit
# or
pnpm add @tantainnovative/ndpr-toolkitimport { ConsentManager } from '@tantainnovative/ndpr-toolkit';
function App() {
return (
<ConsentManager>
{/* Your app content */}
</ConsentManager>
);
}import { ConsentManager, useConsent } from '@tantainnovative/ndpr-toolkit';
function App() {
return (
<ConsentManager headless>
<CustomCookieBanner />
{/* Your app content */}
</ConsentManager>
);
}
function CustomCookieBanner() {
const { hasUserConsented, acceptAll, rejectAll, openSettings } = useConsent();
if (hasUserConsented) return null;
return (
<div className="your-custom-banner">
<button onClick={acceptAll}>Accept</button>
<button onClick={rejectAll}>Reject</button>
<button onClick={openSettings}>Settings</button>
</div>
);
}The main component that provides consent context to your application.
<ConsentManager
headless={false} // Enable/disable built-in UI
onConsentChange={handleChange} // Callback when consent changes
storageKey="my-consent" // Custom storage key
initialConsent={{ // Initial consent state
analytics: true,
marketing: false
}}
>
{children}
</ConsentManager>Access consent state and actions anywhere in your app.
const {
// State
hasUserConsented, // Has the user made a choice?
consentState, // Current consent for each category
showBanner, // Is banner visible?
showSettings, // Is settings modal visible?
// Actions
acceptAll, // Accept all categories
rejectAll, // Reject non-essential categories
savePreferences, // Save custom preferences
openSettings, // Show settings modal
closeSettings, // Hide settings modal
updateConsent, // Update individual category
} = useConsent();<ConsentManager>
{({ consents, actions, ui }) => (
<>
{!consents.hasUserConsented && (
<CustomBanner
onAccept={actions.acceptAll}
onReject={actions.rejectAll}
onSettings={ui.openSettings}
/>
)}
</>
)}
</ConsentManager><ConsentManager
renderBanner={({ onAcceptAll, onRejectAll, onOpenSettings }) => (
<MyCustomBanner
onAccept={onAcceptAll}
onDecline={onRejectAll}
onManage={onOpenSettings}
/>
)}
renderSettings={({ consentState, onUpdateConsent, onSave, onClose }) => (
<MyCustomSettings
consent={consentState}
onChange={onUpdateConsent}
onSave={onSave}
onCancel={onClose}
/>
)}
/><ConsentManager
components={{
Banner: CustomBanner,
Settings: CustomSettings,
}}
/>import {
ConsentBanner,
ConsentSettings
} from '@tantainnovative/ndpr-toolkit/unstyled';
<ConsentBanner unstyled className="my-banner-styles">
<ConsentBanner.Message>
We use cookies...
</ConsentBanner.Message>
<ConsentBanner.Actions>
<button>Accept</button>
<button>Reject</button>
</ConsentBanner.Actions>
</ConsentBanner>import { useConsentManager } from '@tantainnovative/ndpr-toolkit';
function App() {
const manager = useConsentManager();
useEffect(() => {
// Subscribe to events
const unsubscribe = manager.on('consent:accepted', (consents) => {
console.log('Consents accepted:', consents);
initializeAnalytics();
});
manager.on('consent:updated', (consents) => {
updateServices(consents);
});
return unsubscribe;
}, []);
}Available events:
consent:accepted- User accepted all cookiesconsent:rejected- User rejected non-essential cookiesconsent:updated- Consent preferences changedbanner:shown/banner:hidden- Banner visibility changedsettings:opened/settings:closed- Settings modal visibility changed
import { createConsentContext } from '@tantainnovative/ndpr-toolkit';
// Define your custom categories
interface MyCategories {
necessary: boolean;
performance: boolean;
targeting: boolean;
social: boolean;
}
// Create typed context
const { ConsentProvider, useConsent } = createConsentContext<MyCategories>();
// Use in your app
<ConsentProvider
categories={[
{ id: 'necessary', name: 'Essential', required: true },
{ id: 'performance', name: 'Performance' },
{ id: 'targeting', name: 'Targeting' },
{ id: 'social', name: 'Social Media' },
]}
>
<App />
</ConsentProvider><ConsentManager
position="bottom" // 'top' | 'bottom' | 'center'
animation="slide" // 'slide' | 'fade' | 'none'
fullWidth={true}
maxWidth="1200px"
theme={{
primaryColor: '#3B82F6',
textColor: '#1F2937',
backgroundColor: '#FFFFFF',
}}
/>import { cookieUtils } from '@tantainnovative/ndpr-toolkit';
// Set a cookie
cookieUtils.set('user_pref', 'dark_mode', 30); // 30 days
// Get a cookie
const pref = cookieUtils.get('user_pref');
// Delete a cookie
cookieUtils.delete('user_pref');import { consentStorage } from '@tantainnovative/ndpr-toolkit';
// Save consent data
consentStorage.save('consent_key', consentData);
// Load consent data
const data = consentStorage.load('consent_key');
// Remove consent data
consentStorage.remove('consent_key');function App() {
const { consentState, hasUserConsented } = useConsent();
useEffect(() => {
if (hasUserConsented) {
window.gtag?.('consent', 'update', {
'analytics_storage': consentState.analytics ? 'granted' : 'denied',
'ad_storage': consentState.marketing ? 'granted' : 'denied',
});
}
}, [hasUserConsented, consentState]);
}function App() {
const { consentState } = useConsent();
useEffect(() => {
if (consentState.marketing) {
// Initialize Facebook Pixel
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
}
}, [consentState.marketing]);
}-
Always provide a way to change preferences
<button onClick={() => openSettings()}> Cookie Preferences </button>
-
Handle server-side rendering
if (typeof window === 'undefined') { return null; // Don't render consent UI on server }
-
Respect user choices
// Don't initialize tracking until consent is given if (consentState.analytics) { initializeAnalytics(); }
-
Provide clear information
<ConsentBanner> <h3>We value your privacy</h3> <p>We use cookies to improve your experience and analyze site usage.</p> <a href="/privacy-policy">Learn more</a> </ConsentBanner>
// Before
<ConsentManager theme={{ primaryColor: '#000' }}>
<App />
</ConsentManager>
// After
<ConsentManager headless>
<CustomBanner />
<CustomSettings />
<App />
</ConsentManager>// Before
<ConsentManager onAccept={handleAccept}>
<App />
</ConsentManager>
// After
<ConsentManager>
{({ actions }) => {
useEffect(() => {
if (actions.acceptAll) {
handleAccept();
}
}, []);
return <App />;
}}
</ConsentManager>The toolkit is fully typed. Import types as needed:
import type {
ConsentCategories,
ConsentState,
ConsentActions,
BannerProps,
SettingsProps
} from '@tantainnovative/ndpr-toolkit';- Check if
hasUserConsentedis alreadytruein localStorage - Clear consent data:
consentStorage.remove('ndpr-consent-set')
- Ensure you're not using
headlessmode with built-in components - Check if
unstyledprop is set totrue
- Verify localStorage is available
- Check if custom
storageKeyis consistent
For issues and feature requests, please visit our GitHub repository.