shadcn.io is not affiliated with official shadcn/ui
Terms Consent Checkbox Form Block for Radix UI
A create-account panel with an email field and a consent checkbox that links the terms to a dialog, where Accept only works once the six clauses have been read to the end.
Installation
Overview
Make consent something people earn by reading with this terms checkbox form for React with Radix UI. A compact header sits over a hairline frame with a plus mark on each corner. An email band comes first, then a consent band: a checkbox whose label links "terms of service" and names the version, with a hint underneath that says whether the terms were read. The link opens a dialog with six short clauses in a named, focusable scroll region, and a line under it that says where you are. "I accept" is never disabled: pressed before the end it scrolls the terms down and says "Read to the end first"; pressed after, it closes the dialog and ticks the box. Pressing the box itself before reading opens the same dialog. Create account with the box unticked says "Accept the terms to continue" and focuses the box, and an email that is not one is flagged first. It's built from the Dialog, Checkbox, Field, Input, Shine Button and Guides. For sign-up forms, policy updates, waivers and any consent that should be informed.
FAQ
Why is the accept button not disabled until the end?
A disabled button gives no reason and cannot be focused. Here it stays pressable and answers: it scrolls the clauses to the end and says "Read to the end first". When the terms are short enough to fit without scrolling they count as read at once. Both the box and the button read the same read state, so what you read in one place counts in the other.
Does ticking the box prove someone read the terms?
No, and the block does not claim it. It makes reading easy to do and hard to skip by accident. If you must keep evidence, store the version, the time and the account on your server when the form is submitted, and show the same version number the user accepted.
How does it work with a keyboard and a screen reader?
The link is a real button inside the label, so it takes Tab and opens the dialog without ticking the box. Focus lands in the dialog, which traps it and returns it to the link when it closes. The clauses sit in a named region you can focus and scroll with the arrow keys and Space, and the status line under it announces progress. A failed Create account moves focus to the email or the box.
How does it look on a phone?
The dialog fills the height of the screen, with the clauses in the middle taking the room and the buttons pinned under them. The foot of the panel is pinned to the bottom of the screen with Create account at full width.
What stays local, and how do I connect it for real?
No account is created: the foot says "Created in this demo. Nothing sent." The six clauses are typed in CLAUSES. In your app, load the current terms and their version from your server, send the version with the sign-up request, and check the email there too.