→ Core
Gate Wrapper
The shared outer-positioning primitive every visible block composes on.
Best used for Composing a fully custom access-code UI that still needs the standard page/inline positioning.
Not a verification strategy — just layout. Every block that renders visible UI (<KnockCodes>,
<ProtectedCard>, <AccessDeniedScreen>, ...) composes on this instead of re-deriving centering/spacing.
- components
- knock-codes
- react
import type { ReactNode } from "react";
import { cx } from "./cx.ts";
/** Outer positioning only — "page" centers full-height, "inline" flows in place. Visual treatment (borders/padding/shadow) is each block's own concern, not this wrapper's. */
export type GateWrapperVariant = "page" | "inline";
export interface GateWrapperProps {
children: ReactNode;
/** @default "page" */
variant?: GateWrapperVariant;
className?: string;
}
const VARIANT_CLASSES: Record<GateWrapperVariant, string> = {
page: "flex min-h-[100dvh] w-full items-center justify-center p-6",
inline: "flex w-full items-start",
};
/**
* The shared outer-positioning primitive every visible block composes on —
* a plain container, not a verification strategy. Kept separate from
* `<KnockCodes>` so blocks like `<ProtectedRoute>`/`<EmbeddedGate>` can reuse
* the same page-vs-inline placement without re-deriving it, while each block
* still owns its own inner card/border/spacing styling.
*/
export function GateWrapper({ children, variant = "page", className }: GateWrapperProps) {
return <div className={cx(VARIANT_CLASSES[variant], className)}>{children}</div>;
}
Add this block to your project
CLI
npx shadcn@latest add http://localhost:3000/r/react/gate-wrapper.jsonRunning this site somewhere other than localhost? Set NEXT_PUBLIC_SITE_URL and this command switches to that host automatically.
Also installs
- cx (classname helper)
Files created (2)
- components/knock-codes/react/cx.ts
- components/knock-codes/react/GateWrapper.tsx
No CLI? Copy the files by hand
- Open the Code tab in the preview above.
- Create each path listed below in your project and paste its contents in.
- Do the same for anything listed under “Also installs”, if present.
→ Props
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
| children * | ReactNode | — | Content to position. |
| variant | "page" | "inline" | "page" | "page" centers full-height (min-h-100dvh); "inline" flows naturally in place. |
| className | string | — | Extra classes on the wrapper. |
Accessibility
Purely structural — a single div with positioning classes. No semantics of its own to get wrong.
Customization
Use it directly when none of the other blocks' visual shells fit — wrap your own fully custom access-code form in it to get the same full-page-centered or inline placement every other block uses, for free.
→ 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.