Skip to content
← Blocks / Core

PIN Input

A copy-paste React access-code field for building a custom gate on useKnockCodes — masked field or segmented boxes, paste support, accessible errors. Zero dependencies.

CoreCore Blockcoreform

Best used for Building a custom access-code form on useKnockCodes without adopting a full template's layout.

The presentational primitive <KnockCodes> and every dialog-based block render internally. Independently useful any time you're building a fully custom access-code form on top of the headless useKnockCodes hook.

// Usage

Minimal setup

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

<PinInput
  value={code}
  onChange={setCode}
  onSubmit={() => submit(code)}
  submitting={state === "submitting"}
  error={error}
/>
Installation

Add this block to your project

Recommended

npx shadcn@latest add @knock-codes/pin-input

Also installs

  • Knock Codes Core
  • Knock Codes Types

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 (6)

  • 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
Other ways

GitHub shorthand

npx shadcn@latest add trivedi-vatsal/knock-codes/pin-input

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
value *stringCurrent input value (controlled).
onChange *(value: string) => voidCalled on every keystroke/paste.
onSubmit *() => voidCalled on Enter or the submit button, when not empty and not submitting.
submitting *booleanDisables the field and shows the busy label.
error *KnockCodesError | nullDrives which error message renders in the status region.
labelsKnockCodesLabelsOverrides for every user-facing string.
autoFocusbooleanFocus the field (or first box) on mount.
variant"field" | "boxes""field"Masked text field, or a segmented character grid.
lengthnumber6Slot count when variant is boxes.
groupSizenumber4Dash between groups when variant is boxes.
Notes

Accessibility

Field variant: labeled via a real <label>, show/hide is a button with an aria-label. Boxes variant: role=group with per-slot aria-labels. Errors and the submitting label live in a shared aria-live="polite" region.

Customization

`variant="field"` (default) is a masked text input for arbitrary-length codes. `variant="boxes"` is a fixed-length grid (`length`, `groupSize`). No verification logic of its own — drop it into any custom gate on `useKnockCodes`.

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.