shadcn.io is not affiliated with official shadcn/ui
Cookie Consent Login Block for Solid
A bakery subscription's cookie choices shown open over a drawn sign-in page: Essential locked on, Analytics and Marketing switches that start off, and three equal buttons, Reject all, Accept all and Save choices.
Installation
Overview
Ask for cookie choices without taking over the page, with this cookie consent login block for Solid with Ark UI. It's the consent card of Kneadful, a bakery subscription, shown over its sign-in page. The host header says "Cookie choices" and holds the real trigger, an outline "Review choices" Button, and the page itself is drawn in greys under a soft scrim inside a hairline frame with a plus mark on each corner. The card holds three categories: "Essential" is on and locked, "Analytics" and "Marketing" are Switches that start off, each with one line on what it does, and three equal buttons follow, Reject all, Accept all and Save choices, which is the Shine Button and the only coloured control. Any of them closes the card and a polite line under the page says what was chosen; the drawn page shows three dots for the choices once there is one. Nothing is stored. For preview the card is drawn open in place when the page loads; the trigger opens the real Popover, which is not modal, with the same switches and the same state. For any sign-in or landing page that sets non-essential cookies.
FAQ
Why is the card already open, and what do I keep?
So you can see it without a click. On load the card is a copy drawn in place on the stage: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Review choices button opens the real Popover, with the same CookieFields and the block's state, so a switch turned in place is on in the real one, and the copy stays closed until a reload. In your app keep the Popover (or a bottom sheet) and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
What does Save choices store, and how do I wire it for real?
Nothing leaves the page and no cookie is written: the choices live in the block's state, so a reload starts again. A polite line says what was chosen ("Saved: essential on, analytics on, marketing off. No cookie was written."). For real, write one first-party cookie, or a record on the account, with the choices, the date and the version of your policy, only after the visitor chooses; load analytics and marketing scripts only when their switch is on, and read the cookie before loading anything so the card doesn't come back for a returning visitor.
Why are Reject all and Accept all equal?
Because a choice that is easier one way isn't free. Both are outline buttons of the same size and weight, side by side, and Save choices, the coloured one, saves exactly what the switches show. Nothing is pre-switched: analytics and marketing start off, and essential cookies are described as always on because the page can't work without them, not because you agreed.
Why a popover and not a modal dialog?
A consent card shouldn't trap anyone: the page behind it stays usable, and Escape closes it without a choice, which means the same as rejecting. The real card is a Popover opened from the trigger, anchored under it, not modal, with focus returning to the trigger when it closes. If you want a decision before anything else, make it a bottom sheet instead and keep the same fields. The popover is held non-modal with modal={false}.
Is it usable with a keyboard and a screen reader?
Yes. In the real popover focus starts inside it and Escape closes it and puts focus back on Review choices. Each switch is named ("Analytics cookies") and described by its line, the locked one is read as on and unavailable, and the three buttons are ordinary buttons in the order Reject all, Accept all, Save choices. The copy shown on load moves no focus; Escape inside it closes it and puts focus on the trigger. One polite status line reports each choice.
How does it look on a phone?
The copy shown on load docks to the foot of the page as a bottom card, with the three categories scrolling above the buttons if the screen is short and the buttons stacked below them. The real popover opens under the trigger at the width of the screen, with the same stacked buttons.