Skip to content

Unlock Dialog

A copy-paste React unlock dialog for triggering an access-code prompt from a custom button or menu item. Zero dependencies.

Modal & OverlayCore Blockmodaldialog

Best used for Triggering an unlock prompt from a custom button or menu item instead of gating content directly.

The modal shell <ProtectedModal> renders internally, exposed on its own for cases where you want to trigger an unlock prompt manually rather than gating a whole content region.

// Usage

Minimal setup

const { state, error, submit } = useKnockCodes({ expectedHash: hash });
const [code, setCode] = useState("");

<UnlockDialog
  open={state !== "unlocked"}
  value={code}
  onChange={setCode}
  onSubmit={() => submit(code)}
  submitting={state === "submitting"}
  error={error}
/>
FIG.01Demo code: 4242
Dialog open below (contained to this preview frame).
Installation

Add this block to your project

Recommended

npx shadcn@latest add @knock-codes/unlock-dialog

Also installs

  • Knock Codes Core
  • Knock Codes Types
  • PIN Input

These install together as one atomic unit — even a presentational or read-only piece needs the full verification stack (hook, types, core) behind it to actually run.

Files created (7)

  • components/knock-codes/core/hash.ts
  • components/knock-codes/core/verify.ts
  • components/knock-codes/core/session.ts
  • components/knock-codes/core/storage.ts
  • components/knock-codes/react/types.ts
  • components/knock-codes/react/PinInput.tsx
  • components/knock-codes/react/UnlockDialog.tsx
Other ways

GitHub shorthand

npx shadcn@latest add trivedi-vatsal/knock-codes/unlock-dialog

Copy the files by hand

  1. Open the Code tab in the preview above.
  2. Create each path listed below in your project and paste its contents in.
  3. Do the same for anything listed under “Also installs”, if present.
// Props

API reference

PropTypeDefaultDescription
open *booleanWhether the dialog is visible.
value *stringCurrent input value (controlled).
onChange *(value: string) => voidCalled on every keystroke/paste.
onSubmit *() => voidCalled on Enter or the submit button.
submitting *booleanDisables the field and shows the busy label.
error *KnockCodesError | nullDrives which error message renders.
labelsKnockCodesLabelsOverrides for every user-facing string.
footerReactNodeExtra content under the form.
Notes

Accessibility

role="dialog" + aria-modal="true" + aria-labelledby pointing at the heading. Focus moves into the panel on open. Deliberately not dismissable via Escape or backdrop click — a gate you can dismiss without unlocking isn't a gate, so this omission is intentional, not a missing feature.

Customization

Composable standalone — trigger it from your own button or menu item instead of gating content directly, by controlling `open` yourself. Pass `footer` for help text or a support link under the form.

Security & Verification

Need a hash? Use the hash generator on Getting Started — computed locally, never sent anywhere.

The honest version

Knock Codes stops casual visitors, search engines, and forwarded links. Local mode does not stop anyone who opens DevTools — the hash ships in your client bundle by design. Server mode (swap one prop) hides the hash from the client; children you already bundled are still in the JavaScript, and a forged session works unless you wire validateSession. A velvet rope, with an optional real lock. Never marketed as more than that.

// Ready-made

Used in these templates

Want the whole screen instead of assembling it yourself? These templates already build on this block.

// Compose with

Blocks that pair well with this one

These combine naturally with this block, whether as a shared shell, a shared session, or a common fallback.