Skip to main content

<CaptchaWidget>

Solves a captcha challenge against the provider's configured altchaBaseUrl and makes the solution available to the next captcha-gated request automatically. Solutions are single-use — the widget flips back to idle after the SDK consumes one, and a new solve is required for the next captcha-gated call.

Powered by Altcha.

Import

import { CaptchaWidget } from "@feelrift/react";

Basic usage

import {
CaptchaWidget,
ReserveButton,
RiftEvent,
RiftProvider,
} from "@feelrift/react";

<RiftProvider>
<RiftEvent eventId="evt_summerfest_2026">
<CaptchaWidget />
<ReserveButton requireCaptcha />
</RiftEvent>
</RiftProvider>;

No configuration required — the widget reaches the production Altcha challenge endpoint by default and the SDK attaches solved payloads to the next captcha-gated request.

Props

Accepts all HTMLAttributes<HTMLDivElement> (except children — see below) plus:

NameTypeRequiredDefaultDescription
asChildbooleanNofalseSwap the root element via Radix Slot.
childrenReactNode | ((args: { status, solution, verify, reset }) => ReactNode)NoReplace the default rendering. Function form receives live solver state.
verifyLabelReactNodeNot("captcha.actionVerify")One-off label for the verify button in idle/error state.
autoVerifybooleanNofalseSolve on mount instead of waiting for a click. Pair with asChild's hidden slot for invisible-mode usage.
classNamestringNoAppended to the SDK's rift-captcha-widget class.
…restHTMLAttributes<HTMLDivElement>NoForwarded to the root element.

children

Two forms:

  • JSX child — replaces the default verify/status UI.
  • Function child — receives { status, solution, verify, reset } and returns whatever you want. Use for custom visual treatments (a sticker on a button, an inline progress bar, etc.) while keeping the SDK's solution wiring.

autoVerify

When true, the widget invokes verify() on mount whenever the status is idle (no solution + not solving + no error). Useful for invisible-mode setups paired with asChild and an aria-hidden placeholder. Re-fires after a captcha-gated request clears the previous solution.

Render output

Wraps content in <div class="rift-captcha-widget rift-captcha-widget--{status}"> where {status} is one of idle, solving, solved, error.

Default inside:

  • Indicator ( / / )
  • Status label
  • Verify or Retry button (in idle / error)
  • Error row (when status is error)

Behavior

  • Single-use solution. The SDK consumes the stored solution after every captcha-tagged request (success or failure). The widget flips back to idle when the solution is cleared.
  • Status derivation. idle vs solved derives from whether a solution is present (the source of truth). solving and error are transient local state during a verify() in flight.
  • Pre-flight errors. If a mutating request fires while no solution is present, the SDK throws RiftApiError({ code: "captcha_unavailable", status: 0 }) before the request leaves the client. The widget itself doesn't surface this — <ReserveButton> / <CheckoutForm> handle it, or your custom handler should.
  • Error UI. When solving rejects, the widget enters the error status with the thrown message visible. Clicking Retry re-attempts.

Examples

Default

import { CaptchaWidget, ReserveButton } from "@feelrift/react";

<CaptchaWidget />
<ReserveButton requireCaptcha />;

That's it. The widget targets the provider's configured altchaBaseUrl; no consumer setup required.

Invisible mode (auto-solve, hidden UI)

<CaptchaWidget autoVerify asChild>
<div aria-hidden style={{ position: "absolute", visibility: "hidden" }} />
</CaptchaWidget>

Custom render via function children

<CaptchaWidget>
{({ status, verify }) =>
status === "solved" ? (
<span className="text-success">✓ Verified</span>
) : (
<button onClick={verify} disabled={status === "solving"}>
{status === "solving" ? "Verifying…" : "Verify you're human"}
</button>
)
}
</CaptchaWidget>

Reset on user action

function ResetButton() {
const { setSolution } = useCaptcha();
return <button onClick={() => setSolution(null)}>Reset captcha</button>;
}