Krizaka UI
Krizaka UI
Components

Captcha

The bot check of a public form: Cloudflare Turnstile that shows nothing to a normal visitor, a framed box on the tokens only when a challenge needs them, and an accessible error with a retry.

Web · ✓Mobile · n/aDesktop · ✓BetaForms
import { Captcha, CaptchaDisclosure } from "@krizaka/ui/captcha";

Web only — React, from @krizaka/ui/captcha. Beta: its API may still change in a minor version.

  • Mobile · n/a. Turnstile is a web widget; a phone app proves itself with its own session.

Why it is here. krizaka.com's contact form and the blog's newsletter form (the public forms, behind Cloudflare Turnstile).

When to use

  • A public form anyone can post (contact, newsletter, sign-up) that the server verifies with Turnstile's siteverify.
  • When the check must not weigh on the page: it runs in the background and appears only if Cloudflare asks.

When not to use

  • A signed-in action: the session already proves who acts.
  • A confirmation of a destructive action.Use instead: Confirm button

Installation

Install

npm install @krizaka/ui @krizaka/tailwind @krizaka/tokens tailwindcss

Styles

@import "tailwindcss";
@import "@krizaka/tailwind";
@import "@krizaka/ui/tailwind.css";

Import

import { Captcha, CaptchaDisclosure } from "@krizaka/ui/captcha";

Examples

A form with its check

The submit waits for the token; the disclosure sits under it.

The disclosure line

« Protected by Cloudflare Turnstile · Privacy · Terms », in English or French.

Props

Captcha

The bot check of a public form, Cloudflare Turnstile that stays out of the way: managed mode with appearance: "interaction-only", so a normal visitor sees nothing — the check runs in the background and onToken fires. Only when Cloudflare needs the visitor does a framed box appear, on the tokens (radius, border, theme). If the check cannot run, an alert with a retry button replaces it. Pair it with CaptchaDisclosure under the submit.

PropTypeDefaultDescription
onTokenrequired(token: string | null) => void—The token once the check passes; null when it expires, fails or the theme redraws the widget.
siteKeyrequiredstring—The widget's public site key. Empty → nothing is rendered and no token is asked (local dev, tests).
classNamestring—Classes added to the root.
labelsPartial<CaptchaLabels>—Words to say otherwise; the rest comes from the locale.
localestringenThe language of the widget and of the words: "en", "fr"…
theme"auto" | "light" | "dark"autoauto follows the page (html.light / data-theme, redrawn when it flips).

CaptchaDisclosure

« Protected by Cloudflare Turnstile · Privacy · Terms »: the line Cloudflare's terms ask for under the submit button.

PropTypeDefaultDescription
classNamestring—Classes added to the root.
labelsPartial<CaptchaLabels>—Words to say otherwise; the rest comes from the locale.
localestringenThe language of the line: "en", "fr"…
privacyHrefstringhttps://www.cloudflare.com/privacypolicy/The privacy link; Cloudflare's privacy policy by default.
termsHrefstringhttps://www.cloudflare.com/website-terms/The terms link; Cloudflare's website terms by default.

Accessibility

  • The widget sits in a group named by labels.group; a failure is announced as an alert, with a button to try again.
  • The disclosure links open in a new tab with rel="noopener noreferrer".

Keyboard

KeysAction
TabReaches the Cloudflare challenge when it shows, and the Try again button on error.

Best practices

  • Verify the token on the server and fail closed: a missing or refused token is a 400, whatever the browser says.
  • Put CaptchaDisclosure under the submit button: Cloudflare's terms ask for the privacy and terms links when the widget is hidden.
  • Disable the submit while onToken has not given a token, and remount the component (key) after a refused token.
  • Pass the site's locale; the theme follows the page (html.light or data-theme) and redraws when it flips.

Generated from the code of @krizaka/ui 3.63.1: its meta.ts, its examples and its types.Edit this documentation on GitHub

On this page