Socket
Book a DemoInstallSign in
Socket

@consentry/ui

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@consentry/ui

Composable UI components for the Consentry consent manager. Built with Emotion and designed for use with @consentry/core or @consentry/next.

latest
Source
npmnpm
Version
0.2.5
Version published
Maintainers
1
Created
Source

@consentry/ui

Headless and fully customizable React components for consent management. Drop-in cookie banners, settings modals, and toggles — built for Next.js with zero configuration required.

✨ What You Get

  • 🍪 Complete cookie consent solution — banner, modal, settings
  • 🎨 Fully customizable — colors, text, positioning, behavior
  • Zero config required — works out of the box with sensible defaults
  • 🧩 Headless architecture — style it your way or use built-in themes
  • 🔄 Smooth animations — powered by Framer Motion
  • Accessibility first — keyboard navigation, screen readers, focus management
  • 📱 Mobile optimized — responsive design that works everywhere

📦 Installation

npm install @consentry/ui @consentry/next @consentry/core

🚀 Quick Start (5 minutes)

Create providers/consent-provider.tsx:

"use client";
import { ConsentConfig, ConsentManagerProvider } from "@consentry/next";
import ConsentManager from "@consentry/ui";

const ConsentProvider = ({ children }: { children: React.ReactNode }) => {
  const consentConfig: ConsentConfig = {
    defaults: {
      functional: true,
      performance: false,
      advertising: false,
      social: false,
    },
    scripts: [
      {
        id: "gtag-js",
        category: "functional",
        consentRequired: false,
        strategy: "afterInteractive",
        src: "https://www.googletagmanager.com/gtag/js?id=YOUR_GA_ID",
      },
      {
        id: "gtag-init",
        category: "functional",
        consentRequired: false,
        strategy: "afterInteractive",
        content: `
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', 'YOUR_GA_ID');
          gtag('consent', 'default', {
            analytics_storage: 'denied',
            ad_storage: 'denied',
            ad_user_data: 'denied',
            ad_personalization: 'denied'
          });
        `,
      },
    ],
  };

  return (
    <ConsentManagerProvider config={consentConfig}>
      <ConsentManager mode="modal" dark={false} />
      {children}
    </ConsentManagerProvider>
  );
};

export default ConsentProvider;

Step 2: Add to Your App

Create app/providers.tsx:

"use client";
import ConsentProvider from "@/providers/consent-provider";
import { ReactNode } from "react";

export const Providers = ({ children }: { children: ReactNode }) => {
  return <ConsentProvider>{children}</ConsentProvider>;
};

Step 3: Wrap Your App

Update app/layout.tsx:

import { Providers } from "./providers";
import "./globals.css";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

That's it! Your consent manager is now active. Users will see a banner on first visit and can manage preferences anytime.

🎛️ ConsentManager Component

The main UI component that handles everything automatically.

Basic Usage

<ConsentManager mode="modal" dark={false} />

All Props

interface ConsentManagerProps {
  // Layout & Positioning
  mode?: "modal" | "top" | "bottom"; // Banner position
  dark?: boolean; // Dark/light theme
  hideSettingsButton?: boolean; // Hide floating settings button

  // Customization
  colors?: ColorTheme; // Custom color scheme
  labels?: CustomLabels; // Custom text/translations
  classNames?: CustomClassNames; // CSS class overrides

  // Behavior
  categories?: ConsentCategory[]; // Override default categories
  autoShow?: boolean; // Auto-show banner (default: true)
  showDeclineAll?: boolean; // Show "Decline All" button
  showAcceptAll?: boolean; // Show "Accept All" button
}

🎨 Customization Examples

Custom Colors

<ConsentManager
  mode="modal"
  colors={{
    light: {
      primary: "#6B50A2",
      primaryHover: "#4A2F7F",
      primaryText: "#FFFFFF",
      settingsButton: "#645876",
      settingsButtonHover: "#403D57",
      settingsButtonText: "#FFFFFF",
      background: "#FFFFFF",
      text: "#403D57",
      border: "#D6D9E1",
    },
    dark: {
      primary: "#8B5FD6",
      primaryHover: "#A67EE5",
      primaryText: "#FFFFFF",
      settingsButton: "#6B7280",
      settingsButtonHover: "#9CA3AF",
      settingsButtonText: "#FFFFFF",
      background: "#1F2937",
      text: "#F9FAFB",
      border: "#374151",
    },
  }}
/>

Custom Text/Labels

<ConsentManager
  mode="modal"
  labels={{
    banner: {
      title: "We value your privacy",
      description: "We use cookies to enhance your experience and analyze our traffic.",
      acceptAll: "Accept All",
      declineAll: "Decline All",
      settings: "Customize",
    },
    modal: {
      title: "Cookie Preferences",
      description: "Choose which cookies you'd like to accept.",
      save: "Save Preferences",
      acceptAll: "Accept All",
      declineAll: "Decline All",
    },
    categories: {
      functional: {
        title: "Essential Cookies",
        description: "Required for basic site functionality.",
      },
      performance: {
        title: "Performance Cookies",
        description: "Help us analyze site usage and improve performance.",
      },
      advertising: {
        title: "Advertising Cookies",
        description: "Used to deliver relevant ads and measure campaign effectiveness.",
      },
      social: {
        title: "Social Media Cookies",
        description: "Enable social media features and content sharing.",
      },
    },
  }}
/>

Banner Positions

// Modal overlay (recommended)
<ConsentManager mode="modal" />

// Top banner
<ConsentManager mode="top" />

// Bottom banner
<ConsentManager mode="bottom" />

⚙️ Configuration Types

ConsentConfig

interface ConsentConfig {
  debug?: boolean; // Enable debug logging
  defaults: CookiePreferences; // Default consent state
  scripts: ConsentScript[]; // Scripts to manage
}

CookiePreferences

interface CookiePreferences {
  functional: boolean; // Always true (required for site to work)
  performance: boolean; // Analytics, monitoring
  advertising: boolean; // Ads, marketing pixels
  social: boolean; // Social media embeds, sharing
}

ConsentScript

interface ConsentScript {
  id: string; // Unique identifier
  category: ConsentCategory; // Cookie category
  consentRequired?: boolean; // Require explicit consent
  strategy?: "afterInteractive" | "lazyOnload" | "beforeInteractive";
  src?: string; // External script URL
  content?: string; // Inline script content
  noscript?: string; // Fallback for no-JS
  vendor?: string; // Third-party service name
  default?: boolean; // Load by default
}

📜 Script Examples

Google Analytics 4

scripts: [
  {
    id: "gtag-js",
    category: "performance",
    consentRequired: true,
    strategy: "afterInteractive",
    src: "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX",
    vendor: "Google Analytics",
  },
  {
    id: "gtag-init",
    category: "performance",
    consentRequired: true,
    strategy: "afterInteractive",
    content: `
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'G-XXXXXXXXXX', {
        send_page_view: true,
        cookie_flags: 'SameSite=None;Secure'
      });
      // Required for Google Analytics v2 consent mode - must start with 'denied'
      // These will be updated to 'granted' when user provides consent
      gtag('consent', 'default', {
        analytics_storage: 'denied',
        ad_storage: 'denied',
        ad_user_data: 'denied',
        ad_personalization: 'denied'
      });
    `,
    vendor: "Google Analytics",
  },
];

Facebook Pixel

{
  id: "facebook-pixel",
  category: "advertising",
  consentRequired: true,
  strategy: "afterInteractive",
  content: `
    !function(f,b,e,v,n,t,s)
    {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
    n.callMethod.apply(n,arguments):n.queue.push(arguments)};
    if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
    n.queue=[];t=b.createElement(e);t.async=!0;
    t.src=v;s=b.getElementsByTagName(e)[0];
    s.parentNode.insertBefore(t,s)}(window, document,'script',
    'https://connect.facebook.net/en_US/fbevents.js');
    fbq('init', 'YOUR_PIXEL_ID');
    fbq('track', 'PageView');
  `,
  noscript: `<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=YOUR_PIXEL_ID&ev=PageView&noscript=1" />`,
  vendor: "Meta",
}

Hotjar

{
  id: "hotjar",
  category: "performance",
  consentRequired: true,
  strategy: "afterInteractive",
  content: `
    (function(h,o,t,j,a,r){
        h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
        h._hjSettings={hjid:YOUR_HOTJAR_ID,hjsv:6};
        a=o.getElementsByTagName('head')[0];
        r=o.createElement('script');r.async=1;
        r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
        a.appendChild(r);
    })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
  `,
  vendor: "Hotjar",
}

YouTube Embeds

{
  id: "youtube-embeds",
  category: "social",
  consentRequired: true,
  strategy: "lazyOnload",
  content: `
    // Enable YouTube embeds when social cookies are accepted
    document.querySelectorAll('[data-youtube-consent]').forEach(el => {
      el.style.display = 'block';
    });
  `,
  vendor: "YouTube",
}

Twitter/X Embeds

{
  id: "twitter-widgets",
  category: "social",
  consentRequired: true,
  strategy: "lazyOnload",
  src: "https://platform.twitter.com/widgets.js",
  vendor: "Twitter/X",
}

🎛️ Programmatic Control

Open Settings Modal

import { openConsentSettings } from "@consentry/ui";

function PrivacyPage() {
  return (
    <div>
      <h1>Privacy Policy</h1>
      <button onClick={() => openConsentSettings()}>Manage Cookie Preferences</button>
    </div>
  );
}

Get Current Preferences

import { useConsentManager } from "@consentry/next";

function MyComponent() {
  const { preferences, updatePreferences } = useConsentManager();

  return (
    <div>
      <p>Analytics enabled: {preferences.performance ? "Yes" : "No"}</p>
      <button onClick={() => updatePreferences({ performance: !preferences.performance })}>
        Toggle Analytics
      </button>
    </div>
  );
}

🎨 Advanced Styling

CSS Classes Available

classNames={{
  // Main wrapper
  wrapper: "consent-wrapper",

  // Banner classes
  banner: {
    container: "cookie-banner",
    header: "cookie-banner-header",
    title: "cookie-banner-title",
    message: "cookie-banner-message",
    closeButton: "cookie-banner-close-button",
    buttonRow: "cookie-banner-button-row",
    acceptButton: "cookie-banner-accept-button",
    rejectButton: "cookie-banner-reject-button",
    customizeButton: "cookie-banner-customize-button",
    content: "cookie-banner-content",
  },

  // Modal classes
  modal: {
    overlay: "cookie-modal-overlay",
    container: "cookie-modal-container",
    title: "cookie-modal-title",
    section: "cookie-modal-section",
    row: "cookie-modal-row",
    rowText: "cookie-modal-row-text",
    rowTitle: "cookie-modal-row-title",
    rowDescription: "cookie-modal-row-description",
    toggleSwitch: "cookie-modal-switch",
    toggleThumb: "cookie-modal-switch-thumb",
    buttonRow: "cookie-modal-button-row",
    saveButton: "cookie-modal-save-button",
    cancelButton: "cookie-modal-cancel-button",
  },

  // Settings button
  settingsButton: "cookie-settings-button",
}}

Example: Custom styling

/* Style the banner */
.cookie-banner {
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  border: 1px solid #e5e7eb;
}

.cookie-banner-title {
  font-weight: 700;
  font-size: 1.2rem;
  color: #1f2937;
}

.cookie-banner-accept-button {
  background: #6b50a2;
  color: white;
  border-radius: 6px;
  padding: 8px 16px;
}

/* Style the modal */
.cookie-modal-overlay {
  backdrop-filter: blur(4px);
}

.cookie-modal-container {
  border-radius: 16px;
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}

.cookie-modal-switch {
  background: #e5e7eb;
  transition: all 0.2s;
}

.cookie-modal-switch[data-checked="true"] {
  background: #6b50a2;
}

/* Style the settings button */
.cookie-settings-button {
  border-radius: 50%;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  background: #6b50a2;
  color: white;
}

🌍 Internationalization

Multi-language Support

const getLabels = (locale: string) => {
  const translations = {
    en: {
      banner: {
        title: "We value your privacy",
        description: "We use cookies to enhance your experience.",
        acceptAll: "Accept All",
        declineAll: "Decline All",
        settings: "Settings",
      },
    },
    es: {
      banner: {
        title: "Valoramos tu privacidad",
        description: "Utilizamos cookies para mejorar tu experiencia.",
        acceptAll: "Aceptar Todo",
        declineAll: "Rechazar Todo",
        settings: "Configuración",
      },
    },
  };

  return translations[locale] || translations.en;
};

// Usage
<ConsentManager labels={getLabels("es")} />;

🔧 Environment-Specific Configs

Development vs Production

const consentConfig: ConsentConfig = {
  debug: process.env.NODE_ENV === "development",
  defaults: {
    functional: true,
    performance: process.env.NODE_ENV === "production",
    advertising: false,
    social: false,
  },
  scripts: process.env.NODE_ENV === "production" ? productionScripts : [],
};

🚨 Common Issues & Solutions

Scripts Not Loading

// ❌ Wrong - script won't be managed
<Script src="https://analytics.example.com/script.js" />;

// ✅ Correct - add to consent config
scripts: [
  {
    id: "analytics",
    category: "performance",
    consentRequired: true,
    strategy: "afterInteractive",
    src: "https://analytics.example.com/script.js",
  },
];

Styling Not Applied

// ❌ Wrong - CSS loaded after component
import ConsentManager from "@consentry/ui";
import "./consent-styles.css";

// ✅ Correct - CSS loaded first
import "./consent-styles.css";
import ConsentManager from "@consentry/ui";

Hydration Issues

// ❌ Wrong - server/client mismatch
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return null;

// ✅ Correct - use dynamic import
import dynamic from "next/dynamic";
const ConsentManager = dynamic(() => import("@consentry/ui"), { ssr: false });

📚 Full Example

Complete setup with custom styling, multiple analytics, and internationalization:

"use client";
import { ConsentConfig, ConsentManagerProvider } from "@consentry/next";
import ConsentManager from "@consentry/ui";
import { useRouter } from "next/navigation";

const ConsentProvider = ({ children }: { children: React.ReactNode }) => {
  const router = useRouter();

  const consentConfig: ConsentConfig = {
    debug: process.env.NODE_ENV === "development",
    defaults: {
      functional: true,
      performance: false,
      advertising: false,
      social: false,
    },
    scripts: [
      // Google Analytics
      {
        id: "gtag-js",
        category: "performance",
        consentRequired: true,
        strategy: "afterInteractive",
        src: "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX",
        vendor: "Google Analytics",
      },
      {
        id: "gtag-init",
        category: "performance",
        consentRequired: true,
        strategy: "afterInteractive",
        content: `
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', 'G-XXXXXXXXXX');
          gtag('consent', 'default', {
            analytics_storage: 'denied',
            ad_storage: 'denied'
          });
        `,
        vendor: "Google Analytics",
      },

      // Facebook Pixel
      {
        id: "facebook-pixel",
        category: "advertising",
        consentRequired: true,
        strategy: "afterInteractive",
        content: `
          // Facebook Pixel code here
        `,
        vendor: "Meta",
      },

      // Hotjar
      {
        id: "hotjar",
        category: "performance",
        consentRequired: true,
        strategy: "afterInteractive",
        content: `
          // Hotjar code here
        `,
        vendor: "Hotjar",
      },
    ],
  };

  return (
    <ConsentManagerProvider config={consentConfig}>
      <ConsentManager
        mode="modal"
        dark={false}
        colors={{
          light: {
            primary: "#6B50A2",
            primaryHover: "#4A2F7F",
            primaryText: "#FFFFFF",
            settingsButton: "#645876",
            settingsButtonHover: "#403D57",
            settingsButtonText: "#FFFFFF",
            background: "#FFFFFF",
            text: "#403D57",
            border: "#D6D9E1",
          },
        }}
        labels={{
          banner: {
            title: "We respect your privacy",
            description:
              "We use cookies to improve your experience and analyze our website traffic. You can customize your preferences below.",
            acceptAll: "Accept All Cookies",
            declineAll: "Decline All",
            settings: "Customize Settings",
          },
          modal: {
            title: "Cookie Preferences",
            description:
              "We use different types of cookies to optimize your experience on our website. You can customize your preferences for each category below.",
            save: "Save My Preferences",
            acceptAll: "Accept All",
            declineAll: "Decline All",
          },
        }}
        classNames={{
          banner: "rounded-lg shadow-xl",
          bannerTitle: "text-xl font-bold",
          settingsButton: "rounded-full shadow-lg",
        }}
      />
      {children}
    </ConsentManagerProvider>
  );
};

export default ConsentProvider;
  • @consentry/core — Core consent logic (framework-agnostic)
  • @consentry/next — Next.js integration hooks and providers

📄 License

MIT — Copyright © 2025 Mustafa ONAL

Keywords

cookie-consent

FAQs

Package last updated on 19 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts