Pin Input
Enter a short code across coordinated single-character fields.
Usage
Verification code
Enter a short numeric verification code one segment at a time.
Enter a short numeric verification code one segment at a time.
<!-- Pin Input / Verification Code -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
</script>
<template>
<PinInputRoot :length="6" label="Verification code">
<PinInputInput v-for="index in 6" :key="index" :index="index - 1" />
</PinInputRoot>
</template>Custom length
Set the number of input cells to match the code format required by the service.
Set the number of input cells to match the code format required by the service.
<!-- Pin Input / Custom Length -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
</script>
<template>
<PinInputRoot :length="4" label="Four-digit PIN">
<PinInputInput v-for="index in 4" :key="index" :index="index - 1" />
</PinInputRoot>
</template>Masked input
Hide entered characters when the code should not remain visible on screen.
Hide entered characters when the code should not remain visible on screen.
<!-- Pin Input / Masked -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
</script>
<template>
<PinInputRoot :length="6" mask label="Security code">
<PinInputInput v-for="index in 6" :key="index" :index="index - 1" />
</PinInputRoot>
</template>Cell placeholders
Pass a placeholder to each input cell without storing it as part of the value.
Pass a placeholder to each input cell without storing it as part of the value.
<!-- Pin Input / Placeholders -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
</script>
<template>
<PinInputRoot :length="6" label="Access code">
<PinInputInput
v-for="index in 6"
:key="index"
:index="index - 1"
placeholder="○"
/>
</PinInputRoot>
</template>OTP autocomplete
Opt in to one-time-code autocomplete for a value that is intentionally an OTP.
Opt in to one-time-code autocomplete for a value that is intentionally an OTP.
<!-- Pin Input / Otp -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
</script>
<template>
<PinInputRoot :length="6" :otp="true" label="One-time code">
<PinInputInput v-for="index in 6" :key="index" :index="index - 1" />
</PinInputRoot>
</template>Readonly
Remain focusable for inspection while rejecting every mutation request.
Remain focusable for inspection while rejecting every mutation request.
<!-- Pin Input / Readonly -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
</script>
<template>
<PinInputRoot :length="6" default-value="246810" readonly label="Assigned code">
<PinInputInput v-for="index in 6" :key="index" :index="index - 1" />
</PinInputRoot>
</template>Disabled
Remove the control from keyboard and pointer interaction.
Remove the control from keyboard and pointer interaction.
<!-- Pin Input / Disabled -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
</script>
<template>
<PinInputRoot :length="6" default-value="593174" disabled label="Unavailable code">
<PinInputInput v-for="index in 6" :key="index" :index="index - 1" />
</PinInputRoot>
</template>Controlled
Let the parent own the current value and apply accepted changes back to the component.
Let the parent own the current value and apply accepted changes back to the component.
<!-- Pin Input / Controlled -->
<script setup lang="ts">
import { PinInputRoot, PinInputInput } from '@sectile/vue/pin-input'
import { ref } from 'vue'
const value = ref('')
</script>
<template>
<PinInputRoot v-model="value" :length="6" label="Controlled code">
<PinInputInput v-for="index in 6" :key="index" :index="index - 1" />
</PinInputRoot>
<p>Current value: {{ value || 'Empty' }}</p>
</template>API
Vue package: @sectile/vue/pin-input
PinInputRootPinInputInput
Props
PinInputRootProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
defaultValueInitial value used when the component owns its state.
disabledWhether interaction is unavailable.
formID of the native form associated with the control.
labelAccessible name announced for the control.
lengthNumber of coordinated character inputs.
maskWhether entered characters use password-style masking.
modelValueCurrent value when state is controlled by the parent.
nameName used for native form submission.
otpWhether to opt the first input into one-time-code autocomplete.
policiesBehavior policies that customize validation, movement, or selection.
readonlyWhether the value can be inspected but not changed.
requiredWhether the control must contain a valid value before submission.
PinInputInputProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
indexZero-based position of this part in its parent collection.
Slots
PinInputRootSlotProps
completeWhether every required character or step is complete.
disabledWhether interaction is unavailable.
readonlyWhether the value can be inspected but not changed.
valueCurrent value exposed by this contract.
PinInputInputSlotProps
characterCharacter displayed by this input.
completeWhether every required character or step is complete.
disabledWhether interaction is unavailable.
indexZero-based position in the parent collection.
readonlyWhether the value can be inspected but not changed.
valueCurrent value exposed by this contract.
Events
PinInputRoot
completeEmitted when every required segment is filled.
update:modelValueEmitted when the component requests a new controlled value.
Other types
PinInputValueChangeHandler
type PinInputValueChangeHandler = (value: string) => voidPinInputCompleteHandler
type PinInputCompleteHandler = (value: string) => voidParts
Shared scope: [data-scope="pin-input"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
root | [data-part="root"] | Defines the component boundary and owns its composed parts. | — |
input | [data-part="input"] | Accepts the editable value or draft. | — |
Keyboard interaction
| Key | Behavior |
|---|---|
| Arrow Left / Arrow Right | Move between digit inputs. |
| Backspace / Delete | Clear a digit and preserve the expected cursor movement. |
| Text input | Accept valid characters and advance when the field is complete. |
Accessibility
Each digit input has an independent accessible name and preserves a predictable focus order.
