The code so far (controlled). Shorter than length = partially filled.
groupLabel *
string
n/a
Accessible name for the whole row. Each cell derives digit N of M from it.
onValueChange
(value: string) => void
n/a
Fires on every keystroke / paste with the full string so far.
onComplete
(value: string) => void
n/a
Fires once the final cell is filled, the hook for server-side verification.
length
number
6
Number of single-character cells (e.g. 4 or 6).
status
'idle' | 'validating' | 'error' | 'success'
'idle'
Drives the cell border, the trailing glyph, and the message tone. error shakes (reduced-motion freezes it).
message
string
n/a
The single line under the row (helper / error / success). Wired via aria-describedby; live region.
groupAfter
number
n/a
Insert a centered separator after this many cells (e.g. 3 → a 3·3 grouped code).
mask
boolean
false
Render each filled cell as a dot (a password-style passcode).
numeric
boolean
true
Restrict to digits: sets inputMode="numeric" and strips non-digits.
disabled
boolean
false
Inert and clearly seen (never faded to invisible).
No packaged NockerlOtpInput ships yet. These are the parameters of the real
building block (OutlinedTextField per cell) that the idiom above composes, plus the
state a future component would own.
Parameter
Type
Default
Description
value *
String
n/a
The single character for this cell (code.getOrNull(i)).
onValueChange *
(String) -> Unit
n/a
Per-cell change; filter to one digit and focusManager.moveFocus(Next) to auto-advance.
shape
Shape
NockerlControlShape
The shared 12dp control radius. Read the token, never a raw RoundedCornerShape(n).
keyboardOptions
KeyboardOptions
NumberPassword + Next
Numeric keypad; imeAction = Next on all but the last cell (Done).
isError
Boolean
false
Recolors the border via colorScheme.error + drives the supporting caption.
enabled
Boolean
true
When false, the cell is dimmed (alpha) and non-interactive.
modifier
Modifier
Modifier.width(48.dp)
Per-cell width so the row stays evenly spaced.
Not implemented in Nockerl Voice. This is the proposedNockerlOtpInput API,
designed from the field + validation vocabulary, not a shipped signature.
Style
Type
Default
Description
code *
Binding<String>
n/a
Two-way binding to the entered code (controlled).
length
Int
6
Number of cells.
groupLabel *
String
n/a
Accessibility label for the group; each cell exposes its index.
Called when the final cell fills, the verification hook.
Cross-platform drift (tracked for reconciliation)
The web demo is the reference; this component is designed originally from the
recessed-well field + the validation message vocabulary, because neither shipped app
has a formal OTP / segmented-code input yet:
Android: no NockerlOtpInput; the closest real code entry is LoginScreen’s
OutlinedTextField with imeAction = Next + focusManager.moveFocus (the
auto-advance idiom the Kotlin sample reuses). The only “pairing” is FlicPairingFlow
(BLE button, no digit entry).
Swift / Voice:not implemented at all: no verification-code or
device-pairing UI ships. The Swift API above is a proposal, not a shipped signature.
Mono digit: the cell glyph uses font.family.mono so a code reads as code. The
apps don’t yet expose a mono type role (Android Type.kt is all one sans family).
Promote one when a platform implements this.
One implementation needs to win: when Android/Voice build this, the segmented
layout, paste-to-fill, and backspace-to-previous model defined here should be the
shared contract rather than a per-platform re-derivation.