Loading page…
Loading page…
Sensitive actions get one method at a time: registered passkey first, then OTP, then password. A failed attempt reveals Try another way and animates to the next configured method. Complete OTP input submits automatically.
One semantic text input owns the keyboard, clipboard, and OS autofill contract while the six visible cells remain presentational. Arrow keys move the active cell; Backspace/Delete edit in place; a pasted or suggested full code fills all slots without a second input event.
Type, paste, or choose the code offered by your device.
Type six digits, paste a code, or use your device's one-time-code suggestion.
Code verified.
That code has expired. Request another.
External verification owns the error and success state.
import { OTPInput } from "@coldharbor/webui";
<OTPInput
name="one-time-code"
value={code}
onChange={setCode}
onComplete={verifyCode}
autoFocus
/>
// The native input includes:
// type="text" inputMode="numeric" autoComplete="one-time-code"--ch-bg--ch-surface--ch-border--ch-fg--ch-fg-muted--ch-primary--ch-accent--ch-danger--ch-success--ch-focusConfigured methods are normalized to passkey → OTP → password. Fallback stays hidden until the current method fails. The inverted sheet cannot be dismissed by backdrop, Escape, or swipe; Cancel action remains the only unauthenticated exit.
Demo credentials
OTP 141712 · password privateer
No action pending.
Demo passkey fails so Try another way appears. OTP is 141712; password is privateer.
import { StepUpAuthGate } from "@coldharbor/webui";
<StepUpAuthGate
open={gateOpen}
onOpenChange={setGateOpen}
title="Authorize transfer"
description="Authenticate before signing this transfer."
methods={["passkey", "otp", "password"]}
onPasskey={(signal) => verifyPasskey({ signal })}
onVerifyOtp={(code, signal) => verifyOtp(code, { signal })}
onVerifyPassword={(password, signal) => verifyPassword(password, { signal })}
onAuthenticated={() => signTransfer()}
onCancel={() => cancelTransfer()}
/>--ch-bg--ch-surface--ch-border--ch-fg--ch-fg-muted--ch-primary--ch-accent--ch-danger--ch-success--ch-focus