HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Loading the reference
Pin InputView SourceEdit in SandboxView MarkdownCopy MarkdownOpen in ClaudeOpen in CursorA field for a short code, with one box for each character.StableSince 0.1.0FormsUsageimport'@fusion.dev/helix/pin-input'import'@fusion.dev/helix-headless/pin-input'Preview
API ReferenceRoothelix-pin-inputA field for a short code, with one box for each character.
PropTypeDescriptionautocompletestringDefault"one-time-code"The autofill hint for the browser. one-time-code is why this defaults to
anything at all: it is the token that lets a phone offer the code out of a
message.autosubmitbooleanDefaultfalseWhether the form is submitted once the last box is filled, as Web
Awesome's autosubmit and Radix's autoSubmit. The boxes fill from a
code the field takes, or from a value you write back after refusing the
edit. A refused last character with nothing written back submits nothing.case"lower"|"preserve"|"upper"Default"preserve"How typed and pasted letters are cased: upper, lower, or preserve
to keep them as typed. Web Awesome's OTP input takes the same case, for
a code a service reads in one case.cellLabelstringDefault"Character {index} of {length}"The name each box once had, with {index} and {length} filled in.defaultValuestringDefault""The value the control starts with. A form reset returns it to this value,
and to the value attribute where this one is not written, as a native
control resets to the value it declares.disabledbooleanDefaultfalseWhether the control is disabled and cannot be used.feedbackstringDefault""The validation message shown under the control. It replaces the
browser's message.formatstringDefault""Separators drawn between the boxes: # or * for a box and anything
else as it is written, so ###-### draws a dash after the third. The
separators are hidden from screen readers and are not part of the value.hintstringDefault""Help text shown under the control. A validation message replaces it.labelstringDefault""The field's label, which is also its accessible name. Content in the
label slot replaces it.lengthnumberDefault6How many characters the code has.maskbooleanDefaultfalseWhether the characters are hidden, the way a password is. The field is a
password field, and each filled box draws mask-character.maskCharacterstringDefault"•"What a filled box draws under mask, in place of its character, as Web
Awesome's --mask-char.namestringDefault""The name the control's value is submitted under.placeholderstringDefault""What an empty box shows, usually a single dot. It is not shown in the box
the caret is in. Empty by default, because a row of boxes already reads as
a row of boxes.readOnlybooleanDefaultfalseWhether the field blocks input. A read-only code still submits its value.requiredbooleanDefaultfalseWhether the field needs a value before the form can submit.tooShortMessagestringDefault"{length, plural, one {Please enter the # character.} other {Please enter all # characters.}}"The message shown when the code is started and not finished. {length}
is how many characters the code has, written in the locale, and each
language writes the forms it has.type"alphanumeric"|"numeric"|"text"Default"numeric"The characters a box accepts, which also sets the keyboard a phone shows.valuestringThe control's current value, which its form submits.valueMissingMessagestringThe message shown when the field is required and empty.
ReadTypeDescriptionformHTMLFormElement|nullThe form the control belongs to, or null.labelsNodeListThe labels associated with the control.validationMessagestringThe message the browser would show for the control, or an empty string.validityValidityStateWhether the control meets its constraints, and why not.whenSettledPromise<void>Resolves a frame after the first update, when transitions are switched on.willValidatebooleanWhether the control is checked when its form is submitted.
SlotDescriptionfeedbackThe message that says what is wrong, for content richer than a string. It shows while there is a message.hintHelp under the control, for content richer than the hint text.labelThe label, for content richer than the label text.
EventTypeDescriptionchangeEventThe code was filled, or an edited code lost focus.helix-before-changeHelixBeforeChangeEventThe code is about to change. Cancelable.helix-completeHelixCompleteEventThe last box was filled.inputEventThe code changed.
MethodTypeDescriptioncheckValidity() => booleanReturns whether the control is valid, and fires invalid on it when it is
not. The control shows no message for it: reportValidity() does that.clear() => voidEmpties every box and puts the caret in the first.focus(options: FocusOptions) => voidMoves focus to the control, as focusing a native control does.reportValidity() => booleanReturns whether the control is valid, and when it is not, fires invalid
and shows the browser's message at the control.requestValue(next: string) => booleanRequests a new value, and returns whether the change was applied.setCustomValidity(message: string) => voidMarks the control invalid with message, or clears that with an empty
string, as on a native control. The form does not submit while it is set.
PartDescriptioncaretThe caret, drawn in the empty box it is in while the field has focus.cellOne box.cell-activeThe box the caret is in, while the field has focus. Set together with cell.cell-filledA box that holds a character. Set together with cell.controlThe one field that holds the code, out of sight: the boxes are drawn from it.feedbackThe message that says what is wrong with the code.fieldThe row of boxes.hintThe help under the boxes, shown while there is no feedback.labelThe label above the boxes.placeholderThe placeholder text in an empty box.separatorThe text format draws between two boxes.
CSS PropertyDescription--pin-input-caret-colorThe color of the caret drawn in an empty box. Without it, the character color applies.--pin-input-cell-background-colorFill behind each box.--pin-input-cell-border-colorEdge of each box at rest. Hover, focus and an error still draw their own.--pin-input-cell-border-color-focusEdge of the box the caret is in.--pin-input-cell-colorThe color of a typed character.--pin-input-cell-font-sizeThe size of a typed character.--pin-input-cell-radiusCorner radius of each box.--pin-input-cell-sizeWidth and height of each box.--pin-input-gapThe space between one box and the next.--pin-input-placeholder-colorThe color of the placeholder text in an empty box.--pin-input-separator-colorThe color of the text format draws between boxes.
Custom stateDescriptioncompleteEvery box holds a character.invalidThe control has an error to show, from the browser's validation or from your feedback.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Roothelix-headless-pin-inputA field for a short code, with one box for each character.
PropTypeDescriptionautocompletestringDefault"one-time-code"The autofill hint for the browser. one-time-code is why this defaults to
anything at all: it is the token that lets a phone offer the code out of a
message.autosubmitbooleanDefaultfalseWhether the form is submitted once the last box is filled, as Web
Awesome's autosubmit and Radix's autoSubmit. The boxes fill from a
code the field takes, or from a value you write back after refusing the
edit. A refused last character with nothing written back submits nothing.case"lower"|"preserve"|"upper"Default"preserve"How typed and pasted letters are cased: upper, lower, or preserve
to keep them as typed. Web Awesome's OTP input takes the same case, for
a code a service reads in one case.cellLabelstringDefault"Character {index} of {length}"The name each box once had, with {index} and {length} filled in.defaultValuestringDefault""The value the control starts with. A form reset returns it to this value,
and to the value attribute where this one is not written, as a native
control resets to the value it declares.disabledbooleanDefaultfalseWhether the control is disabled and cannot be used.feedbackstringDefault""The validation message shown under the control. It replaces the
browser's message.formatstringDefault""Separators drawn between the boxes: # or * for a box and anything
else as it is written, so ###-### draws a dash after the third. The
separators are hidden from screen readers and are not part of the value.hintstringDefault""Help text shown under the control. A validation message replaces it.labelstringDefault""The field's label, which is also its accessible name. Content in the
label slot replaces it.lengthnumberDefault6How many characters the code has.maskbooleanDefaultfalseWhether the characters are hidden, the way a password is. The field is a
password field, and each filled box draws mask-character.maskCharacterstringDefault"•"What a filled box draws under mask, in place of its character, as Web
Awesome's --mask-char.namestringDefault""The name the control's value is submitted under.placeholderstringDefault""What an empty box shows, usually a single dot. It is not shown in the box
the caret is in. Empty by default, because a row of boxes already reads as
a row of boxes.readOnlybooleanDefaultfalseWhether the field blocks input. A read-only code still submits its value.requiredbooleanDefaultfalseWhether the field needs a value before the form can submit.tooShortMessagestringDefault"{length, plural, one {Please enter the # character.} other {Please enter all # characters.}}"The message shown when the code is started and not finished. {length}
is how many characters the code has, written in the locale, and each
language writes the forms it has.type"alphanumeric"|"numeric"|"text"Default"numeric"The characters a box accepts, which also sets the keyboard a phone shows.valuestringThe control's current value, which its form submits.valueMissingMessagestringThe message shown when the field is required and empty.
ReadTypeDescriptionformHTMLFormElement|nullThe form the control belongs to, or null.labelsNodeListThe labels associated with the control.validationMessagestringThe message the browser would show for the control, or an empty string.validityValidityStateWhether the control meets its constraints, and why not.whenSettledPromise<void>Resolves a frame after the first update, when transitions are switched on.willValidatebooleanWhether the control is checked when its form is submitted.
SlotDescriptionfeedbackThe message that says what is wrong, for content richer than a string. It shows while there is a message.hintHelp under the control, for content richer than the hint text.labelThe label, for content richer than the label text.
EventTypeDescriptionchangeEventThe code was filled, or an edited code lost focus.helix-before-changeHelixBeforeChangeEventThe code is about to change. Cancelable.helix-completeHelixCompleteEventThe last box was filled.inputEventThe code changed.
MethodTypeDescriptioncheckValidity() => booleanReturns whether the control is valid, and fires invalid on it when it is
not. The control shows no message for it: reportValidity() does that.clear() => voidEmpties every box and puts the caret in the first.focus(options: FocusOptions) => voidPuts the caret in the first empty box.reportValidity() => booleanReturns whether the control is valid, and when it is not, fires invalid
and shows the browser's message at the control.requestValue(next: string) => booleanRequests a new value, and returns whether the change was applied.setCustomValidity(message: string) => voidMarks the control invalid with message, or clears that with an empty
string, as on a native control. The form does not submit while it is set.
PartDescriptioncaretThe caret, drawn in the empty box it is in while the field has focus.cellOne box.cell-activeThe box the caret is in, while the field has focus. Set together with cell.cell-filledA box that holds a character. Set together with cell.controlThe one field that holds the code, out of sight: the boxes are drawn from it.feedbackThe message that says what is wrong with the code.fieldThe row of boxes, ordered left to right in every language.hintThe help under the boxes, shown while there is no feedback.labelThe label above the boxes.placeholderThe placeholder text in an empty box.separatorThe text format draws between two boxes.
Custom stateDescriptioncompleteEvery box holds a character.invalidThe control has an error to show, from the browser's validation or from your feedback.settledSet one frame after the first render. Transitions wait for it, so an element does not animate its own arrival.
Examples
NameDescriptionCompleteThe boxes advance as you type, and the last one completes the code.DisabledA disabled pin input.EventsThe events a pin input sends as you type, including helix-complete when the last box is filled.InvalidAn unfinished code with a message set by feedback.Length And TypeA four-digit code, and a six-character code of letters and digits.MaskedA code whose characters are hidden as you type, for a secret code.PreviewA code across separate boxes, one character each.PreviewA code across separate boxes, one character each.Read OnlyA read-only code, shown for you to read. It can still be selected and is still announced.