Skip to content

No.209 · Overlays· New

Plain Consent

Cookie consent without the tricks: reject and accept are the same size and weight, side by side, with a ledger of exactly what each category stores, for how long and who sets it. Once chosen, the card folds into a tab, so changing your mind is one click.

The prompt

Copy this text

Automatic copying is unavailable. Copy the selected text using your device’s copy command.

Written for the variant you picked above: Paper

Build a cookie consent notice that a regulator and a reader would both call fair. The card sits at the bottom-left of the viewport (or of a positioned parent when contained), 25rem wide at most, with a 12px radius, a 1px ring and a soft shadow. It is a labelled region, not a modal: the page behind stays usable, there is no scrim and no focus trap. Mono caps eyebrow "Cookies"; a 24px serif heading "What this site keeps on your device"; one plain sentence saying how many things are essential and how many need a yes. Two buttons of identical size, weight and style, side by side: "Reject non-essential" and "Accept all". Both are 44px high with a 1px ink inset ring and fill with ink on hover. Neither is coloured, enlarged or placed to look like the default. Beneath them a text button "See exactly what each one does" (chevron rotates) folds a ledger open (grid-template-rows 0fr to 1fr, 320ms). Each category is a row: its name in a serif and either "Always on" (essential ones) or a real switch (a native checkbox with role=switch, 44px hit area, 34 by 20px track); a sentence about what it stores and why; and two small facts, "Lasts" and "Set by". A "Save these choices" button, same style, closes the ledger. After any decision: persist the choices in localStorage inside try/catch (read after mount so server and client agree; nothing animates until read), call onChange, and fold the card away (fade and 8px drop, 320ms) while a pill tab fades in at the same corner reading "Cookie choices · 2 of 3 optional on". Focus moves to the tab. Pressing the tab reopens the card and focuses its heading. The hidden side is inert and aria-hidden. Paper and Night themes. Selected variant — Paper (paper): Palette for this theme (Paper): --pc-accent #2f6bff; --pc-bg #ffffff; --pc-ink #1b1a17; --pc-line rgb(27 26 23 / 0.14); --pc-muted #6b6861; --pc-wash rgb(27 26 23 / 0.05). Treat these as the root colour tokens, one value per role, and name them to suit your code. Select it with the theme option set to "paper". Keep every dimension, spacing value, state and motion from the brief unchanged, and keep text at 4.5:1 contrast or better on these surfaces. This selection takes precedence over references to other themes or options in the general brief. Implement this selected appearance; do not add a variant picker or alternative appearances unless requested. Implementation requirements: Use React and TypeScript. Keep the component self-contained, with uniquely scoped CSS and no animation libraries. Include required imports, styles and font setup in the result. Interaction: Choose Accept or Reject (or open the ledger and set each one), then press the tab left in the corner to change your mind. Motion: Ledger folds in 320ms; the card fades and drops 8px in 320ms while the tab rises in after a 120ms delay; switches slide 200ms. Accessibility: A labelled region (not a modal) with no trap; switches are native checkboxes with role=switch, named by their category and described by what it stores. The ledger is a real list with a description list per row. The folded-away side is inert and aria-hidden, and focus moves to the control that appears. Reduced motion makes every change instant. Responsive behavior: Width is min(25rem, 100% - 32px) so it fits any screen; on short screens the card scrolls inside itself. Touch: Every control is 44px; nothing depends on hover. Preserve keyboard access, visible focus and reduced-motion behavior. Keep fictional demo data and simulated service calls in a separate usage example; expose callbacks for real actions and recover from rejected requests. Keep usage-example links inside the demo: use local buttons or prevent navigation. Demonstration links must not navigate to Vitrine routes or open other pages; preserve real URL support in the reusable component itself. Verify the result at narrow and wide viewport sizes, with keyboard input and reduced motion enabled.

Notes

Interaction
Choose Accept or Reject (or open the ledger and set each one), then press the tab left in the corner to change your mind.
Motion
Ledger folds in 320ms; the card fades and drops 8px in 320ms while the tab rises in after a 120ms delay; switches slide 200ms.
Accessibility
A labelled region (not a modal) with no trap; switches are native checkboxes with role=switch, named by their category and described by what it stores. The ledger is a real list with a description list per row. The folded-away side is inert and aria-hidden, and focus moves to the control that appears. Reduced motion makes every change instant.
Responsive
Width is min(25rem, 100% - 32px) so it fits any screen; on short screens the card scrolls inside itself.
On touch
Every control is 44px; nothing depends on hover.

Featured

402 components