Headless primitivesOptOut

OptOut

Markdown
Loading…

Build the CCPA Do Not Sell dialog with your own markup.

What it does

OptOut.* gives you the Do Not Sell dialog in pieces: when it opens, the checkbox and its label, the Save and Cancel buttons, and the confirmation shown after saving. You supply the elements and the classes. Focus handling, Escape to close and the dialog roles come with OptOut.Root.

Use it only when CookieOptOut cannot produce the markup your design needs, and only if your site serves CCPA visitors. It is one checkbox, not a list of categories; for GDPR, build with Preferences.

Build a dialog

Render this in place of <CookieOptOut />. OptOut.Root renders nothing while the dialog is closed, so keep it as the outer element.

app/consent-opt-out.tsx
"use client";

import { OptOut } from "@cookieyes/nextjs";

export function ConsentOptOut() {
  return (
    <OptOut.Root className="overlay">
      <div className="dialog">
        <OptOut.Title className="dialog-title" />
        <OptOut.Close className="dialog-close" />
        <OptOut.Description className="dialog-text" />

        <div className="opt-out-row">
          <OptOut.Checkbox id="do-not-sell" />
          <OptOut.CheckboxLabel htmlFor="do-not-sell" />
        </div>

        <OptOut.Buttons className="dialog-actions">
          <OptOut.Cancel className="btn" />
          <OptOut.Save className="btn btn-primary" />
        </OptOut.Buttons>
        <OptOut.Success className="dialog-success" />
      </div>
    </OptOut.Root>
  );
}

Give the checkbox an id and the label the matching htmlFor, so clicking the label ticks the box. Render both Buttons and Success: after an opt-out, the buttons disappear and the confirmation takes their place. Saving without an opt-out closes the dialog at once.

The pieces

PieceRendersWhat it does
OptOut.Root<div>The overlay. Opens and closes the dialog, traps focus, closes on Escape. Keep it as the wrapper
OptOut.Title<h2>The dialog heading
OptOut.Description<p>The dialog text
OptOut.Close<button>Closes without saving
OptOut.Checkbox<input type="checkbox">The Do Not Sell checkbox. Ticked already if the visitor has opted out
OptOut.CheckboxLabel<label>The checkbox text
OptOut.Cancel<button>Closes without saving
OptOut.Save<button>Saves and shows the confirmation
OptOut.Buttons<div>Holds Cancel and Save. Hidden while the confirmation shows
OptOut.Success<div>The confirmation after an opt-out, with a ten-second countdown, then the dialog closes. It receives focus so screen readers announce it
OptOut.Branding<a>The "Powered by" link

Every piece takes className, style and the other props of the element it renders, and renders the translated text for the active language; pass children to replace it. Close, Cancel and Save accept asChild for your own button component, the same way as on Banner.

What Save actually writes

Save with the box ticked rejects every optional category. Save with the box unticked accepts every category. Cancel and Close record nothing.

Common mistakes

Error: OptOut.* sub-components must be rendered inside <OptOut.Root>. Checkbox, Save, Buttons or Success sits outside OptOut.Root. Move it inside.

Nothing shows after Save. If the box was not ticked, the dialog simply closes; that is expected. If it was ticked, OptOut.Success is not rendered.

Clicking the label does not tick the box. The checkbox id and the label htmlFor do not match.

The dialog never opens. The visitor is not under CCPA, or nothing opens it. Render Banner.DoNotSell, RecallButton, or your own button calling useConsentActions().showOptOut().

Next steps

On this page