Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Feedback

Cookie Consent

Feedback

Cookie Consent React component for Tailwind CSS v4

BannerEmoji Reaction
Live props
Content
title
description
policyHref
showReject
showSettings
Appearance
variant
tone
color
radius
Layout
position
portal
State
defaultOpen
defaultSettingsOpen
Behavior
blocking
delayAt once
storageKey
version1
storage
maxAgeDays180d
responsive
Code
import { CookieConsent } from "@/components/ui/cookie-consent"

<CookieConsent />
  1. Home
  2. Components
  3. Feedback
  4. Cookie Consent
Pro

Cookie Consent React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React cookie consent banner for GDPR: a bottom bar or card with Accept, Reject and Settings, per-category switches, and a gate for embeds.

The bar rises from the bottom edge once the page has painted, only for visitors who have not chosen yet. Accept all, Reject all and Settings are equal buttons (on a phone three full-width 48px buttons with Accept on top); any choice slides the bar away, saves the record for 180 days and is announced to screen readers. Settings opens a dialog on desktop and a full-height bottom sheet on phones: flip a switch per category (Strictly necessary is locked on), tap Show cookies for the list behind it, then Save choices or Accept all; closing it any other way discards the draft. Keyboard: Tab reaches the buttons and the policy link, Enter or Space activates, Escape closes the settings without saving. With blocking the page dims, focus starts on Reject all, Tab stays inside and Escape does nothing until a choice; afterwards focus returns to what had it before the bar. A footer link (CookieSettingsLink) reopens the settings from anywhere; raising version brings the bar back.

Cookie Consent is a Pro React component in the React feedback components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add cookie-consent, together with useConsent, Button, Switch, Dialog, Collapsible and 6 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add cookie-consent

Cookie Consent is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import CookieConsent from @/components/ui/cookie-consent.

import type { ReactNode } from "react"
import { ConsentGate, CookieConsent, CookieSettingsLink } from "@/components/ui/cookie-consent"

export function SiteShell({ children }: { children: ReactNode }) {
  return (
    <>
      {children}
      <ConsentGate category="marketing" className="aspect-video">
        <iframe title="Acme CRM overview" src="https://www.youtube-nocookie.com/embed/abc123" className="aspect-video w-full rounded-2xl" />
      </ConsentGate>
      <footer>
        <CookieSettingsLink />
      </footer>
      <CookieConsent
        policyHref="/cookie-policy"
        delay={500}
        onDecide={(record) => {
          if (record.choices.analytics) console.log("load analytics")
        }}
      />
    </>
  )
}

Props

  • titledefault ""
    ReactNode

    The heading. Empty uses labels.title ("We use cookies" by default).

  • descriptiondefault ""
    ReactNode

    The text under the heading. Empty uses labels.description; the policy link follows it.

  • policyHrefdefault ""
    string

    The cookie policy URL, shown as an underlined link after the description. Empty hides the link.

  • icon
    ReactNode | false

    A cookie in a 40px tinted tile by default; pass your own icon, or false to hide it.

  • categories
    ConsentCategoryConfig[]

    { id, label, description?, required?, cookies?: { name, provider?, duration?, purpose? }[] }[]. Display order; necessary (or any required) is locked on. Default DEFAULT_CONSENT_CATEGORY_CONFIG (English), or CONSENT_CATEGORY_CONFIG_RO.

  • labels
    Partial<CookieConsentLabels>

    Every string: region, title, description, policy, acceptAll, rejectAll, settings, settingsTitle, settingsDescription, save, alwaysOn, showCookies(count), hideCookies, cookieName, provider, duration, purpose, saved, gateTitle(category), gateDescription, gateAllow, close. English by default; pass COOKIE_CONSENT_LABELS_RO for the ready Romanian copy.

  • variantdefault "bar"
    "bar" | "card"

    bar: a full-width glass bar at the bottom (a card-like sheet on phones). card: a 400px floating card.

  • positiondefault "bottom"
    "bottom" | "bottom-start" | "bottom-end"

    Where the card floats (centered, start or end corner); for the bar, where its content column sits on wide screens. Unset, the bar uses bottom and the card bottom-start.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The Accept button, the switches and the icon tile. Reject keeps the neutral soft look at the same size, so both choices weigh the same.

  • colordefault ""
    string

    Any CSS color; replaces the tone on the Accept button, the switches and the icon tile.

  • radiusdefault "md"
    "none" | "sm" | "md" | "lg" | "full"

    Corner shape of the buttons, scaled per size like the button's (the 48px phone buttons take the lg step).

  • showRejectdefault true
    boolean

    Reject all next to Accept all, as easy as accepting. Keep it on in the EU.

  • showSettingsdefault true
    boolean

    The Settings button that opens the per-category panel.

  • defaultOpendefault false
    boolean

    Shows the bar on mount even when the visitor already chose. Unset, the bar shows exactly while the visitor has not decided. Controlled with open / onOpenChange.

  • open
    boolean

    Controls the bar's visibility (previews, a consent page). onOpenChange(false) fires when a choice hides it.

  • onOpenChange
    (open: boolean) => void

    Called when a choice hides the bar.

  • defaultSettingsOpendefault false
    boolean

    Opens the settings panel on mount. Controlled with settingsOpen / onSettingsOpenChange; openConsentSettings() opens it from anywhere.

  • settingsOpen
    boolean

    Controls the settings panel.

  • onSettingsOpenChange
    (open: boolean) => void

    Called when the settings panel opens or closes.

  • blockingdefault false
    boolean

    Dims the page and traps focus until a choice (role dialog, focus on Reject all, Escape does nothing). Non-blocking is the default and the usual advice; use this only where legally advised.

  • delaydefault 0
    number

    Milliseconds after hydration before the bar shows, so the page paints first. The bar is fixed, so it never shifts the layout.

  • storageKeydefault "ui-consent"
    string

    Cookie / storage key of the record, passed to useConsent. Every consent hook, gate and link with the same key shares it.

  • versiondefault 1
    number

    The policy version. Bump it when the policy or the categories change: older choices count as undecided and the bar returns.

  • storagedefault "cookie"
    "cookie" | "local" | "session"

    Where the record lives. A cookie can be read on the server too. When storage is blocked the choice lives in memory for the session.

  • maxAgeDaysdefault 180
    number

    How long a cookie choice is kept before the visitor is asked again.

  • responsivedefault true
    boolean

    Settings as a full-height bottom sheet below 768px (a dialog otherwise).

  • portaldefault true
    boolean

    Renders the region as the first child of document.body (or container), so keyboard and screen reader users reach it before the page. false renders it in place with absolute instead of fixed (previews, a phone frame, docs).

  • container
    HTMLElement | null

    The portal target instead of document.body. A container with contain: layout or a transform keeps the fixed bar inside it.

  • onDecide
    (record: ConsentRecord) => void

    After every decision (accept, reject, save): { version, choices, decidedAt, method }. Load scripts here, or use onConsentChange from use-consent.

  • classNames
    Partial<Record<"overlay" | "inner" | "icon" | "content" | "title" | "description" | "policy" | "actions" | "button" | "settings" | "category" | "cookies" | "cookie", string>>

    Extra classes for the inner parts; settings is the dialog / sheet content (the data-slot cookie-consent-settings marks the category list inside it).

  • className
    string

    Extra classes for the bar or card itself, merged last.

Parts

  • ConsentGate

    component

    Renders children only when the category is allowed, nothing during hydration, and otherwise a placeholder tile with labels.gateTitle and an Allow and load button that turns that category on. Props: { category; children; fallback?; storageKey?; version?; storage?; maxAgeDays?; categories?; icon?; tone?; color?; radius?; labels? }.

  • CookieSettingsLink

    component

    A link-styled button for the footer that calls openConsentSettings(storageKey). Children default to labels.settingsTitle. Props: ButtonProps & { storageKey?; labels? }.

  • COOKIE_CONSENT_LABELS_RO

    constant

    Ready Romanian copy. Type: CookieConsentLabels.

  • CONSENT_CATEGORY_CONFIG_RO

    constant

    Ready Romanian categories (necessary, preferences, analytics, marketing). Type: ConsentCategoryConfig[].

  • DEFAULT_COOKIE_CONSENT_LABELS

    constant

    The English default copy, to extend. Type: CookieConsentLabels.

  • DEFAULT_CONSENT_CATEGORY_CONFIG

    constant

    The English default categories, to extend or reorder. Type: ConsentCategoryConfig[].

  • ConsentCategoryConfig

    type

    One category of categories: { id, label, description?, required?, cookies? }.

Examples

Card, bottom-start

A 400px floating card for sites where a full-width bar feels too loud.

Settings with cookie lists

Opened from a link anywhere on the page. A draft per category; each one lists its cookies.

ConsentGate around a YouTube embed

The video loads only once marketing is allowed; the placeholder asks for it in place.

Blocking before checkout

Dims the page, keeps focus inside, and Escape does nothing until a choice. Use only where advised.

Romanian copy

COOKIE_CONSENT_LABELS_RO and CONSENT_CATEGORY_CONFIG_RO: the ready Romanian wording, with no strings to write.

Policy version bump

A new version makes old choices undecided, so the bar comes back.

Dependencies

motionlucide-reactuse-consentbuttonswitchdialogcollapsiblebadgeuse-media-queryuse-controllable-statemotiontonesui-config

Files

  • components/ui/cookie-consent.tsx

FAQ

Is the React Cookie Consent component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Cookie Consent?

Run npx wingo-ui@latest add cookie-consent. It also adds the Wingo UI items it builds on (useConsent, Button, Switch, Dialog, Collapsible and 6 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/cookie-consent.

How does Cookie Consent behave on phones?

Settings as a full-height bottom sheet below 768px (a dialog otherwise). The responsive prop controls this and is on by default.

See also

useConsenthookBannerSwitchDialog

Used in

Marketplace Shell

More React feedback components

Empty StateNotification BellNotification CenterSetup ChecklistSpinnerSkeleton
All 13 React feedback components

Articles using this component

  • Nextjs Cookie Consent: GDPR Banner and Consent Mode v2

    Next.js and Tailwind CSS · Oct 16, 2026 · 12 min read

PreviousBannerNext Emoji Reaction
A
acme.com
ProductPricingCustomers
Acme CRM 3.2

Your customers, quotes and invoices, in one place.

Used by 1,200 companies from New York to Seattle. From $29 a month.

© 2026 Acme Inc.Terms
storageKey="ui-lab-cookie-demo" version=1 storage="cookie" maxAgeDays=180 delay=0 responsive=true portal=true defaultOpen=autono choice for v1: the bar is shown